From f4fb588c3d404f33e33456759f3d5cad0aba575b Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Fri, 20 Apr 2018 13:41:29 +0100 Subject: [PATCH] Replace extract-text-webpack-plugin with mini-css-extract-plugin Since the former is deprecated for CSS extraction, and is not compatible with webpack 4. The new plugin has a much simpler API: https://github.com/webpack-contrib/mini-css-extract-plugin I've also chosen to remove `css-hot-loader` - since it's unnecessary when using `style-loader` in development. ie option (2) from #802. (Once `mini-css-extract-plugin` supports HMR we can stop using `style-loader` entirely.) NB: `mini-css-extract-plugin` doesn't support having multiple plugin instances, so now we only have one instance for both standard CSS and module CSS. This will need testing to ensure everything still works. --- docs/packages/style-loader/README.md | 19 ++++----- docs/packages/web/README.md | 5 +-- packages/style-loader/README.md | 19 ++++----- packages/style-loader/index.js | 59 ++++++---------------------- packages/style-loader/package.json | 3 +- packages/web/README.md | 5 +-- 6 files changed, 32 insertions(+), 78 deletions(-) diff --git a/docs/packages/style-loader/README.md b/docs/packages/style-loader/README.md index 98075159f..8742a2b95 100644 --- a/docs/packages/style-loader/README.md +++ b/docs/packages/style-loader/README.md @@ -57,15 +57,15 @@ neutrino.use(styles, { ruleId: 'style', styleUseId: 'style', cssUseId: 'css', - hotUseId: 'hot', - hot: true, modules: true, modulesSuffix: '-modules', modulesTest: /\.module.css$/, extractId: 'extract', extract: { plugin: {}, - loader: {} + loader: { + filename: neutrino.options.command === 'build' ? '[name].[contenthash].css' : '[name].css' + } } }); ``` @@ -89,15 +89,15 @@ module.exports = { ruleId: 'style', styleUseId: 'style', cssUseId: 'css', - hotUseId: 'hot', - hot: true, modules: true, modulesSuffix: '-modules', modulesTest: /\.module.css$/, extractId: 'extract', extract: { plugin: {}, - loader: {} + loader: { + filename: neutrino.options.command === 'build' ? '[name].[contenthash].css' : '[name].css' + } } }] ] @@ -111,8 +111,6 @@ module.exports = { - `ruleId`: The ID of the webpack-chain rule used to identify the stylesheet loaders - `styleUseId`: The ID of the webpack-chain `use` used to identify the style-loader - `cssUseId`: The ID of the webpack-chain `use` used to identify the css-loader -- `hotUseId`: The ID of the webpack-chain `use` used to identify the css-hot-loader -- `hot`: Enable usage of CSS Hot Module Replacement. Set to `false` to disable. - `modules`: Enable usage of CSS modules via `*.module.css` files. Set to `false` to disable and skip defining these rules. - `modulesSuffix`: A suffix added to `ruleId`, `styleUseId`, `cssUseId`, `hotUseId`, and `extractId` to derive names for modules-related rules. For example, the default `-modules` suffix will generate a rule ID for the CSS modules rules of @@ -234,8 +232,8 @@ The following is a list of default rules and their identifiers which can be over | Name | Description | Environments and Commands | | --- | --- | --- | -| `style` | Allows importing CSS stylesheets from modules. Contains two loaders named `style` and `css` which use `style-loader` and `css-loader`, respectively. | all | -| `style-modules` | Allows importing CSS Modules styles from modules. Contains two loaders named `style-modules` and `css-modules` which use `style-loader` and `css-loader`, respectively. | all | +| `style` | Allows importing CSS stylesheets from modules. By default contains two loaders named `extract` and `css` which use `MiniCssExtractPlugin.loader` and `css-loader`, respectively. If `options.extract` is `false`, then the `extract` loader is replaced by `style`, which uses `style-loader`. | all | +| `style-modules` | Allows importing CSS Modules styles from modules. By default contains two loaders named `extract` and `css` which use `MiniCssExtractPlugin.loader` and `css-loader`, respectively. If `options.extract` is `false`, then the `extract` loader is replaced by `style`, which uses `style-loader`. | all | ### Plugins @@ -246,7 +244,6 @@ _Note: Some plugins may be only available in certain environments. To override t | Name | Description | Environments and Commands | | --- | --- | --- | | `extract` | Extracts CSS from JS bundle into a separate stylesheet file. | all | -| `extract-modules` | Extracts CSS from JS bundle into a separate stylesheet file. | all | ## Contributing diff --git a/docs/packages/web/README.md b/docs/packages/web/README.md index cec9f867b..35b212bec 100644 --- a/docs/packages/web/README.md +++ b/docs/packages/web/README.md @@ -417,8 +417,8 @@ The following is a list of rules and their identifiers which can be overridden: | --- | --- | --- | | `compile` | Compiles JS files from the `src` directory using Babel. Contains a single loader named `babel`. From `@neutrinojs/compile-loader`. | all | | `html` | Allows importing HTML files from modules. Contains a single loader named `html`. From `@neutrinojs/html-loader`. | all | -| `style` | Allows importing CSS stylesheets from modules. Contains two loaders named `style` and `css` which use `style-loader` and `css-loader`, respectively. From `@neutrinojs/style-loader`. | all | -| `style-modules` | Allows importing CSS Modules styles from modules. Contains two loaders named `style-modules` and `css-modules` which use `style-loader` and `css-loader`, respectively. From `@neutrinojs/style-loader`. | all | +| `style` | Allows importing CSS stylesheets from modules. In production contains two loaders named `extract` and `css` which use `MiniCssExtractPlugin.loader` and `css-loader`, respectively. In development the `extract` loader is replaced by `style`, which uses `style-loader`. From `@neutrinojs/style-loader`. | all | +| `style-modules` | Allows importing CSS Modules styles from modules. In production contains two loaders named `extract` and `css` which use `MiniCssExtractPlugin.loader` and `css-loader`, respectively. In development the `extract` loader is replaced by `style`, which uses `style-loader`. From `@neutrinojs/style-loader`. | all | | `img`, `svg`, `ico` | Allows import image files from modules. Each contains a single loader named `url`. From `@neutrinojs/image-loader`. | all | | `woff`, `ttf` | Allows importing WOFF and TTF font files from modules. Each contains a single loader named `url`. From `@neutrinojs/font-loader`. | all | | `eot` | Allows importing EOT font files from modules. Contains a single loader named `file`. From `@neutrinojs/font-loader`. | all | @@ -434,7 +434,6 @@ _Note: Some plugins are only available in certain environments. To override them | --- | --- | --- | | `env` | Inject environment variables into source code at `process.env`, defaults to only inject `NODE_ENV`. From `@neutrinojs/env`. | all | | `extract` | Extracts CSS from JS bundle into a separate stylesheet file. From `@neutrinojs/style-loader`. | all | -| `extract-modules` | Extracts CSS from JS bundle into a separate stylesheet file. From `@neutrinojs/style-loader`. | all | | `html-sibling-chunks` | Works around `html-webpack-plugin` not supporting `splitChunks` when using multiple entrypoints, via `html-webpack-include-sibling-chunks-plugin`. | all | | `html-{MAIN_NAME}` | Automatically generates HTML files for configured entry points. `{MAIN_NAME}` corresponds to the entry point of each page. By default, there is only a single `index` main, so this would generate a plugin named `html-index`. From `@neutrinojs/html-template` | all | | `hot` | Enables Hot Module Replacement. From `@neutrinojs/hot`. | `start` command | diff --git a/packages/style-loader/README.md b/packages/style-loader/README.md index dac738ec2..39a09da42 100644 --- a/packages/style-loader/README.md +++ b/packages/style-loader/README.md @@ -57,15 +57,15 @@ neutrino.use(styles, { ruleId: 'style', styleUseId: 'style', cssUseId: 'css', - hotUseId: 'hot', - hot: true, modules: true, modulesSuffix: '-modules', modulesTest: /\.module.css$/, extractId: 'extract', extract: { plugin: {}, - loader: {} + loader: { + filename: neutrino.options.command === 'build' ? '[name].[contenthash].css' : '[name].css' + } } }); ``` @@ -89,15 +89,15 @@ module.exports = { ruleId: 'style', styleUseId: 'style', cssUseId: 'css', - hotUseId: 'hot', - hot: true, modules: true, modulesSuffix: '-modules', modulesTest: /\.module.css$/, extractId: 'extract', extract: { plugin: {}, - loader: {} + loader: { + filename: neutrino.options.command === 'build' ? '[name].[contenthash].css' : '[name].css' + } } }] ] @@ -111,8 +111,6 @@ module.exports = { - `ruleId`: The ID of the webpack-chain rule used to identify the stylesheet loaders - `styleUseId`: The ID of the webpack-chain `use` used to identify the style-loader - `cssUseId`: The ID of the webpack-chain `use` used to identify the css-loader -- `hotUseId`: The ID of the webpack-chain `use` used to identify the css-hot-loader -- `hot`: Enable usage of CSS Hot Module Replacement. Set to `false` to disable. - `modules`: Enable usage of CSS modules via `*.module.css` files. Set to `false` to disable and skip defining these rules. - `modulesSuffix`: A suffix added to `ruleId`, `styleUseId`, `cssUseId`, `hotUseId`, and `extractId` to derive names for modules-related rules. For example, the default `-modules` suffix will generate a rule ID for the CSS modules rules of @@ -234,8 +232,8 @@ The following is a list of default rules and their identifiers which can be over | Name | Description | Environments and Commands | | --- | --- | --- | -| `style` | Allows importing CSS stylesheets from modules. Contains two loaders named `style` and `css` which use `style-loader` and `css-loader`, respectively. | all | -| `style-modules` | Allows importing CSS Modules styles from modules. Contains two loaders named `style-modules` and `css-modules` which use `style-loader` and `css-loader`, respectively. | all | +| `style` | Allows importing CSS stylesheets from modules. By default contains two loaders named `extract` and `css` which use `MiniCssExtractPlugin.loader` and `css-loader`, respectively. If `options.extract` is `false`, then the `extract` loader is replaced by `style`, which uses `style-loader`. | all | +| `style-modules` | Allows importing CSS Modules styles from modules. By default contains two loaders named `extract` and `css` which use `MiniCssExtractPlugin.loader` and `css-loader`, respectively. If `options.extract` is `false`, then the `extract` loader is replaced by `style`, which uses `style-loader`. | all | ### Plugins @@ -246,7 +244,6 @@ _Note: Some plugins may be only available in certain environments. To override t | Name | Description | Environments and Commands | | --- | --- | --- | | `extract` | Extracts CSS from JS bundle into a separate stylesheet file. | all | -| `extract-modules` | Extracts CSS from JS bundle into a separate stylesheet file. | all | ## Contributing diff --git a/packages/style-loader/index.js b/packages/style-loader/index.js index 482317678..808a25882 100644 --- a/packages/style-loader/index.js +++ b/packages/style-loader/index.js @@ -1,4 +1,4 @@ -const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const merge = require('deepmerge'); module.exports = (neutrino, opts = {}) => { @@ -13,8 +13,6 @@ module.exports = (neutrino, opts = {}) => { importLoaders: opts.loaders ? opts.loaders.length : 0 }, style: {}, - hot: true, - hotUseId: 'hot', modules, modulesTest, modulesSuffix: '-modules', @@ -22,10 +20,9 @@ module.exports = (neutrino, opts = {}) => { loaders: [], extractId: 'extract', extract: { + loader: {}, plugin: { - filename: neutrino.options.command === 'build' ? '[name].[contenthash].css' : '[name].css', - ignoreOrder: opts.modules !== false, - allChunks: true + filename: neutrino.options.command === 'build' ? '[name].[contenthash].css' : '[name].css' } } }, opts); @@ -40,7 +37,6 @@ module.exports = (neutrino, opts = {}) => { ruleId: `${options.ruleId}${options.modulesSuffix}`, styleUseId: `${options.styleUseId}${options.modulesSuffix}`, cssUseId: `${options.cssUseId}${options.modulesSuffix}`, - hotUseId: `${options.hotUseId}${options.modulesSuffix}`, extractId: `${options.extractId}${options.modulesSuffix}`, css: { modules: options.modules @@ -53,9 +49,9 @@ module.exports = (neutrino, opts = {}) => { const styleRule = neutrino.config.module.rule(options.ruleId); const loaders = [ { - loader: require.resolve('style-loader'), - options: options.style, - useId: options.styleUseId + loader: options.extract ? MiniCssExtractPlugin.loader : require.resolve('style-loader'), + options: options.extract ? options.extract.loader : options.style, + useId: options.extract ? options.extractId : options.styleUseId }, { loader: require.resolve('css-loader'), @@ -80,44 +76,11 @@ module.exports = (neutrino, opts = {}) => { .loader(loader.loader) .when(loader.options, use => use.options(loader.options)); }); - - if (options.extract) { - const styleEntries = styleRule.uses.entries(); - const useIds = Object.keys(styleEntries).filter(key => key !== options.styleUseId); - const extractLoader = Object.assign({ - use: useIds.map(key => ({ - loader: styleEntries[key].get('loader'), - options: styleEntries[key].get('options') - })), - fallback: { - loader: styleEntries[options.styleUseId].get('loader'), - options: styleEntries[options.styleUseId].get('options') - } - }, options.extract.loader || {}); - - styleRule - .uses - .clear() - .end() - .when(options.hot, (rule) => { - rule.use(options.hotUseId) - .loader(require.resolve('css-hot-loader')) - .when(options.hot !== true, use => use.options(options.hot)); - }); - - ExtractTextPlugin - .extract(extractLoader) - .forEach(({ loader, options }) => { - styleRule - .use(loader) - .loader(loader) - .options(options); - }); - - neutrino.config - .plugin(options.extractId) - .use(ExtractTextPlugin, [options.extract.plugin]); - } }); + if (options.extract) { + neutrino.config + .plugin(options.extractId) + .use(MiniCssExtractPlugin, [options.extract.plugin]); + } }; diff --git a/packages/style-loader/package.json b/packages/style-loader/package.json index 88efef1df..bbb3e169a 100644 --- a/packages/style-loader/package.json +++ b/packages/style-loader/package.json @@ -24,10 +24,9 @@ "yarn": ">=1.2.1" }, "dependencies": { - "css-hot-loader": "^1.3.4", "css-loader": "^0.28.7", "deepmerge": "^1.5.2", - "extract-text-webpack-plugin": "^3.0.2", + "mini-css-extract-plugin": "^0.4.0", "style-loader": "^0.21.0" }, "devDependencies": { diff --git a/packages/web/README.md b/packages/web/README.md index 013ecea9b..43017c9df 100644 --- a/packages/web/README.md +++ b/packages/web/README.md @@ -417,8 +417,8 @@ The following is a list of rules and their identifiers which can be overridden: | --- | --- | --- | | `compile` | Compiles JS files from the `src` directory using Babel. Contains a single loader named `babel`. From `@neutrinojs/compile-loader`. | all | | `html` | Allows importing HTML files from modules. Contains a single loader named `html`. From `@neutrinojs/html-loader`. | all | -| `style` | Allows importing CSS stylesheets from modules. Contains two loaders named `style` and `css` which use `style-loader` and `css-loader`, respectively. From `@neutrinojs/style-loader`. | all | -| `style-modules` | Allows importing CSS Modules styles from modules. Contains two loaders named `style-modules` and `css-modules` which use `style-loader` and `css-loader`, respectively. From `@neutrinojs/style-loader`. | all | +| `style` | Allows importing CSS stylesheets from modules. In production contains two loaders named `extract` and `css` which use `MiniCssExtractPlugin.loader` and `css-loader`, respectively. In development the `extract` loader is replaced by `style`, which uses `style-loader`. From `@neutrinojs/style-loader`. | all | +| `style-modules` | Allows importing CSS Modules styles from modules. In production contains two loaders named `extract` and `css` which use `MiniCssExtractPlugin.loader` and `css-loader`, respectively. In development the `extract` loader is replaced by `style`, which uses `style-loader`. From `@neutrinojs/style-loader`. | all | | `img`, `svg`, `ico` | Allows import image files from modules. Each contains a single loader named `url`. From `@neutrinojs/image-loader`. | all | | `woff`, `ttf` | Allows importing WOFF and TTF font files from modules. Each contains a single loader named `url`. From `@neutrinojs/font-loader`. | all | | `eot` | Allows importing EOT font files from modules. Contains a single loader named `file`. From `@neutrinojs/font-loader`. | all | @@ -434,7 +434,6 @@ _Note: Some plugins are only available in certain environments. To override them | --- | --- | --- | | `env` | Inject environment variables into source code at `process.env`, defaults to only inject `NODE_ENV`. From `@neutrinojs/env`. | all | | `extract` | Extracts CSS from JS bundle into a separate stylesheet file. From `@neutrinojs/style-loader`. | all | -| `extract-modules` | Extracts CSS from JS bundle into a separate stylesheet file. From `@neutrinojs/style-loader`. | all | | `html-sibling-chunks` | Works around `html-webpack-plugin` not supporting `splitChunks` when using multiple entrypoints, via `html-webpack-include-sibling-chunks-plugin`. | all | | `html-{MAIN_NAME}` | Automatically generates HTML files for configured entry points. `{MAIN_NAME}` corresponds to the entry point of each page. By default, there is only a single `index` main, so this would generate a plugin named `html-index`. From `@neutrinojs/html-template` | all | | `hot` | Enables Hot Module Replacement. From `@neutrinojs/hot`. | `start` command |