diff --git a/README.md b/README.md index 3608f846..fab71bbd 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ module.exports = { | **[`insert`](#insert)** | `{String\|Function}` | `document.head.appendChild(linkTag);` | Inserts the `link` tag at the given position for [non-initial (async)](https://webpack.js.org/concepts/under-the-hood/#chunks) CSS chunks | | **[`attributes`](#attributes)** | `{Object}` | `{}` | Adds custom attributes to the `link` tag for [non-initial (async)](https://webpack.js.org/concepts/under-the-hood/#chunks) CSS chunks | | **[`linkType`](#linkType)** | `{String\|Boolean}` | `text/css` | Allows loading asynchronous chunks with a custom link type | +| **[`noRuntime`](#linkType)** | `{Boolean}` | `false` | Skips the runtime generation | | **[`experimentalUseImportModule`](#experimentalUseImportModule)** | `{Boolean}` | `false` | Use an experimental webpack API to execute modules instead of child compilers | #### `filename` @@ -265,6 +266,35 @@ module.exports = { }; ``` +#### `noRuntime` + +##### `Boolean` + +An option to avoid the runtime generation. Assets are still extracted and can be used for a custom loading methods. For example, you can use [assets-webpack-plugin](https://github.com/ztoben/assets-webpack-plugin) to retreive them then use your own runtime code to download assets when needed. + +`true` to skip. + +**webpack.config.js** + +```js +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +module.exports = { + plugins: [ + new MiniCssExtractPlugin({ + skipRuntimeLoading: true, + }), + ], + module: { + rules: [ + { + test: /\.css$/i, + use: [MiniCssExtractPlugin.loader, "css-loader"], + }, + ], + }, +}; +``` + #### `experimentalUseImportModule` Use an experimental webpack API to execute modules instead of child compilers. diff --git a/src/index.js b/src/index.js index c9aabcfe..1378946d 100644 --- a/src/index.js +++ b/src/index.js @@ -337,6 +337,7 @@ class MiniCssExtractPlugin { filename: DEFAULT_FILENAME, ignoreOrder: false, experimentalUseImportModule: false, + noRuntime: false, }, options ); @@ -520,6 +521,10 @@ class MiniCssExtractPlugin { } }); + // All the code below is dedicated to the runtime and + // can be skipped in a noRuntime context + if (this.options.noRuntime) return; + const { Template } = webpack; const { RuntimeGlobals, runtime } = webpack; diff --git a/src/plugin-options.json b/src/plugin-options.json index e4f61e0b..7d70379d 100644 --- a/src/plugin-options.json +++ b/src/plugin-options.json @@ -65,6 +65,11 @@ ], "description": "This option allows loading asynchronous chunks with a custom link type", "link": "https://github.com/webpack-contrib/mini-css-extract-plugin#linktype" + }, + "noRuntime": { + "type": "boolean", + "description": "An option to avoid the runtime generation. Assets are still extracted and can be used for a custom loading methods.", + "link": "https://github.com/webpack-contrib/mini-css-extract-plugin#noRuntime" } } } diff --git a/test/__snapshots__/noRuntime-option.test.js.snap b/test/__snapshots__/noRuntime-option.test.js.snap new file mode 100644 index 00000000..93ab1046 --- /dev/null +++ b/test/__snapshots__/noRuntime-option.test.js.snap @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`noRuntime option should work when noRuntime option is "false": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`noRuntime option should work when noRuntime option is "false": errors 1`] = `Array []`; + +exports[`noRuntime option should work when noRuntime option is "false": warnings 1`] = `Array []`; + +exports[`noRuntime option should work when noRuntime option is "true": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`noRuntime option should work when noRuntime option is "true": errors 1`] = `Array []`; + +exports[`noRuntime option should work when noRuntime option is "true": warnings 1`] = `Array []`; + +exports[`noRuntime option should work without noRuntime option: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`noRuntime option should work without noRuntime option: errors 1`] = `Array []`; + +exports[`noRuntime option should work without noRuntime option: warnings 1`] = `Array []`; diff --git a/test/__snapshots__/validate-plugin-options.test.js.snap b/test/__snapshots__/validate-plugin-options.test.js.snap index 185a3c40..ed3d6acd 100644 --- a/test/__snapshots__/validate-plugin-options.test.js.snap +++ b/test/__snapshots__/validate-plugin-options.test.js.snap @@ -117,47 +117,47 @@ exports[`validate options should throw an error on the "linkType" option with "i exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType? }" + object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType?, noRuntime? }" `; exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType? }" + object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType?, noRuntime? }" `; exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType? }" + object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType?, noRuntime? }" `; exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType? }" + object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType?, noRuntime? }" `; exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType? }" + object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType?, noRuntime? }" `; exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType? }" + object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType?, noRuntime? }" `; exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType? }" + object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType?, noRuntime? }" `; exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = ` "Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType? }" + object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType?, noRuntime? }" `; diff --git a/test/noRuntime-option.test.js b/test/noRuntime-option.test.js new file mode 100644 index 00000000..7b48561d --- /dev/null +++ b/test/noRuntime-option.test.js @@ -0,0 +1,97 @@ +/* eslint-env browser */ +import path from "path"; + +import MiniCssExtractPlugin from "../src/cjs"; + +import { + compile, + getCompiler, + getErrors, + getWarnings, + runInJsDom, +} from "./helpers/index"; + +describe("noRuntime option", () => { + it(`should work without noRuntime option`, async () => { + const compiler = getCompiler( + "attributes.js", + {}, + { + output: { + publicPath: "", + path: path.resolve(__dirname, "../outputs"), + filename: "[name].bundle.js", + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: "[name].css", + }), + ], + } + ); + const stats = await compile(compiler); + + runInJsDom("main.bundle.js", compiler, stats, (dom) => { + expect(dom.serialize()).toMatchSnapshot("DOM"); + }); + + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); + + it(`should work when noRuntime option is "false"`, async () => { + const compiler = getCompiler( + "attributes.js", + {}, + { + output: { + publicPath: "", + path: path.resolve(__dirname, "../outputs"), + filename: "[name].bundle.js", + }, + plugins: [ + new MiniCssExtractPlugin({ + noRuntime: false, + filename: "[name].css", + }), + ], + } + ); + const stats = await compile(compiler); + + runInJsDom("main.bundle.js", compiler, stats, (dom) => { + expect(dom.serialize()).toMatchSnapshot("DOM"); + }); + + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); + + it(`should work when noRuntime option is "true"`, async () => { + const compiler = getCompiler( + "attributes.js", + {}, + { + output: { + publicPath: "", + path: path.resolve(__dirname, "../outputs"), + filename: "[name].bundle.js", + }, + plugins: [ + new MiniCssExtractPlugin({ + noRuntime: true, + filename: "[name].css", + }), + ], + } + ); + const stats = await compile(compiler); + + runInJsDom("main.bundle.js", compiler, stats, (dom) => { + expect(dom.serialize()).toMatchSnapshot("DOM"); + }); + + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); +});