mirror of https://github.com/webpack/webpack.git
				
				
				
			fix(css): avoid extra `module.export` output for css module (#19265)
This commit is contained in:
		
							parent
							
								
									e5c3f95b84
								
							
						
					
					
						commit
						e0891eeea0
					
				|  | @ -105,6 +105,7 @@ const makeSerializable = require("./util/makeSerializable"); | |||
|  * @property {boolean=} async | ||||
|  * @property {boolean=} sideEffectFree | ||||
|  * @property {Record<string, string>=} exportsFinalName | ||||
|  * @property {boolean=} isCSSModule | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  |  | |||
|  | @ -34,6 +34,11 @@ const ASSET_AND_JS_AND_CSS_URL_TYPES = new Set([ | |||
| 	"css-url" | ||||
| ]); | ||||
| 
 | ||||
| /** | ||||
|  * @type {"javascript"} | ||||
|  */ | ||||
| const JS_TYPE = "javascript"; | ||||
| 
 | ||||
| /** | ||||
|  * @type {ReadonlySet<"javascript">} | ||||
|  */ | ||||
|  | @ -54,6 +59,10 @@ const JS_AND_CSS_URL_TYPES = new Set(["javascript", "css-url"]); | |||
|  */ | ||||
| const JS_AND_CSS_TYPES = new Set(["javascript", "css"]); | ||||
| 
 | ||||
| /** | ||||
|  * @type {"css"} | ||||
|  */ | ||||
| const CSS_TYPE = "css"; | ||||
| /** | ||||
|  * @type {ReadonlySet<"css">} | ||||
|  */ | ||||
|  | @ -94,6 +103,7 @@ const CONSUME_SHARED_TYPES = new Set(["consume-shared"]); | |||
| const SHARED_INIT_TYPES = new Set(["share-init"]); | ||||
| 
 | ||||
| module.exports.NO_TYPES = NO_TYPES; | ||||
| module.exports.JS_TYPE = JS_TYPE; | ||||
| module.exports.JS_TYPES = JS_TYPES; | ||||
| module.exports.JS_AND_CSS_TYPES = JS_AND_CSS_TYPES; | ||||
| module.exports.JS_AND_CSS_URL_TYPES = JS_AND_CSS_URL_TYPES; | ||||
|  | @ -102,6 +112,7 @@ module.exports.ASSET_TYPES = ASSET_TYPES; | |||
| module.exports.ASSET_AND_JS_TYPES = ASSET_AND_JS_TYPES; | ||||
| module.exports.ASSET_AND_CSS_URL_TYPES = ASSET_AND_CSS_URL_TYPES; | ||||
| module.exports.ASSET_AND_JS_AND_CSS_URL_TYPES = ASSET_AND_JS_AND_CSS_URL_TYPES; | ||||
| module.exports.CSS_TYPE = CSS_TYPE; | ||||
| module.exports.CSS_TYPES = CSS_TYPES; | ||||
| module.exports.CSS_URL_TYPES = CSS_URL_TYPES; | ||||
| module.exports.CSS_IMPORT_TYPES = CSS_IMPORT_TYPES; | ||||
|  |  | |||
|  | @ -11,7 +11,10 @@ const Generator = require("../Generator"); | |||
| const InitFragment = require("../InitFragment"); | ||||
| const { | ||||
| 	JS_AND_CSS_EXPORT_TYPES, | ||||
| 	JS_AND_CSS_TYPES | ||||
| 	JS_AND_CSS_TYPES, | ||||
| 	CSS_TYPES, | ||||
| 	JS_TYPE, | ||||
| 	CSS_TYPE | ||||
| } = require("../ModuleSourceTypesConstants"); | ||||
| const RuntimeGlobals = require("../RuntimeGlobals"); | ||||
| const Template = require("../Template"); | ||||
|  | @ -27,21 +30,25 @@ const Template = require("../Template"); | |||
| /** @typedef {import("../Generator").GenerateContext} GenerateContext */ | ||||
| /** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */ | ||||
| /** @typedef {import("../Module").BuildInfo} BuildInfo */ | ||||
| /** @typedef {import("../Module").BuildMeta} BuildMeta */ | ||||
| /** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */ | ||||
| /** @typedef {import("../Module").SourceTypes} SourceTypes */ | ||||
| /** @typedef {import("../ModuleGraph")} ModuleGraph */ | ||||
| /** @typedef {import("../NormalModule")} NormalModule */ | ||||
| /** @typedef {import("../util/Hash")} Hash */ | ||||
| 
 | ||||
| class CssGenerator extends Generator { | ||||
| 	/** | ||||
| 	 * @param {CssAutoGeneratorOptions | CssGlobalGeneratorOptions | CssModuleGeneratorOptions} options options | ||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | ||||
| 	 */ | ||||
| 	constructor(options) { | ||||
| 	constructor(options, moduleGraph) { | ||||
| 		super(); | ||||
| 		this.convention = options.exportsConvention; | ||||
| 		this.localIdentName = options.localIdentName; | ||||
| 		this.exportsOnly = options.exportsOnly; | ||||
| 		this.esModule = options.esModule; | ||||
| 		this._moduleGraph = moduleGraph; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  | @ -169,6 +176,13 @@ class CssGenerator extends Generator { | |||
| 					return source; | ||||
| 				} | ||||
| 
 | ||||
| 				if ( | ||||
| 					cssData.exports.size === 0 && | ||||
| 					!(/** @type {BuildMeta} */ (module.buildMeta).isCSSModule) | ||||
| 				) { | ||||
| 					return new RawSource(""); | ||||
| 				} | ||||
| 
 | ||||
| 				const needNsObj = | ||||
| 					this.esModule && | ||||
| 					generateContext.moduleGraph | ||||
|  | @ -237,7 +251,22 @@ class CssGenerator extends Generator { | |||
| 	 */ | ||||
| 	getTypes(module) { | ||||
| 		// TODO, find a better way to prevent the original module from being removed after concatenation, maybe it is a bug
 | ||||
| 		return this.exportsOnly ? JS_AND_CSS_EXPORT_TYPES : JS_AND_CSS_TYPES; | ||||
| 		if (this.exportsOnly) { | ||||
| 			return JS_AND_CSS_EXPORT_TYPES; | ||||
| 		} | ||||
| 		const sourceTypes = new Set(); | ||||
| 		const connections = this._moduleGraph.getIncomingConnections(module); | ||||
| 		for (const connection of connections) { | ||||
| 			if (!connection.originModule) { | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (connection.originModule.type.split("/")[0] !== CSS_TYPE) | ||||
| 				sourceTypes.add(JS_TYPE); | ||||
| 		} | ||||
| 		if (sourceTypes.has(JS_TYPE)) { | ||||
| 			return JS_AND_CSS_TYPES; | ||||
| 		} | ||||
| 		return CSS_TYPES; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  | @ -248,12 +277,17 @@ class CssGenerator extends Generator { | |||
| 	getSize(module, type) { | ||||
| 		switch (type) { | ||||
| 			case "javascript": { | ||||
| 				const buildInfo = /** @type {BuildInfo} */ (module.buildInfo); | ||||
| 				if (!buildInfo.cssData) { | ||||
| 				const cssData = /** @type {BuildInfo} */ (module.buildInfo).cssData; | ||||
| 				if (!cssData) { | ||||
| 					return 42; | ||||
| 				} | ||||
| 
 | ||||
| 				const exports = buildInfo.cssData.exports; | ||||
| 				if (cssData.exports.size === 0) { | ||||
| 					if (/** @type {BuildMeta} */ (module.buildMeta).isCSSModule) { | ||||
| 						return 42; | ||||
| 					} | ||||
| 					return 0; | ||||
| 				} | ||||
| 				const exports = cssData.exports; | ||||
| 				const stringifiedExports = JSON.stringify( | ||||
| 					Array.from(exports).reduce((obj, [key, value]) => { | ||||
| 						obj[key] = value; | ||||
|  |  | |||
|  | @ -301,7 +301,10 @@ class CssModulesPlugin { | |||
| 						.tap(PLUGIN_NAME, generatorOptions => { | ||||
| 							validateGeneratorOptions[type](generatorOptions); | ||||
| 
 | ||||
| 							return new CssGenerator(generatorOptions); | ||||
| 							return new CssGenerator( | ||||
| 								generatorOptions, | ||||
| 								compilation.moduleGraph | ||||
| 							); | ||||
| 						}); | ||||
| 					normalModuleFactory.hooks.createModuleClass | ||||
| 						.for(type) | ||||
|  |  | |||
|  | @ -361,6 +361,9 @@ class CssParser extends Parser { | |||
| 
 | ||||
| 		const isModules = mode === "global" || mode === "local"; | ||||
| 
 | ||||
| 		/** @type {BuildMeta} */ | ||||
| 		(module.buildMeta).isCSSModule = isModules; | ||||
| 
 | ||||
| 		const locConverter = new LocConverter(source); | ||||
| 
 | ||||
| 		/** @type {number} */ | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| const asyncLib = require("neo-async"); | ||||
| const ChunkGraph = require("../ChunkGraph"); | ||||
| const ModuleGraph = require("../ModuleGraph"); | ||||
| const { JS_TYPE } = require("../ModuleSourceTypesConstants"); | ||||
| const { STAGE_DEFAULT } = require("../OptimizationStages"); | ||||
| const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency"); | ||||
| const { compareModulesByIdentifier } = require("../util/comparators"); | ||||
|  | @ -452,7 +453,7 @@ class ModuleConcatenationPlugin { | |||
| 												chunkGraph.disconnectChunkAndModule(chunk, m); | ||||
| 											} else { | ||||
| 												const newSourceTypes = new Set(sourceTypes); | ||||
| 												newSourceTypes.delete("javascript"); | ||||
| 												newSourceTypes.delete(JS_TYPE); | ||||
| 												chunkGraph.setChunkModuleSourceTypes( | ||||
| 													chunk, | ||||
| 													m, | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ const vm = require("vm"); | |||
| const rimraf = require("rimraf"); | ||||
| const checkArrayExpectation = require("./checkArrayExpectation"); | ||||
| const createLazyTestEnv = require("./helpers/createLazyTestEnv"); | ||||
| const FakeDocument = require("./helpers/FakeDocument"); | ||||
| 
 | ||||
| const casesPath = path.join(__dirname, "hotCases"); | ||||
| let categories = fs | ||||
|  | @ -108,8 +109,7 @@ const describeCases = config => { | |||
| 								// ignored
 | ||||
| 							} | ||||
| 
 | ||||
| 							compiler = webpack(options); | ||||
| 							compiler.run((err, stats) => { | ||||
| 							const onCompiled = (err, stats) => { | ||||
| 								if (err) return done(err); | ||||
| 								const jsonStats = stats.toJson({ | ||||
| 									errorDetails: true | ||||
|  | @ -179,9 +179,8 @@ const describeCases = config => { | |||
| 									}, | ||||
| 									document: { | ||||
| 										createElement(type) { | ||||
| 											return { | ||||
| 											const ele = { | ||||
| 												_type: type, | ||||
| 												sheet: {}, | ||||
| 												getAttribute(name) { | ||||
| 													return this[name]; | ||||
| 												}, | ||||
|  | @ -199,6 +198,11 @@ const describeCases = config => { | |||
| 													} | ||||
| 												} | ||||
| 											}; | ||||
| 											ele.sheet = | ||||
| 												type === "link" | ||||
| 													? new FakeDocument.FakeSheet(ele, outputDirectory) | ||||
| 													: {}; | ||||
| 											return ele; | ||||
| 										}, | ||||
| 										head: { | ||||
| 											appendChild(element) { | ||||
|  | @ -353,8 +357,15 @@ const describeCases = config => { | |||
| 								let promise = Promise.resolve(); | ||||
| 								const info = stats.toJson({ all: false, entrypoints: true }); | ||||
| 								if (config.target === "web") { | ||||
| 									for (const file of info.entrypoints.main.assets) | ||||
| 									for (const file of info.entrypoints.main.assets) { | ||||
| 										if (file.name.endsWith(".css")) { | ||||
| 											const link = window.document.createElement("link"); | ||||
| 											link.href = path.join(outputDirectory, file.name); | ||||
| 											window.document.head.appendChild(link); | ||||
| 										} else { | ||||
| 											_require(`./${file.name}`); | ||||
| 										} | ||||
| 									} | ||||
| 								} else { | ||||
| 									const assets = info.entrypoints.main.assets; | ||||
| 									const result = _require( | ||||
|  | @ -375,7 +386,9 @@ const describeCases = config => { | |||
| 										done(err); | ||||
| 									} | ||||
| 								); | ||||
| 							}); | ||||
| 							}; | ||||
| 							compiler = webpack(options); | ||||
| 							compiler.run(onCompiled); | ||||
| 						}, 20000); | ||||
| 
 | ||||
| 						const { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| it("should compile and load style on demand", (done) => { | ||||
| 	import("./style.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 		const style = getComputedStyle(document.body); | ||||
| 		expect(style.getPropertyValue("background")).toBe(" red"); | ||||
| 		expect(style.getPropertyValue("margin")).toBe(" 10px"); | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| import * as style from "./style.css"; | ||||
| 
 | ||||
| it("should compile and load style on demand", done => { | ||||
| 	expect(style).toEqual(nsObj({})); | ||||
| 	expect(style).toEqual({}); | ||||
| 	import("./style2.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 		done(); | ||||
| 	}, done); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| import * as style from "./style.css"; | ||||
| 
 | ||||
| it("should compile and load style on demand", done => { | ||||
| 	expect(style).toEqual(nsObj({})); | ||||
| 	expect(style).toEqual({}); | ||||
| 	import("./style2.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 		const style = getComputedStyle(document.body); | ||||
| 		expect(style.getPropertyValue("background")).toBe(" red"); | ||||
| 		expect(style.getPropertyValue("margin")).toBe(" 10px"); | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import * as style from "./style.css"; | ||||
| 
 | ||||
| it("should compile and load initial style", () => { | ||||
| 	expect(style).toEqual(nsObj({})); | ||||
| 	expect(style).toEqual({}); | ||||
| 	const computedStyle = getComputedStyle(document.body); | ||||
| 	expect(computedStyle.getPropertyValue("background")).toBe(" red"); | ||||
| 	expect(computedStyle.getPropertyValue("margin")).toBe(" 10px"); | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| import * as style from "./style.css"; | ||||
| 
 | ||||
| it("should compile and load style on demand", done => { | ||||
| 	expect(style).toEqual(nsObj({})); | ||||
| 	expect(style).toEqual({}); | ||||
| 	import("./style2.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 		const style = getComputedStyle(document.body); | ||||
| 		expect(style.getPropertyValue("background")).toBe(" red"); | ||||
| 		expect(style.getPropertyValue("margin")).toBe(" 10px"); | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| import * as style from "./style.css"; | ||||
| 
 | ||||
| it("should compile and load style on demand", done => { | ||||
| 	expect(style).toEqual(nsObj({})); | ||||
| 	expect(style).toEqual({}); | ||||
| 	import("./style2.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 		const style = getComputedStyle(document.body); | ||||
| 		expect(style.getPropertyValue("background")).toBe(" red"); | ||||
| 		expect(style.getPropertyValue("margin")).toBe(" 10px"); | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ it("should work with js", done => { | |||
| }); | ||||
| 
 | ||||
| it("should work with css", done => { | ||||
| 	expect(style).toEqual(nsObj({})); | ||||
| 	expect(style).toEqual({}); | ||||
| 
 | ||||
| 	const computedStyle = getComputedStyle(document.body); | ||||
| 
 | ||||
|  | @ -16,7 +16,7 @@ it("should work with css", done => { | |||
| 	expect(computedStyle.getPropertyValue("color")).toBe(" yellow"); | ||||
| 
 | ||||
| 	import("./async.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 
 | ||||
| 		const style = getComputedStyle(document.body); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| it("should import an external css", done => { | ||||
| 	import("../external/style.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 		done(); | ||||
| 	}, done); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| it("should import an external css", done => { | ||||
| 	import("./style.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 		const style = getComputedStyle(document.body); | ||||
| 		expect(style.getPropertyValue("color")).toBe(" green"); | ||||
| 		expect(style.getPropertyValue("background")).toBe( | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import * as style from "./style.css"; | ||||
| 
 | ||||
| it("should compile and load style on demand", () => { | ||||
| 	expect(style).toEqual(nsObj({})); | ||||
| 	expect(style).toEqual({}); | ||||
| 	const computedStyle = getComputedStyle(document.body); | ||||
| 	expect(computedStyle.getPropertyValue("background")).toBe(" red"); | ||||
| 	expect(computedStyle.getPropertyValue("margin")).toBe(" 10px"); | ||||
|  |  | |||
|  | @ -0,0 +1,3 @@ | |||
| .bar { | ||||
| 	background-color: black; | ||||
| } | ||||
|  | @ -0,0 +1,3 @@ | |||
| .bar { | ||||
| 	background-color: black; | ||||
| } | ||||
|  | @ -0,0 +1,3 @@ | |||
| .bar { | ||||
| 	background-color: black; | ||||
| } | ||||
|  | @ -0,0 +1,3 @@ | |||
| .bar { | ||||
| 	background-color: black; | ||||
| } | ||||
|  | @ -0,0 +1,3 @@ | |||
| .bar { | ||||
| 	background-color: black; | ||||
| } | ||||
|  | @ -0,0 +1,5 @@ | |||
| @import url("./a1.css"); | ||||
| 
 | ||||
| .foo { | ||||
| 	background-color: red; | ||||
| } | ||||
|  | @ -0,0 +1,4 @@ | |||
| import "./main.css" | ||||
| require("./a2.css") | ||||
| import("./a2.css").then(() => {}) | ||||
| 
 | ||||
|  | @ -0,0 +1,3 @@ | |||
| import a1 from "./a1.module.css" | ||||
| const a2 = require("./a2.module.css") | ||||
| import("./a3.module.css").then(() => {}) | ||||
|  | @ -0,0 +1,12 @@ | |||
| module.exports = { | ||||
| 	findBundle: function (i) { | ||||
| 		switch (i) { | ||||
| 			case 0: | ||||
| 				return ["test.js"]; | ||||
| 			case 1: | ||||
| 				return ["test.js", `1/main.js`]; | ||||
| 			case 2: | ||||
| 				return ["test.js", `2/main.js`]; | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
|  | @ -0,0 +1,30 @@ | |||
| it("should work", () => { | ||||
| 	const stats = __STATS__.children[__STATS_I__]; | ||||
| 
 | ||||
| 	expect(stats.assets.findIndex(a => a.name === "test.js") > -1).toBe(true); | ||||
| 
 | ||||
| 	expect( | ||||
| 		stats.assets.findIndex(a => a.name === `${__STATS_I__}/main.css`) > -1 | ||||
| 	).toBe(true); | ||||
| 
 | ||||
| 	if (__STATS_I__ === 0) { | ||||
| 		// ./main.css
 | ||||
| 		// ./a.css
 | ||||
| 		// and it still output two runtime module:
 | ||||
| 		// 	 'webpack/runtime/make namespace object'
 | ||||
| 		// 	 'webpack/runtime/css loading'
 | ||||
| 		expect(stats.modules.length).toBe(4); | ||||
| 	} else if (__STATS_I__ === 1) { | ||||
| 		stats.modules | ||||
| 			.filter(module => module.moduleType === "css/auto") | ||||
| 			.forEach(module => { | ||||
| 				expect(module.sizes["javascript"] === 1).toBe(true); | ||||
| 			}); | ||||
| 	} else if (__STATS_I__ === 2) { | ||||
| 		stats.modules | ||||
| 			.filter(module => module.moduleType === "css/auto") | ||||
| 			.forEach(module => { | ||||
| 				expect(module.sizes["javascript"] === 1).toBe(false); | ||||
| 			}); | ||||
| 	} | ||||
| }); | ||||
|  | @ -0,0 +1,69 @@ | |||
| const path = require("path"); | ||||
| const fs = require("fs"); | ||||
| const webpack = require("../../../../"); | ||||
| 
 | ||||
| const entry = i => { | ||||
| 	switch (i) { | ||||
| 		case 0: | ||||
| 			return { | ||||
| 				main: ["./main.css"] | ||||
| 			}; | ||||
| 		case 1: | ||||
| 			return { | ||||
| 				main: ["./main1.js"] | ||||
| 			}; | ||||
| 		case 2: | ||||
| 			return { | ||||
| 				main: ["./main2.js"] | ||||
| 			}; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * @param {number} i param | ||||
|  * @returns {import("../../../../").Configuration} return | ||||
|  */ | ||||
| const common = i => ({ | ||||
| 	entry: { | ||||
| 		...entry(i) | ||||
| 	}, | ||||
| 	target: "web", | ||||
| 	devtool: false, | ||||
| 	experiments: { | ||||
| 		css: true | ||||
| 	}, | ||||
| 	output: { | ||||
| 		filename: `${i}/[name].js`, | ||||
| 		chunkFilename: `${i}/[name].js`, | ||||
| 		cssFilename: `${i}/[name].css`, | ||||
| 		cssChunkFilename: `${i}/[name].css` | ||||
| 	}, | ||||
| 	plugins: [ | ||||
| 		{ | ||||
| 			apply(compiler) { | ||||
| 				compiler.hooks.compilation.tap("Test", compilation => { | ||||
| 					compilation.hooks.processAssets.tap( | ||||
| 						{ | ||||
| 							name: "copy-webpack-plugin", | ||||
| 							stage: | ||||
| 								compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL | ||||
| 						}, | ||||
| 						() => { | ||||
| 							const data = fs.readFileSync( | ||||
| 								path.resolve(__dirname, "./test.js") | ||||
| 							); | ||||
| 
 | ||||
| 							compilation.emitAsset( | ||||
| 								"test.js", | ||||
| 								new webpack.sources.RawSource(data) | ||||
| 							); | ||||
| 						} | ||||
| 					); | ||||
| 				}); | ||||
| 			} | ||||
| 		} | ||||
| 	] | ||||
| }); | ||||
| 
 | ||||
| /** @type {import("../../../../").Configuration[]} */ | ||||
| module.exports = [...[0, 1].map(i => common(i))]; | ||||
|  | @ -1,9 +1,9 @@ | |||
| import * as style from "./style.css"; | ||||
| 
 | ||||
| it("should compile and load style on demand", done => { | ||||
| 	expect(style).toEqual(nsObj({})); | ||||
| 	expect(style).toEqual({}); | ||||
| 	import("./style2.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 		const style = getComputedStyle(document.body); | ||||
| 		expect(style.getPropertyValue("background")).toBe(" red"); | ||||
| 		expect(style.getPropertyValue("margin")).toBe(" 10px"); | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import * as styles1 from "./style.less"; | |||
| import * as styles2 from "./style.modules.less"; | ||||
| 
 | ||||
| it("should prefer relative", () => { | ||||
| 	expect(styles1).toEqual(nsObj({})); | ||||
| 	expect(styles1).toEqual({}); | ||||
| 	expect(styles2).toEqual(nsObj({ | ||||
| 		"style-module": "_style_modules_less-style-module", | ||||
| 	})); | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import * as styles1 from "./style.css"; | |||
| import * as styles2 from "./style.modules.css"; | ||||
| 
 | ||||
| it("should prefer relative", () => { | ||||
| 	expect(styles1).toEqual(nsObj({})); | ||||
| 	expect(styles1).toEqual({}); | ||||
| 	expect(styles2).toEqual(nsObj({ | ||||
| 		"style-module": "_style_modules_css-style-module", | ||||
| 	})); | ||||
|  |  | |||
|  | @ -2,13 +2,13 @@ import * as pureStyle from "./style.css"; | |||
| import * as styles from "./style.modules.css"; | ||||
| 
 | ||||
| it("should work", done => { | ||||
| 	expect(pureStyle).toEqual(nsObj({})); | ||||
| 	expect(pureStyle).toEqual({}); | ||||
| 	const style = getComputedStyle(document.body); | ||||
| 	expect(style.getPropertyValue("background")).toBe(" red"); | ||||
|   expect(styles.foo).toBe('_style_modules_css-foo'); | ||||
| 
 | ||||
| 	import(/* webpackPrefetch: true */ "./style2.css").then(x => { | ||||
| 		expect(x).toEqual(nsObj({})); | ||||
| 		expect(x).toEqual({}); | ||||
| 		const style = getComputedStyle(document.body); | ||||
| 		expect(style.getPropertyValue("color")).toBe(" blue"); | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ it(`should generate correct url public path with css filename`, done => { | |||
| 	document.body.appendChild(h1); | ||||
| 	import("./index.css").then(x => { | ||||
| 		try { | ||||
| 			expect(x).toEqual(nsObj({})); | ||||
| 			expect(x).toEqual({}); | ||||
| 			const style1 = getComputedStyle(h1); | ||||
| 			expect(style1).toMatchSnapshot(); | ||||
| 			const style2 = getComputedStyle(h2); | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ function getPropertyValue(property) { | |||
| 	return this[property]; | ||||
| } | ||||
| 
 | ||||
| module.exports = class FakeDocument { | ||||
| class FakeDocument { | ||||
| 	constructor(basePath) { | ||||
| 		this.head = this.createElement("head"); | ||||
| 		this.body = this.createElement("body"); | ||||
|  | @ -54,7 +54,7 @@ module.exports = class FakeDocument { | |||
| 		} | ||||
| 		return style; | ||||
| 	} | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| class FakeElement { | ||||
| 	constructor(document, type, basePath) { | ||||
|  | @ -252,3 +252,8 @@ class FakeSheet { | |||
| 		return rules; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| FakeDocument.FakeSheet = FakeSheet; | ||||
| FakeDocument.FakeElement = FakeDocument; | ||||
| 
 | ||||
| module.exports = FakeDocument; | ||||
|  |  | |||
|  | @ -0,0 +1,4 @@ | |||
| 
 | ||||
| .html { | ||||
| 	color: green; | ||||
| } | ||||
|  | @ -0,0 +1,9 @@ | |||
| @import url("./a.css"); | ||||
| --- | ||||
| html { | ||||
| 	color: blue; | ||||
| } | ||||
| --- | ||||
| html { | ||||
| 	color: yellow; | ||||
| } | ||||
|  | @ -0,0 +1,21 @@ | |||
| import "./index.css" | ||||
| 
 | ||||
| it("should work", done => { | ||||
| 	const links = window.document.getElementsByTagName("link"); | ||||
| 	expect(links[0].sheet.css).toContain("color: green;"); | ||||
| 
 | ||||
| 	NEXT( | ||||
| 		require("../../update")(done, true, () => { | ||||
| 			const links = window.document.getElementsByTagName("link"); | ||||
| 			expect(links[0].sheet.css).toContain("color: blue;"); | ||||
| 
 | ||||
| 			NEXT( | ||||
| 				require("../../update")(done, true, () => { | ||||
| 					const links = window.document.getElementsByTagName("link"); | ||||
| 					expect(links[0].sheet.css).toContain("color: yellow;"); | ||||
| 					done(); | ||||
| 				}) | ||||
| 			); | ||||
| 		}) | ||||
| 	); | ||||
| }); | ||||
|  | @ -0,0 +1,5 @@ | |||
| module.exports = function (config) { | ||||
| 	if (config.target !== "web") { | ||||
| 		return false; | ||||
| 	} | ||||
| }; | ||||
|  | @ -0,0 +1,8 @@ | |||
| /** @type {import("../../../../").Configuration} */ | ||||
| module.exports = { | ||||
| 	mode: "development", | ||||
| 	devtool: false, | ||||
| 	experiments: { | ||||
| 		css: true | ||||
| 	} | ||||
| }; | ||||
|  | @ -0,0 +1,11 @@ | |||
| .html { | ||||
| 	color: red; | ||||
| } | ||||
| --- | ||||
| html { | ||||
| 	color: blue; | ||||
| } | ||||
| --- | ||||
| html { | ||||
| 	color: yellow; | ||||
| } | ||||
|  | @ -0,0 +1,19 @@ | |||
| it("should work", done => { | ||||
| 	const links = window.document.getElementsByTagName("link"); | ||||
| 	expect(links[0].sheet.css).toContain("color: red;"); | ||||
| 
 | ||||
| 	NEXT( | ||||
| 		require("../../update")(done, true, () => { | ||||
| 			const links = window.document.getElementsByTagName("link"); | ||||
| 			expect(links[0].sheet.css).toContain("color: blue;"); | ||||
| 
 | ||||
| 			NEXT( | ||||
| 				require("../../update")(done, true, () => { | ||||
| 					const links = window.document.getElementsByTagName("link"); | ||||
| 					expect(links[0].sheet.css).toContain("color: yellow;"); | ||||
| 					done(); | ||||
| 				}) | ||||
| 			); | ||||
| 		}) | ||||
| 	); | ||||
| }); | ||||
|  | @ -0,0 +1,5 @@ | |||
| module.exports = function (config) { | ||||
| 	if (config.target !== "web") { | ||||
| 		return false; | ||||
| 	} | ||||
| }; | ||||
|  | @ -0,0 +1,29 @@ | |||
| const webpack = require("../../../../"); | ||||
| 
 | ||||
| /** @type {import("../../../../").Configuration} */ | ||||
| module.exports = { | ||||
| 	mode: "development", | ||||
| 	devtool: false, | ||||
| 	entry: ["./index.js", "./index.css"], | ||||
| 	experiments: { | ||||
| 		css: true | ||||
| 	}, | ||||
| 	plugins: [ | ||||
| 		{ | ||||
| 			apply(compiler) { | ||||
| 				compiler.hooks.compilation.tap("Test", compilation => { | ||||
| 					compilation.hooks.additionalTreeRuntimeRequirements.tap( | ||||
| 						"Test", | ||||
| 						(module, set, context) => { | ||||
| 							// To prevent the runtime error `ReferenceError: __webpack_exports__ is not defined`,
 | ||||
| 							// which occurs because the default `output.library` setting is `commonjs2`,
 | ||||
| 							// resulting in adding `module.exports = __webpack_exports__;`.
 | ||||
| 							set.add(webpack.RuntimeGlobals.startup); | ||||
| 							set.add(webpack.RuntimeGlobals.exports); | ||||
| 						} | ||||
| 					); | ||||
| 				}); | ||||
| 			} | ||||
| 		} | ||||
| 	] | ||||
| }; | ||||
|  | @ -0,0 +1,39 @@ | |||
| const getFile = name => | ||||
| 	__non_webpack_require__("fs").readFileSync( | ||||
| 		__non_webpack_require__("path").join(__dirname, name), | ||||
| 		"utf-8" | ||||
| 	); | ||||
| 
 | ||||
| it("should work", async function (done) { | ||||
| 	let promise = import("./style.css"); | ||||
| 
 | ||||
| 	NEXT( | ||||
| 		require("../../update")(done, true, () => { | ||||
| 			promise.then(res => { | ||||
| 				const links = window.document.getElementsByTagName("link"); | ||||
| 				let href = links[0].href; | ||||
| 				expect(href).toBe("https://test.cases/path/style_css.css"); | ||||
| 				href = href | ||||
| 					.replace(/^https:\/\/test\.cases\/path\//, "") | ||||
| 					.replace(/^https:\/\/example\.com\//, ""); | ||||
| 				let sheet = getFile(href); | ||||
| 				expect(sheet).toContain("color: red;"); | ||||
| 
 | ||||
| 				module.hot.accept("./style.css", () => { | ||||
| 					const links = window.document.getElementsByTagName("link"); | ||||
| 					let href = links[0].href; | ||||
| 					expect(href).toContain("https://test.cases/path/style_css.css?hmr"); | ||||
| 					href = href | ||||
| 						.replace(/^https:\/\/test\.cases\/path\//, "") | ||||
| 						.replace(/^https:\/\/example\.com\//, "") | ||||
| 						.split("?")[0]; | ||||
| 					let sheet = getFile(href); | ||||
| 					expect(sheet).toContain("color: blue;"); | ||||
| 					done(); | ||||
| 				}); | ||||
| 
 | ||||
| 				NEXT(require("../../update")(done)); | ||||
| 			}); | ||||
| 		}) | ||||
| 	); | ||||
| }); | ||||
|  | @ -0,0 +1,11 @@ | |||
| html { | ||||
| 	color: red; | ||||
| } | ||||
| --- | ||||
| html { | ||||
| 	color: red; | ||||
| } | ||||
| --- | ||||
| html { | ||||
| 	color: blue; | ||||
| } | ||||
|  | @ -0,0 +1,5 @@ | |||
| module.exports = function (config) { | ||||
| 	if (config.target !== "web") { | ||||
| 		return false; | ||||
| 	} | ||||
| }; | ||||
|  | @ -0,0 +1,19 @@ | |||
| /** @type {import("../../../../").Configuration} */ | ||||
| module.exports = { | ||||
| 	mode: "development", | ||||
| 	devtool: false, | ||||
| 	output: { | ||||
| 		cssFilename: "[name].css", | ||||
| 		cssChunkFilename: "[name].css" | ||||
| 	}, | ||||
| 	experiments: { | ||||
| 		css: true, | ||||
| 		lazyCompilation: { | ||||
| 			entries: false, | ||||
| 			imports: true | ||||
| 		} | ||||
| 	}, | ||||
| 	node: { | ||||
| 		__dirname: false | ||||
| 	} | ||||
| }; | ||||
|  | @ -7617,6 +7617,7 @@ declare interface KnownBuildMeta { | |||
| 	async?: boolean; | ||||
| 	sideEffectFree?: boolean; | ||||
| 	exportsFinalName?: Record<string, string>; | ||||
| 	isCSSModule?: boolean; | ||||
| } | ||||
| declare interface KnownCreateStatsOptionsContext { | ||||
| 	forToString?: boolean; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue