From 1c74da5ab72b9c1d4a134e74ba430f6d1af23aec Mon Sep 17 00:00:00 2001 From: Filip Dabrowski <filip.dabrowski@theaa.com> Date: Thu, 12 Jul 2018 17:01:43 +0100 Subject: [PATCH 1/6] Add SASS support --- .../config/webpack.config.dev.js | 39 ++++++++++++++ .../config/webpack.config.prod.js | 54 +++++++++++++++++++ packages/react-scripts/package.json | 3 +- 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 924e3e4f0..6ed8feea9 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -188,6 +188,7 @@ module.exports = { // "style" loader turns CSS into JS modules that inject <style> tags. // In production, we use a plugin to extract that CSS to a file, but // in development "style" loader enables hot editing of CSS. + // SASS/SCSS supported. { test: /\.css$/, use: [ @@ -220,6 +221,44 @@ module.exports = { }, ], }, + { + test: /\.scss$/, + use: [ + require.resolve('style-loader'), + { + loader: require.resolve('css-loader'), + options: { + importLoaders: 1, + }, + }, + { + loader: require.resolve('postcss-loader'), + options: { + // Necessary for external CSS imports to work + // https://github.com/facebookincubator/create-react-app/issues/2677 + ident: 'postcss', + plugins: () => [ + require('postcss-flexbugs-fixes'), + autoprefixer({ + browsers: [ + '>1%', + 'last 4 versions', + 'Firefox ESR', + 'not ie < 9', // React doesn't support IE8 anyway + ], + flexbox: 'no-2009', + }), + ], + }, + }, + { + loader: require.resolve('sass-loader'), + options: { + importLoaders: 1, + }, + }, + ], + }, // "file" loader makes sure those assets get served by WebpackDevServer. // When you `import` an asset, you get its (virtual) filename. // In production, they would get copied to the `build` folder. diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 7cb33afd0..1a9238579 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -200,6 +200,7 @@ module.exports = { // tags. If you use code splitting, however, any async bundles will still // use the "style" loader inside the async code so CSS from them won't be // in the main CSS file. + // SASS/SCSS supported. { test: /\.css$/, loader: ExtractTextPlugin.extract( @@ -247,6 +248,59 @@ module.exports = { ), // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. }, + { + test: /\.scss$/, + loader: ExtractTextPlugin.extract( + Object.assign( + { + fallback: { + loader: require.resolve('style-loader'), + options: { + hmr: false, + }, + }, + use: [ + { + loader: require.resolve('css-loader'), + options: { + importLoaders: 1, + minimize: true, + sourceMap: shouldUseSourceMap, + }, + }, + { + loader: require.resolve('postcss-loader'), + options: { + // Necessary for external CSS imports to work + // https://github.com/facebookincubator/create-react-app/issues/2677 + ident: 'postcss', + plugins: () => [ + require('postcss-flexbugs-fixes'), + autoprefixer({ + browsers: [ + '>1%', + 'last 4 versions', + 'Firefox ESR', + 'not ie < 9', // React doesn't support IE8 anyway + ], + flexbox: 'no-2009', + }), + ], + }, + }, + { + loader: require.resolve('sass-loader'), + options: { + importLoaders: 1, + }, + }, + ], + }, + extractTextPluginOptions + ) + ), + // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. + }, // "file" loader makes sure assets end up in the `build` folder. // When you `import` an asset, you get its filename. // This loader doesn't use a "test" so it will catch all modules diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 95bf68c2a..6719ae0c9 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -41,9 +41,10 @@ "postcss-loader": "2.0.8", "promise": "8.0.1", "raf": "3.4.0", - "source-map-loader": "^0.2.1", "react-dev-utils": "^5.0.1", "resolve": "1.6.0", + "sass-loader": "^7.0.3", + "source-map-loader": "^0.2.1", "style-loader": "0.19.0", "sw-precache-webpack-plugin": "0.11.4", "ts-jest": "22.0.1", From cb96b560415aa17390c0cdb5755b4ffea1f40f61 Mon Sep 17 00:00:00 2001 From: Filip Dabrowski <filip.dabrowski@theaa.com> Date: Fri, 13 Jul 2018 14:23:39 +0100 Subject: [PATCH 2/6] Add node-sass dependency --- packages/react-scripts/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 6719ae0c9..bde811b88 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -36,6 +36,7 @@ "fs-extra": "3.0.1", "html-webpack-plugin": "2.29.0", "jest": "22.4.2", + "node-sass": "^4.9.2", "object-assign": "4.1.1", "postcss-flexbugs-fixes": "3.2.0", "postcss-loader": "2.0.8", From c6e7aaaa2697622a12d9b8eb63377adae2884644 Mon Sep 17 00:00:00 2001 From: Filip Dabrowski <fifofil@gmail.com> Date: Tue, 17 Jul 2018 14:35:27 +0100 Subject: [PATCH 3/6] Replace node-sass with node-sass-chokidar --- packages/react-scripts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index bde811b88..60a881288 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -36,7 +36,7 @@ "fs-extra": "3.0.1", "html-webpack-plugin": "2.29.0", "jest": "22.4.2", - "node-sass": "^4.9.2", + "node-sass-chokidar": "1.3.0", "object-assign": "4.1.1", "postcss-flexbugs-fixes": "3.2.0", "postcss-loader": "2.0.8", From cd704af753bc5bc748e8e2076fa73af2adaa6fbc Mon Sep 17 00:00:00 2001 From: John Rom <john@nimblelight.com> Date: Fri, 28 Sep 2018 12:48:50 -0400 Subject: [PATCH 4/6] Update webpack config to use real create-react-app 2.0 SASS config --- .../config/webpack.config.dev.js | 141 +++++++------ .../config/webpack.config.prod.js | 198 ++++++++---------- 2 files changed, 167 insertions(+), 172 deletions(-) diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 6ed8feea9..a649f380c 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -31,6 +31,47 @@ const publicUrl = ''; // Get environment variables to inject into our app. const env = getClientEnvironment(publicUrl); + // style files regexes +const cssRegex = /\.css$/; +const cssModuleRegex = /\.module\.css$/; +const sassRegex = /\.(scss|sass)$/; +const sassModuleRegex = /\.module\.(scss|sass)$/; + + // common function to get style loaders +const getStyleLoaders = (cssOptions, preProcessor) => { + const loaders = [ + require.resolve('style-loader'), + { + loader: require.resolve('css-loader'), + options: cssOptions, + }, + { + // Options for PostCSS as we reference these options twice + // Adds vendor prefixing based on your specified browser support in + // package.json + loader: require.resolve('postcss-loader'), + options: { + // Necessary for external CSS imports to work + // https://github.com/facebook/create-react-app/issues/2677 + ident: 'postcss', + plugins: () => [ + require('postcss-flexbugs-fixes'), + require('postcss-preset-env')({ + autoprefixer: { + flexbox: 'no-2009', + }, + stage: 3, + }), + ], + }, + }, + ]; + if (preProcessor) { + loaders.push(require.resolve(preProcessor)); + } + return loaders; +}; + // This is the development configuration. // It is focused on developer experience and fast rebuilds. // The production configuration is different and lives in a separate file. @@ -188,76 +229,46 @@ module.exports = { // "style" loader turns CSS into JS modules that inject <style> tags. // In production, we use a plugin to extract that CSS to a file, but // in development "style" loader enables hot editing of CSS. - // SASS/SCSS supported. + // By default we support CSS Modules with the extension .module.css { - test: /\.css$/, - use: [ - require.resolve('style-loader'), - { - loader: require.resolve('css-loader'), - options: { - importLoaders: 1, - }, - }, - { - loader: require.resolve('postcss-loader'), - options: { - // Necessary for external CSS imports to work - // https://github.com/facebookincubator/create-react-app/issues/2677 - ident: 'postcss', - plugins: () => [ - require('postcss-flexbugs-fixes'), - autoprefixer({ - browsers: [ - '>1%', - 'last 4 versions', - 'Firefox ESR', - 'not ie < 9', // React doesn't support IE8 anyway - ], - flexbox: 'no-2009', - }), - ], - }, - }, - ], + test: cssRegex, + exclude: cssModuleRegex, + use: getStyleLoaders({ + importLoaders: 1, + }), }, + // Adds support for CSS Modules (https://github.com/css-modules/css-modules) + // using the extension .module.css { - test: /\.scss$/, - use: [ - require.resolve('style-loader'), - { - loader: require.resolve('css-loader'), - options: { - importLoaders: 1, - }, - }, - { - loader: require.resolve('postcss-loader'), - options: { - // Necessary for external CSS imports to work - // https://github.com/facebookincubator/create-react-app/issues/2677 - ident: 'postcss', - plugins: () => [ - require('postcss-flexbugs-fixes'), - autoprefixer({ - browsers: [ - '>1%', - 'last 4 versions', - 'Firefox ESR', - 'not ie < 9', // React doesn't support IE8 anyway - ], - flexbox: 'no-2009', - }), - ], - }, - }, + test: cssModuleRegex, + use: getStyleLoaders({ + importLoaders: 1, + modules: true, + getLocalIdent: getCSSModuleLocalIdent, + }), + }, + // Opt-in support for SASS (using .scss or .sass extensions). + // Chains the sass-loader with the css-loader and the style-loader + // to immediately apply all styles to the DOM. + // By default we support SASS Modules with the + // extensions .module.scss or .module.sass + { + test: sassRegex, + exclude: sassModuleRegex, + use: getStyleLoaders({ importLoaders: 2 }, 'sass-loader'), + }, + // Adds support for CSS Modules, but using SASS + // using the extension .module.scss or .module.sass + { + test: sassModuleRegex, + use: getStyleLoaders( { - loader: require.resolve('sass-loader'), - options: { - importLoaders: 1, - }, + importLoaders: 2, + modules: true, + getLocalIdent: getCSSModuleLocalIdent, }, - ], + 'sass-loader' + ), }, // "file" loader makes sure those assets get served by WebpackDevServer. // When you `import` an asset, you get its (virtual) filename. diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 1a9238579..ddfb7dda2 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -44,8 +44,51 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') { throw new Error('Production builds must have NODE_ENV=production.'); } -// Note: defined here because it will be used more than once. -const cssFilename = 'static/css/[name].[contenthash:8].css'; +// style files regexes +const cssRegex = /\.css$/; +const cssModuleRegex = /\.module\.css$/; +const sassRegex = /\.(scss|sass)$/; +const sassModuleRegex = /\.module\.(scss|sass)$/;// common function to get style loaders + +const getStyleLoaders = (cssOptions, preProcessor) => { + const loaders = [ + MiniCssExtractPlugin.loader, + { + loader: require.resolve('css-loader'), + options: cssOptions, + }, + { + // Options for PostCSS as we reference these options twice + // Adds vendor prefixing based on your specified browser support in + // package.json + loader: require.resolve('postcss-loader'), + options: { + // Necessary for external CSS imports to work + // https://github.com/facebook/create-react-app/issues/2677 + ident: 'postcss', + plugins: () => [ + require('postcss-flexbugs-fixes'), + require('postcss-preset-env')({ + autoprefixer: { + flexbox: 'no-2009', + }, + stage: 3, + }), + ], + sourceMap: shouldUseSourceMap, + }, + }, + ]; + if (preProcessor) { + loaders.push({ + loader: require.resolve(preProcessor), + options: { + sourceMap: shouldUseSourceMap, + }, + }); + } + return loaders; +}; // ExtractTextPlugin expects the build output to be flat. // (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27) @@ -188,118 +231,59 @@ module.exports = { }, ], }, - // The notation here is somewhat confusing. // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. - // "style" loader normally turns CSS into JS modules injecting <style>, - // but unlike in development configuration, we do something different. - // `ExtractTextPlugin` first applies the "postcss" and "css" loaders - // (second argument), then grabs the result CSS and puts it into a - // separate file in our build process. This way we actually ship - // a single CSS file in production instead of JS code injecting <style> - // tags. If you use code splitting, however, any async bundles will still - // use the "style" loader inside the async code so CSS from them won't be - // in the main CSS file. - // SASS/SCSS supported. + // `MiniCSSExtractPlugin` extracts styles into CSS + // files. If you use code splitting, async bundles will have their own separate CSS chunk file. + // By default we support CSS Modules with the extension .module.css { - test: /\.css$/, - loader: ExtractTextPlugin.extract( - Object.assign( - { - fallback: { - loader: require.resolve('style-loader'), - options: { - hmr: false, - }, - }, - use: [ - { - loader: require.resolve('css-loader'), - options: { - importLoaders: 1, - minimize: true, - sourceMap: shouldUseSourceMap, - }, - }, - { - loader: require.resolve('postcss-loader'), - options: { - // Necessary for external CSS imports to work - // https://github.com/facebookincubator/create-react-app/issues/2677 - ident: 'postcss', - plugins: () => [ - require('postcss-flexbugs-fixes'), - autoprefixer({ - browsers: [ - '>1%', - 'last 4 versions', - 'Firefox ESR', - 'not ie < 9', // React doesn't support IE8 anyway - ], - flexbox: 'no-2009', - }), - ], - }, - }, - ], - }, - extractTextPluginOptions - ) + test: cssRegex, + exclude: cssModuleRegex, + loader: getStyleLoaders({ + importLoaders: 1, + sourceMap: shouldUseSourceMap, + }), + }, + // Adds support for CSS Modules (https://github.com/css-modules/css-modules) + // using the extension .module.css + { + test: cssModuleRegex, + loader: getStyleLoaders({ + importLoaders: 1, + sourceMap: shouldUseSourceMap, + modules: true, + getLocalIdent: getCSSModuleLocalIdent, + }), + }, + // Opt-in support for SASS. The logic here is somewhat similar + // as in the CSS routine, except that "sass-loader" runs first + // to compile SASS files into CSS. + // By default we support SASS Modules with the + // extensions .module.scss or .module.sass + { + test: sassRegex, + exclude: sassModuleRegex, + loader: getStyleLoaders( + { + importLoaders: 2, + sourceMap: shouldUseSourceMap, + }, + 'sass-loader' ), - // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. }, + // Adds support for CSS Modules, but using SASS + // using the extension .module.scss or .module.sass { - test: /\.scss$/, - loader: ExtractTextPlugin.extract( - Object.assign( - { - fallback: { - loader: require.resolve('style-loader'), - options: { - hmr: false, - }, - }, - use: [ - { - loader: require.resolve('css-loader'), - options: { - importLoaders: 1, - minimize: true, - sourceMap: shouldUseSourceMap, - }, - }, - { - loader: require.resolve('postcss-loader'), - options: { - // Necessary for external CSS imports to work - // https://github.com/facebookincubator/create-react-app/issues/2677 - ident: 'postcss', - plugins: () => [ - require('postcss-flexbugs-fixes'), - autoprefixer({ - browsers: [ - '>1%', - 'last 4 versions', - 'Firefox ESR', - 'not ie < 9', // React doesn't support IE8 anyway - ], - flexbox: 'no-2009', - }), - ], - }, - }, - { - loader: require.resolve('sass-loader'), - options: { - importLoaders: 1, - }, - }, - ], - }, - extractTextPluginOptions - ) + test: sassModuleRegex, + loader: getStyleLoaders( + { + importLoaders: 2, + sourceMap: shouldUseSourceMap, + modules: true, + getLocalIdent: getCSSModuleLocalIdent, + }, + 'sass-loader' ), - // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. }, // "file" loader makes sure assets end up in the `build` folder. // When you `import` an asset, you get its filename. From 9bbf3fb8a9ad34e3ef41d040ed4dd60acb7df850 Mon Sep 17 00:00:00 2001 From: John Rom <john@nimblelight.com> Date: Fri, 28 Sep 2018 13:32:15 -0400 Subject: [PATCH 5/6] Remove old file --- packages/react-scripts/package.json | 75 ----------------------------- 1 file changed, 75 deletions(-) delete mode 100644 packages/react-scripts/package.json diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json deleted file mode 100644 index 60a881288..000000000 --- a/packages/react-scripts/package.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "name": "react-scripts-ts", - "version": "2.16.0", - "description": "Configuration and scripts for Create React App.", - "repository": "wmonk/create-react-app", - "license": "BSD-3-Clause", - "engines": { - "node": ">=6" - }, - "bugs": { - "url": "https://github.com/wmonk/create-react-app/issues" - }, - "files": [ - "bin", - "config", - "scripts", - "template", - "utils" - ], - "bin": { - "react-scripts-ts": "./bin/react-scripts-ts.js" - }, - "dependencies": { - "autoprefixer": "7.1.6", - "babel-jest": "^22.1.0", - "babel-loader": "^7.1.2", - "babel-preset-react-app": "^3.1.1", - "case-sensitive-paths-webpack-plugin": "2.1.1", - "chalk": "1.1.3", - "css-loader": "0.28.7", - "dotenv": "4.0.0", - "dotenv-expand": "4.2.0", - "extract-text-webpack-plugin": "3.0.2", - "file-loader": "0.11.2", - "fork-ts-checker-webpack-plugin": "^0.2.8", - "fs-extra": "3.0.1", - "html-webpack-plugin": "2.29.0", - "jest": "22.4.2", - "node-sass-chokidar": "1.3.0", - "object-assign": "4.1.1", - "postcss-flexbugs-fixes": "3.2.0", - "postcss-loader": "2.0.8", - "promise": "8.0.1", - "raf": "3.4.0", - "react-dev-utils": "^5.0.1", - "resolve": "1.6.0", - "sass-loader": "^7.0.3", - "source-map-loader": "^0.2.1", - "style-loader": "0.19.0", - "sw-precache-webpack-plugin": "0.11.4", - "ts-jest": "22.0.1", - "ts-loader": "^2.3.7", - "tsconfig-paths-webpack-plugin": "^2.0.0", - "tslint": "^5.7.0", - "tslint-config-prettier": "^1.10.0", - "tslint-react": "^3.2.0", - "uglifyjs-webpack-plugin": "^1.1.8", - "url-loader": "0.6.2", - "webpack": "3.8.1", - "webpack-dev-server": "2.9.4", - "webpack-manifest-plugin": "1.3.2", - "whatwg-fetch": "2.0.3" - }, - "devDependencies": { - "react": "^15.5.4", - "react-dom": "^15.5.4", - "typescript": "^2.7.1" - }, - "peerDependencies": { - "typescript": "2.x" - }, - "optionalDependencies": { - "fsevents": "^1.1.3" - } -} From 4b6cab5c49cd49cdf06b8ad24f6ca0abec1d1bba Mon Sep 17 00:00:00 2001 From: John Rom <john@nimblelight.com> Date: Fri, 28 Sep 2018 16:27:48 -0400 Subject: [PATCH 6/6] small fixes --- config/webpack.config.dev.js | 8 ++++++-- config/webpack.config.prod.js | 8 ++++++-- package.json | 5 ++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index a649f380c..1b361ae5d 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -244,7 +244,9 @@ module.exports = { use: getStyleLoaders({ importLoaders: 1, modules: true, - getLocalIdent: getCSSModuleLocalIdent, + // TODO: This is in a future react-dev-utils version + // It should be enabled when react-dev-utils is updated + // getLocalIdent: getCSSModuleLocalIdent, }), }, // Opt-in support for SASS (using .scss or .sass extensions). @@ -265,7 +267,9 @@ module.exports = { { importLoaders: 2, modules: true, - getLocalIdent: getCSSModuleLocalIdent, + // TODO: This is in a future react-dev-utils + // It should be enabled when react-dev-utils is updated + // getLocalIdent: getCSSModuleLocalIdent, }, 'sass-loader' ), diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index cc04aa0a9..56f551c95 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -252,7 +252,9 @@ module.exports = { importLoaders: 1, sourceMap: shouldUseSourceMap, modules: true, - getLocalIdent: getCSSModuleLocalIdent, + // TODO: This is in a future react-dev-utils version + // It should be enabled when react-dev-utils is updated + // getLocalIdent: getCSSModuleLocalIdent, }), }, // Opt-in support for SASS. The logic here is somewhat similar @@ -280,7 +282,9 @@ module.exports = { importLoaders: 2, sourceMap: shouldUseSourceMap, modules: true, - getLocalIdent: getCSSModuleLocalIdent, + // TODO: This is in a future react-dev-utils version + // It should be enabled when react-dev-utils is updated + // getLocalIdent: getCSSModuleLocalIdent, }, 'sass-loader' ), diff --git a/package.json b/package.json index 092fd8790..4563d7227 100644 --- a/package.json +++ b/package.json @@ -36,14 +36,17 @@ "fs-extra": "3.0.1", "html-webpack-plugin": "2.29.0", "jest": "20.0.4", + "node-sass-chokidar": "^1.3.3", "object-assign": "4.1.1", "postcss-flexbugs-fixes": "3.2.0", "postcss-loader": "2.0.8", + "postcss-preset-env": "^6.0.7", "promise": "8.0.1", "raf": "3.4.0", - "source-map-loader": "^0.2.1", "react-dev-utils": "^5.0.2", "resolve": "1.6.0", + "sass-loader": "^7.1.0", + "source-map-loader": "^0.2.1", "style-loader": "0.19.0", "sw-precache-webpack-plugin": "0.11.4", "ts-jest": "22.0.1",