Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1489b91

Browse filesBrowse files
committed
allow to generate only exports for css in node
add more options to the DeterministicModuleIdsPlugin to allow to opt-in into a fixed mode optimize module iterations for module id assignment
1 parent e550b2c commit 1489b91
Copy full SHA for 1489b91
Expand file treeCollapse file tree

24 files changed

+617
-126
lines changed

‎declarations/WebpackOptions.d.ts

Copy file name to clipboardExpand all lines: declarations/WebpackOptions.d.ts
+17-4Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2723,6 +2723,15 @@ export interface AssetResourceGeneratorOptions {
27232723
*/
27242724
publicPath?: RawPublicPath;
27252725
}
2726+
/**
2727+
* Options for css handling.
2728+
*/
2729+
export interface CssExperimentOptions {
2730+
/**
2731+
* Avoid generating and loading a stylesheet and only embed exports from css into output javascript files.
2732+
*/
2733+
exportsOnly?: boolean;
2734+
}
27262735
/**
27272736
* Generator options for css modules.
27282737
*/
@@ -2809,10 +2818,6 @@ export interface ExperimentsCommon {
28092818
* Enable additional in memory caching of modules that are unchanged and reference only unchanged modules.
28102819
*/
28112820
cacheUnaffected?: boolean;
2812-
/**
2813-
* Enable css support.
2814-
*/
2815-
css?: boolean;
28162821
/**
28172822
* Apply defaults of next major version.
28182823
*/
@@ -3453,6 +3458,10 @@ export interface ExperimentsExtra {
34533458
* Build http(s): urls using a lockfile and resource content cache.
34543459
*/
34553460
buildHttp?: HttpUriAllowedUris | HttpUriOptions;
3461+
/**
3462+
* Enable css support.
3463+
*/
3464+
css?: boolean | CssExperimentOptions;
34563465
/**
34573466
* Compile entrypoints and import()s only when they are accessed.
34583467
*/
@@ -3466,6 +3475,10 @@ export interface ExperimentsNormalizedExtra {
34663475
* Build http(s): urls using a lockfile and resource content cache.
34673476
*/
34683477
buildHttp?: HttpUriOptions;
3478+
/**
3479+
* Enable css support.
3480+
*/
3481+
css?: CssExperimentOptions;
34693482
/**
34703483
* Compile entrypoints and import()s only when they are accessed.
34713484
*/

‎lib/WebpackOptionsApply.js

Copy file name to clipboardExpand all lines: lib/WebpackOptionsApply.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ class WebpackOptionsApply extends OptionsApply {
291291

292292
if (options.experiments.css) {
293293
const CssModulesPlugin = require("./css/CssModulesPlugin");
294-
new CssModulesPlugin().apply(compiler);
294+
new CssModulesPlugin(options.experiments.css).apply(compiler);
295295
}
296296

297297
if (options.experiments.lazyCompilation) {

‎lib/config/defaults.js

Copy file name to clipboardExpand all lines: lib/config/defaults.js
+22-5Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const {
1616
} = require("./target");
1717

1818
/** @typedef {import("../../declarations/WebpackOptions").CacheOptionsNormalized} CacheOptions */
19+
/** @typedef {import("../../declarations/WebpackOptions").CssExperimentOptions} CssExperimentOptions */
1920
/** @typedef {import("../../declarations/WebpackOptions").EntryDescription} EntryDescription */
2021
/** @typedef {import("../../declarations/WebpackOptions").EntryNormalized} Entry */
2122
/** @typedef {import("../../declarations/WebpackOptions").Experiments} Experiments */
@@ -160,7 +161,11 @@ const applyWebpackOptionsDefaults = options => {
160161
D(options, "recordsInputPath", false);
161162
D(options, "recordsOutputPath", false);
162163

163-
applyExperimentsDefaults(options.experiments, { production, development });
164+
applyExperimentsDefaults(options.experiments, {
165+
production,
166+
development,
167+
targetProperties
168+
});
164169

165170
const futureDefaults = options.experiments.futureDefaults;
166171

@@ -265,9 +270,13 @@ const applyWebpackOptionsDefaults = options => {
265270
* @param {Object} options options
266271
* @param {boolean} options.production is production
267272
* @param {boolean} options.development is development mode
273+
* @param {TargetProperties | false} options.targetProperties target properties
268274
* @returns {void}
269275
*/
270-
const applyExperimentsDefaults = (experiments, { production, development }) => {
276+
const applyExperimentsDefaults = (
277+
experiments,
278+
{ production, development, targetProperties }
279+
) => {
271280
D(experiments, "futureDefaults", false);
272281
D(experiments, "backCompat", !experiments.futureDefaults);
273282
D(experiments, "topLevelAwait", experiments.futureDefaults);
@@ -278,12 +287,20 @@ const applyExperimentsDefaults = (experiments, { production, development }) => {
278287
D(experiments, "lazyCompilation", undefined);
279288
D(experiments, "buildHttp", undefined);
280289
D(experiments, "cacheUnaffected", experiments.futureDefaults);
281-
D(experiments, "css", experiments.futureDefaults);
290+
F(experiments, "css", () => (experiments.futureDefaults ? {} : undefined));
282291

283292
if (typeof experiments.buildHttp === "object") {
284293
D(experiments.buildHttp, "frozen", production);
285294
D(experiments.buildHttp, "upgrade", false);
286295
}
296+
297+
if (typeof experiments.css === "object") {
298+
D(
299+
experiments.css,
300+
"exportsOnly",
301+
!targetProperties || !targetProperties.document
302+
);
303+
}
287304
};
288305

289306
/**
@@ -461,7 +478,7 @@ const applyJavascriptParserOptionsDefaults = (
461478
* @param {boolean} options.cache is caching enabled
462479
* @param {boolean} options.syncWebAssembly is syncWebAssembly enabled
463480
* @param {boolean} options.asyncWebAssembly is asyncWebAssembly enabled
464-
* @param {boolean} options.css is css enabled
481+
* @param {CssExperimentOptions} options.css is css enabled
465482
* @param {boolean} options.futureDefaults is future defaults enabled
466483
* @returns {void}
467484
*/
@@ -1083,7 +1100,7 @@ const applyPerformanceDefaults = (performance, { production }) => {
10831100
* @param {Object} options options
10841101
* @param {boolean} options.production is production
10851102
* @param {boolean} options.development is development
1086-
* @param {boolean} options.css is css enabled
1103+
* @param {CssExperimentOptions} options.css is css enabled
10871104
* @param {boolean} options.records using records
10881105
* @returns {void}
10891106
*/

‎lib/config/normalization.js

Copy file name to clipboardExpand all lines: lib/config/normalization.js
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ const getNormalizedWebpackOptions = config => {
180180
experiments.lazyCompilation,
181181
options =>
182182
options === true ? {} : options === false ? undefined : options
183+
),
184+
css: optionalNestedConfig(experiments.css, options =>
185+
options === true ? {} : options === false ? undefined : options
183186
)
184187
})),
185188
externals: config.externals,

‎lib/css/CssExportsGenerator.js

Copy file name to clipboard
+145Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Sergey Melyukov @smelukov
4+
*/
5+
6+
"use strict";
7+
8+
const { ReplaceSource, RawSource, ConcatSource } = require("webpack-sources");
9+
const { UsageState } = require("../ExportsInfo");
10+
const Generator = require("../Generator");
11+
const RuntimeGlobals = require("../RuntimeGlobals");
12+
const Template = require("../Template");
13+
14+
/** @typedef {import("webpack-sources").Source} Source */
15+
/** @typedef {import("../Dependency")} Dependency */
16+
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
17+
/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */
18+
/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
19+
/** @typedef {import("../NormalModule")} NormalModule */
20+
/** @typedef {import("../util/Hash")} Hash */
21+
22+
const TYPES = new Set(["javascript"]);
23+
24+
class CssExportsGenerator extends Generator {
25+
constructor() {
26+
super();
27+
}
28+
29+
/**
30+
* @param {NormalModule} module module for which the bailout reason should be determined
31+
* @param {ConcatenationBailoutReasonContext} context context
32+
* @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
33+
*/
34+
getConcatenationBailoutReason(module, context) {
35+
return undefined;
36+
}
37+
38+
/**
39+
* @param {NormalModule} module module for which the code should be generated
40+
* @param {GenerateContext} generateContext context for generate
41+
* @returns {Source} generated code
42+
*/
43+
generate(module, generateContext) {
44+
const source = new ReplaceSource(new RawSource(""));
45+
const initFragments = [];
46+
const cssExports = new Map();
47+
48+
generateContext.runtimeRequirements.add(RuntimeGlobals.module);
49+
50+
const runtimeRequirements = new Set();
51+
52+
const templateContext = {
53+
runtimeTemplate: generateContext.runtimeTemplate,
54+
dependencyTemplates: generateContext.dependencyTemplates,
55+
moduleGraph: generateContext.moduleGraph,
56+
chunkGraph: generateContext.chunkGraph,
57+
module,
58+
runtime: generateContext.runtime,
59+
runtimeRequirements: runtimeRequirements,
60+
concatenationScope: generateContext.concatenationScope,
61+
codeGenerationResults: generateContext.codeGenerationResults,
62+
initFragments,
63+
cssExports
64+
};
65+
66+
const handleDependency = dependency => {
67+
const constructor = /** @type {new (...args: any[]) => Dependency} */ (
68+
dependency.constructor
69+
);
70+
const template = generateContext.dependencyTemplates.get(constructor);
71+
if (!template) {
72+
throw new Error(
73+
"No template for dependency: " + dependency.constructor.name
74+
);
75+
}
76+
77+
template.apply(dependency, source, templateContext);
78+
};
79+
module.dependencies.forEach(handleDependency);
80+
81+
if (generateContext.concatenationScope) {
82+
const source = new ConcatSource();
83+
const usedIdentifiers = new Set();
84+
for (const [k, v] of cssExports) {
85+
let identifier = Template.toIdentifier(k);
86+
let i = 0;
87+
while (usedIdentifiers.has(identifier)) {
88+
identifier = Template.toIdentifier(k + i);
89+
}
90+
usedIdentifiers.add(identifier);
91+
generateContext.concatenationScope.registerExport(k, identifier);
92+
source.add(
93+
`${
94+
generateContext.runtimeTemplate.supportsConst ? "const" : "var"
95+
} ${identifier} = ${JSON.stringify(v)};\n`
96+
);
97+
}
98+
return source;
99+
} else {
100+
const otherUsed =
101+
generateContext.moduleGraph
102+
.getExportsInfo(module)
103+
.otherExportsInfo.getUsed(generateContext.runtime) !==
104+
UsageState.Unused;
105+
if (otherUsed) {
106+
generateContext.runtimeRequirements.add(
107+
RuntimeGlobals.makeNamespaceObject
108+
);
109+
}
110+
return new RawSource(
111+
`${otherUsed ? `${RuntimeGlobals.makeNamespaceObject}(` : ""}${
112+
module.moduleArgument
113+
}.exports = {\n${Array.from(
114+
cssExports,
115+
([k, v]) => `\t${JSON.stringify(k)}: ${JSON.stringify(v)}`
116+
).join(",\n")}\n}${otherUsed ? ")" : ""};`
117+
);
118+
}
119+
}
120+
121+
/**
122+
* @param {NormalModule} module fresh module
123+
* @returns {Set<string>} available types (do not mutate)
124+
*/
125+
getTypes(module) {
126+
return TYPES;
127+
}
128+
129+
/**
130+
* @param {NormalModule} module the module
131+
* @param {string=} type source type
132+
* @returns {number} estimate size of the module
133+
*/
134+
getSize(module, type) {
135+
return 42;
136+
}
137+
138+
/**
139+
* @param {Hash} hash hash that will be modified
140+
* @param {UpdateHashContext} updateHashContext context for updating hash
141+
*/
142+
updateHash(hash, { module }) {}
143+
}
144+
145+
module.exports = CssExportsGenerator;

‎lib/css/CssLoadingRuntimeModule.js

Copy file name to clipboardExpand all lines: lib/css/CssLoadingRuntimeModule.js
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,7 @@ class CssLoadingRuntimeModule extends RuntimeModule {
192192
"exports, module",
193193
`module.exports = exports;`
194194
)}).bind(null, exports); ${
195-
withHmr
196-
? "moduleIds.push(token); target[token].cssExports = exports; "
197-
: ""
195+
withHmr ? "moduleIds.push(token); " : ""
198196
}token = ""; exports = {}; exportsWithId.length = 0; }`,
199197
`else if(cc == ${cc("\\")}) { token += data[++i] }`,
200198
`else { token += data[i]; }`

‎lib/css/CssModulesPlugin.js

Copy file name to clipboardExpand all lines: lib/css/CssModulesPlugin.js
+17-3Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ const { compareModulesByIdentifier } = require("../util/comparators");
1919
const createSchemaValidation = require("../util/create-schema-validation");
2020
const createHash = require("../util/createHash");
2121
const memoize = require("../util/memoize");
22+
const CssExportsGenerator = require("./CssExportsGenerator");
2223
const CssGenerator = require("./CssGenerator");
2324
const CssParser = require("./CssParser");
2425

2526
/** @typedef {import("webpack-sources").Source} Source */
27+
/** @typedef {import("../../declarations/WebpackOptions").CssExperimentOptions} CssExperimentOptions */
2628
/** @typedef {import("../Chunk")} Chunk */
2729
/** @typedef {import("../Compiler")} Compiler */
2830
/** @typedef {import("../Module")} Module */
@@ -70,6 +72,12 @@ const escapeCss = (str, omitOptionalUnderscore) => {
7072
const plugin = "CssModulesPlugin";
7173

7274
class CssModulesPlugin {
75+
/**
76+
* @param {CssExperimentOptions} options options
77+
*/
78+
constructor({ exportsOnly = false }) {
79+
this._exportsOnly = exportsOnly;
80+
}
7381
/**
7482
* Apply the plugin
7583
* @param {Compiler} compiler the compiler instance
@@ -143,19 +151,25 @@ class CssModulesPlugin {
143151
.for("css")
144152
.tap(plugin, generatorOptions => {
145153
validateGeneratorOptions(generatorOptions);
146-
return new CssGenerator();
154+
return this._exportsOnly
155+
? new CssExportsGenerator()
156+
: new CssGenerator();
147157
});
148158
normalModuleFactory.hooks.createGenerator
149159
.for("css/global")
150160
.tap(plugin, generatorOptions => {
151161
validateGeneratorOptions(generatorOptions);
152-
return new CssGenerator();
162+
return this._exportsOnly
163+
? new CssExportsGenerator()
164+
: new CssGenerator();
153165
});
154166
normalModuleFactory.hooks.createGenerator
155167
.for("css/module")
156168
.tap(plugin, generatorOptions => {
157169
validateGeneratorOptions(generatorOptions);
158-
return new CssGenerator();
170+
return this._exportsOnly
171+
? new CssExportsGenerator()
172+
: new CssGenerator();
159173
});
160174
const orderedCssModulesPerChunk = new WeakMap();
161175
compilation.hooks.afterCodeGeneration.tap("CssModulesPlugin", () => {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.