Skip to content

Commit 453e5ca

Browse files
committed
add support for :export {} block
1 parent b9c6691 commit 453e5ca

14 files changed

Lines changed: 530 additions & 38 deletions

lib/DependencyTemplate.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@
3232
* @property {CodeGenerationResults} codeGenerationResults the code generation results
3333
*/
3434

35+
/**
36+
* @typedef {Object} CssDependencyTemplateContextExtras
37+
* @property {Map<string, string>} cssExports the css exports
38+
*/
39+
40+
/** @typedef {DependencyTemplateContext & CssDependencyTemplateContextExtras} CssDependencyTemplateContext */
41+
3542
class DependencyTemplate {
3643
/* istanbul ignore next */
3744
/**

lib/config/defaults.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,9 +599,27 @@ const applyModuleDefaults = (
599599
preferRelative: true
600600
}
601601
};
602+
const cssModulesRule = {
603+
type: "css/module",
604+
resolve: {
605+
fullySpecified: true
606+
}
607+
};
602608
rules.push({
603609
test: /\.css$/i,
604-
...cssRule
610+
oneOf: [
611+
{
612+
test: /\.module\.css$/i,
613+
...cssModulesRule
614+
},
615+
{
616+
...cssRule
617+
}
618+
]
619+
});
620+
rules.push({
621+
mimetype: "text/css+module",
622+
...cssModulesRule
605623
});
606624
rules.push({
607625
mimetype: "text/css",

lib/css/CssGenerator.js

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,23 @@ class CssGenerator extends Generator {
3232
const originalSource = module.originalSource();
3333
const source = new ReplaceSource(originalSource);
3434
const initFragments = [];
35+
const cssExports = new Map();
3536

36-
for (const dependency of module.dependencies) {
37+
const templateContext = {
38+
runtimeTemplate: generateContext.runtimeTemplate,
39+
dependencyTemplates: generateContext.dependencyTemplates,
40+
moduleGraph: generateContext.moduleGraph,
41+
chunkGraph: generateContext.chunkGraph,
42+
module,
43+
runtime: generateContext.runtime,
44+
runtimeRequirements: generateContext.runtimeRequirements,
45+
concatenationScope: generateContext.concatenationScope,
46+
codeGenerationResults: generateContext.codeGenerationResults,
47+
initFragments,
48+
cssExports
49+
};
50+
51+
const handleDependency = dependency => {
3752
const constructor = /** @type {new (...args: any[]) => Dependency} */ (
3853
dependency.constructor
3954
);
@@ -44,21 +59,17 @@ class CssGenerator extends Generator {
4459
);
4560
}
4661

47-
const templateContext = {
48-
runtimeTemplate: generateContext.runtimeTemplate,
49-
dependencyTemplates: generateContext.dependencyTemplates,
50-
moduleGraph: generateContext.moduleGraph,
51-
chunkGraph: generateContext.chunkGraph,
52-
module,
53-
runtime: generateContext.runtime,
54-
runtimeRequirements: generateContext.runtimeRequirements,
55-
concatenationScope: generateContext.concatenationScope,
56-
codeGenerationResults: generateContext.codeGenerationResults,
57-
initFragments
58-
};
59-
6062
template.apply(dependency, source, templateContext);
63+
};
64+
module.dependencies.forEach(handleDependency);
65+
if (module.presentationalDependencies !== undefined)
66+
module.presentationalDependencies.forEach(handleDependency);
67+
68+
if (cssExports.size > 0) {
69+
const data = generateContext.getData();
70+
data.set("css-exports", cssExports);
6171
}
72+
6273
return InitFragment.addToSource(source, initFragments, generateContext);
6374
}
6475

lib/css/CssLoadingRuntimeModule.js

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ class CssLoadingRuntimeModule extends RuntimeModule {
120120
: ""
121121
]);
122122

123+
const cc = str => str.charCodeAt(0);
124+
123125
return Template.asString([
124126
"// object to store loaded and loading chunks",
125127
"// undefined = chunk not loaded, null = chunk preloaded/prefetched",
@@ -132,27 +134,29 @@ class CssLoadingRuntimeModule extends RuntimeModule {
132134
).join(",")}};`,
133135
"",
134136
`var loadCssChunkData = ${runtimeTemplate.basicFunction("chunkId, link", [
135-
'var data, tokens = [], token = "", i = 0;',
137+
'var data, token = "", token2, exports = {}, i = 0, cc = 1;',
136138
"try { if(!link) link = loadStylesheet(chunkId); data = link.sheet.cssRules; data = data[data.length - 1].style; } catch(e) { data = getComputedStyle(document.head); }",
137139
'data = data.getPropertyValue("--webpack-" + chunkId);',
138140
"if(!data) return;",
139-
"for(; i < data.length; i++) {",
141+
"for(; cc; i++) {",
140142
Template.indent([
141-
"var cc = data.charCodeAt(i);",
142-
'if(cc == 44) { tokens.push(token); token = ""; }',
143-
"else if(cc == 92) { token += data[++i] }",
144-
"else { token += data[i]; }"
143+
"cc = data.charCodeAt(i);",
144+
`if(cc == ${cc("(")}) { token2 = token; token = ""; }`,
145+
`else if(cc == ${cc(
146+
")"
147+
)}) { exports[token2.replace(/^_/, "")] = token.replace(/^_/, ""); token = ""; }`,
148+
`else if(!cc || cc == ${cc(",")}) { ${
149+
RuntimeGlobals.makeNamespaceObject
150+
}(exports); ${
151+
RuntimeGlobals.moduleFactories
152+
}[token.replace(/^_/, "")] = (${runtimeTemplate.basicFunction(
153+
"exports, module",
154+
`module.exports = exports;`
155+
)}).bind(null, exports); token = ""; exports = {}; }`,
156+
`else if(cc == ${cc("\\")}) { token += data[++i] }`,
157+
`else { token += data[i]; }`
145158
]),
146159
"}",
147-
"token && tokens.push(token);",
148-
`tokens.forEach(${runtimeTemplate.basicFunction("token", [
149-
`${
150-
RuntimeGlobals.moduleFactories
151-
}[token.replace(/^_/, "")] = ${runtimeTemplate.basicFunction(
152-
"module, exports",
153-
[`${RuntimeGlobals.makeNamespaceObject}(exports);`]
154-
)};`
155-
])});`,
156160
"installedChunks[chunkId] = 0;"
157161
])}`,
158162
'var loadingAttribute = "data-webpack-loading";',

lib/css/CssModulesPlugin.js

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
const { ConcatSource } = require("webpack-sources");
99
const HotUpdateChunk = require("../HotUpdateChunk");
1010
const RuntimeGlobals = require("../RuntimeGlobals");
11+
const CssExportDependency = require("../dependencies/CssExportDependency");
1112
const CssImportDependency = require("../dependencies/CssImportDependency");
1213
const CssUrlDependency = require("../dependencies/CssUrlDependency");
1314
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
@@ -85,6 +86,10 @@ class CssModulesPlugin {
8586
CssUrlDependency,
8687
new CssUrlDependency.Template()
8788
);
89+
compilation.dependencyTemplates.set(
90+
CssExportDependency,
91+
new CssExportDependency.Template()
92+
);
8893
compilation.dependencyFactories.set(
8994
CssImportDependency,
9095
normalModuleFactory
@@ -103,12 +108,36 @@ class CssModulesPlugin {
103108
validateParserOptions(parserOptions);
104109
return new CssParser();
105110
});
111+
normalModuleFactory.hooks.createParser
112+
.for("css/global")
113+
.tap(plugin, parserOptions => {
114+
validateParserOptions(parserOptions);
115+
return new CssParser({ allowPseudoBlocks: false });
116+
});
117+
normalModuleFactory.hooks.createParser
118+
.for("css/module")
119+
.tap(plugin, parserOptions => {
120+
validateParserOptions(parserOptions);
121+
return new CssParser({ allowPseudoBlocks: true });
122+
});
106123
normalModuleFactory.hooks.createGenerator
107124
.for("css")
108125
.tap(plugin, generatorOptions => {
109126
validateGeneratorOptions(generatorOptions);
110127
return new CssGenerator();
111128
});
129+
normalModuleFactory.hooks.createGenerator
130+
.for("css/global")
131+
.tap(plugin, generatorOptions => {
132+
validateGeneratorOptions(generatorOptions);
133+
return new CssGenerator();
134+
});
135+
normalModuleFactory.hooks.createGenerator
136+
.for("css/module")
137+
.tap(plugin, generatorOptions => {
138+
validateGeneratorOptions(generatorOptions);
139+
return new CssGenerator();
140+
});
112141
compilation.hooks.contentHash.tap("JavascriptModulesPlugin", chunk => {
113142
const {
114143
chunkGraph,
@@ -204,25 +233,43 @@ class CssModulesPlugin {
204233
renderChunk({ chunk, chunkGraph, codeGenerationResults }) {
205234
const modules = this.getOrderedChunkCssModules(chunk, chunkGraph);
206235
const source = new ConcatSource();
236+
const metaData = [];
207237
for (const module of modules) {
208238
try {
239+
const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
240+
209241
const s =
210-
codeGenerationResults.getSource(module, chunk.runtime, "css") ||
211-
codeGenerationResults.getSource(module, chunk.runtime, "css-import");
242+
codeGenResult.sources.get("css") ||
243+
codeGenResult.sources.get("css-import");
212244
if (s) {
213245
source.add(s);
214246
source.add("\n");
215247
}
248+
const exports =
249+
codeGenResult.data && codeGenResult.data.get("css-exports");
250+
metaData.push(
251+
`${
252+
exports
253+
? Array.from(
254+
exports,
255+
([n, v]) =>
256+
`${escapeCssIdentifierPart(
257+
n,
258+
true
259+
)}(${escapeCssIdentifierPart(v, true)})`
260+
).join("")
261+
: ""
262+
}${escapeCssIdentifierPart(chunkGraph.getModuleId(module), true)}`
263+
);
216264
} catch (e) {
217265
e.message += `\nduring rendering of css ${module.identifier()}`;
218266
throw e;
219267
}
220268
}
221269
source.add(
222-
`head{--webpack-${escapeCssIdentifierPart(chunk.id)}:${Array.from(
223-
modules,
224-
m => `${escapeCssIdentifierPart(chunkGraph.getModuleId(m), true)}`
225-
).join(",")};}`
270+
`head{--webpack-${escapeCssIdentifierPart(chunk.id)}:${metaData.join(
271+
","
272+
)};}`
226273
);
227274
return source;
228275
}

0 commit comments

Comments
 (0)