feat: refactoring project

This commit is contained in:
Carlos
2024-11-23 14:56:07 -05:00
parent f0c2a50c18
commit 1c6db5818d
2351 changed files with 39323 additions and 60326 deletions

View File

@@ -8,18 +8,21 @@
const { ReplaceSource, RawSource, ConcatSource } = require("webpack-sources");
const { UsageState } = require("../ExportsInfo");
const Generator = require("../Generator");
const { JS_TYPES } = require("../ModuleSourceTypesConstants");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").CssGeneratorExportsConvention} CssGeneratorExportsConvention */
/** @typedef {import("../../declarations/WebpackOptions").CssGeneratorLocalIdentName} CssGeneratorLocalIdentName */
/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../DependencyTemplate").CssDependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../DependencyTemplate").CssExportsData} CssExportsData */
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */
/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
/** @typedef {import("../Module").SourceTypes} SourceTypes */
/** @typedef {import("../NormalModule")} NormalModule */
/** @typedef {import("../util/Hash")} Hash */
@@ -28,19 +31,15 @@ const Template = require("../Template");
* @typedef {import("../InitFragment")<T>} InitFragment
*/
const TYPES = new Set(["javascript"]);
class CssExportsGenerator extends Generator {
/**
* @param {CssGeneratorExportsConvention | undefined} convention the convention of the exports name
* @param {CssGeneratorLocalIdentName | undefined} localIdentName css export local ident name
* @param {CssGeneratorExportsConvention} convention the convention of the exports name
* @param {CssGeneratorLocalIdentName} localIdentName css export local ident name
* @param {boolean} esModule whether to use ES modules syntax
*/
constructor(convention, localIdentName, esModule) {
super();
/** @type {CssGeneratorExportsConvention | undefined} */
this.convention = convention;
/** @type {CssGeneratorLocalIdentName | undefined} */
this.localIdentName = localIdentName;
/** @type {boolean} */
this.esModule = esModule;
@@ -68,11 +67,11 @@ class CssExportsGenerator extends Generator {
/**
* @param {NormalModule} module module for which the code should be generated
* @param {GenerateContext} generateContext context for generate
* @returns {Source} generated code
* @returns {Source | null} generated code
*/
generate(module, generateContext) {
const source = new ReplaceSource(new RawSource(""));
/** @type {InitFragment<TODO>[]} */
/** @type {InitFragment<GenerateContext>[]} */
const initFragments = [];
/** @type {CssExportsData} */
const cssExportsData = {
@@ -82,6 +81,7 @@ class CssExportsGenerator extends Generator {
generateContext.runtimeRequirements.add(RuntimeGlobals.module);
/** @type {InitFragment<GenerateContext>[] | undefined} */
let chunkInitFragments;
const runtimeRequirements = new Set();
@@ -93,14 +93,18 @@ class CssExportsGenerator extends Generator {
chunkGraph: generateContext.chunkGraph,
module,
runtime: generateContext.runtime,
runtimeRequirements: runtimeRequirements,
runtimeRequirements,
concatenationScope: generateContext.concatenationScope,
codeGenerationResults: generateContext.codeGenerationResults,
codeGenerationResults:
/** @type {CodeGenerationResults} */
(generateContext.codeGenerationResults),
initFragments,
cssExportsData,
get chunkInitFragments() {
if (!chunkInitFragments) {
const data = generateContext.getData();
const data =
/** @type {NonNullable<GenerateContext["getData"]>} */
(generateContext.getData)();
chunkInitFragments = data.get("chunkInitFragments");
if (!chunkInitFragments) {
chunkInitFragments = [];
@@ -122,20 +126,23 @@ class CssExportsGenerator extends Generator {
const template = generateContext.dependencyTemplates.get(constructor);
if (!template) {
throw new Error(
"No template for dependency: " + dependency.constructor.name
`No template for dependency: ${dependency.constructor.name}`
);
}
template.apply(dependency, source, templateContext);
};
module.dependencies.forEach(handleDependency);
for (const dependency of module.dependencies) {
handleDependency(dependency);
}
if (generateContext.concatenationScope) {
const source = new ConcatSource();
const usedIdentifiers = new Set();
for (const [name, v] of cssExportsData.exports) {
let identifier = Template.toIdentifier(name);
let i = 0;
const i = 0;
while (usedIdentifiers.has(identifier)) {
identifier = Template.toIdentifier(name + i);
}
@@ -148,36 +155,35 @@ class CssExportsGenerator extends Generator {
);
}
return source;
} else {
const needNsObj =
this.esModule &&
generateContext.moduleGraph
.getExportsInfo(module)
.otherExportsInfo.getUsed(generateContext.runtime) !==
UsageState.Unused;
if (needNsObj) {
generateContext.runtimeRequirements.add(
RuntimeGlobals.makeNamespaceObject
);
}
const exports = [];
for (let [name, v] of cssExportsData.exports) {
exports.push(`\t${JSON.stringify(name)}: ${JSON.stringify(v)}`);
}
return new RawSource(
`${needNsObj ? `${RuntimeGlobals.makeNamespaceObject}(` : ""}${
module.moduleArgument
}.exports = {\n${exports.join(",\n")}\n}${needNsObj ? ")" : ""};`
}
const needNsObj =
this.esModule &&
generateContext.moduleGraph
.getExportsInfo(module)
.otherExportsInfo.getUsed(generateContext.runtime) !==
UsageState.Unused;
if (needNsObj) {
generateContext.runtimeRequirements.add(
RuntimeGlobals.makeNamespaceObject
);
}
const exports = [];
for (const [name, v] of cssExportsData.exports) {
exports.push(`\t${JSON.stringify(name)}: ${JSON.stringify(v)}`);
}
return new RawSource(
`${needNsObj ? `${RuntimeGlobals.makeNamespaceObject}(` : ""}${
module.moduleArgument
}.exports = {\n${exports.join(",\n")}\n}${needNsObj ? ")" : ""};`
);
}
/**
* @param {NormalModule} module fresh module
* @returns {Set<string>} available types (do not mutate)
* @returns {SourceTypes} available types (do not mutate)
*/
getTypes(module) {
return TYPES;
return JS_TYPES;
}
/**

View File

@@ -8,32 +8,31 @@
const { ReplaceSource } = require("webpack-sources");
const Generator = require("../Generator");
const InitFragment = require("../InitFragment");
const { CSS_TYPES } = require("../ModuleSourceTypesConstants");
const RuntimeGlobals = require("../RuntimeGlobals");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").CssGeneratorExportsConvention} CssGeneratorExportsConvention */
/** @typedef {import("../../declarations/WebpackOptions").CssGeneratorLocalIdentName} CssGeneratorLocalIdentName */
/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../DependencyTemplate").CssDependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../DependencyTemplate").CssExportsData} CssExportsData */
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */
/** @typedef {import("../Module").SourceTypes} SourceTypes */
/** @typedef {import("../NormalModule")} NormalModule */
/** @typedef {import("../util/Hash")} Hash */
const TYPES = new Set(["css"]);
class CssGenerator extends Generator {
/**
* @param {CssGeneratorExportsConvention | undefined} convention the convention of the exports name
* @param {CssGeneratorLocalIdentName | undefined} localIdentName css export local ident name
* @param {CssGeneratorExportsConvention} convention the convention of the exports name
* @param {CssGeneratorLocalIdentName} localIdentName css export local ident name
* @param {boolean} esModule whether to use ES modules syntax
*/
constructor(convention, localIdentName, esModule) {
super();
/** @type {CssGeneratorExportsConvention | undefined} */
this.convention = convention;
/** @type {CssGeneratorLocalIdentName | undefined} */
this.localIdentName = localIdentName;
/** @type {boolean} */
this.esModule = esModule;
@@ -42,12 +41,12 @@ class CssGenerator extends Generator {
/**
* @param {NormalModule} module module for which the code should be generated
* @param {GenerateContext} generateContext context for generate
* @returns {Source} generated code
* @returns {Source | null} generated code
*/
generate(module, generateContext) {
const originalSource = /** @type {Source} */ (module.originalSource());
const source = new ReplaceSource(originalSource);
/** @type {InitFragment[]} */
/** @type {InitFragment<GenerateContext>[]} */
const initFragments = [];
/** @type {CssExportsData} */
const cssExportsData = {
@@ -57,6 +56,7 @@ class CssGenerator extends Generator {
generateContext.runtimeRequirements.add(RuntimeGlobals.hasCssModules);
/** @type {InitFragment<GenerateContext>[] | undefined} */
let chunkInitFragments;
/** @type {DependencyTemplateContext} */
const templateContext = {
@@ -68,12 +68,16 @@ class CssGenerator extends Generator {
runtime: generateContext.runtime,
runtimeRequirements: generateContext.runtimeRequirements,
concatenationScope: generateContext.concatenationScope,
codeGenerationResults: generateContext.codeGenerationResults,
codeGenerationResults:
/** @type {CodeGenerationResults} */
(generateContext.codeGenerationResults),
initFragments,
cssExportsData,
get chunkInitFragments() {
if (!chunkInitFragments) {
const data = generateContext.getData();
const data =
/** @type {NonNullable<GenerateContext["getData"]>} */
(generateContext.getData)();
chunkInitFragments = data.get("chunkInitFragments");
if (!chunkInitFragments) {
chunkInitFragments = [];
@@ -89,23 +93,30 @@ class CssGenerator extends Generator {
* @param {Dependency} dependency dependency
*/
const handleDependency = dependency => {
const constructor = /** @type {new (...args: any[]) => Dependency} */ (
dependency.constructor
);
const constructor =
/** @type {new (...args: EXPECTED_ANY[]) => Dependency} */
(dependency.constructor);
const template = generateContext.dependencyTemplates.get(constructor);
if (!template) {
throw new Error(
"No template for dependency: " + dependency.constructor.name
`No template for dependency: ${dependency.constructor.name}`
);
}
template.apply(dependency, source, templateContext);
};
module.dependencies.forEach(handleDependency);
if (module.presentationalDependencies !== undefined)
module.presentationalDependencies.forEach(handleDependency);
for (const dependency of module.dependencies) {
handleDependency(dependency);
}
if (module.presentationalDependencies !== undefined) {
for (const dependency of module.presentationalDependencies) {
handleDependency(dependency);
}
}
const data = generateContext.getData();
const data =
/** @type {NonNullable<GenerateContext["getData"]>} */
(generateContext.getData)();
data.set("css-exports", cssExportsData);
return InitFragment.addToSource(source, initFragments, generateContext);
@@ -113,10 +124,10 @@ class CssGenerator extends Generator {
/**
* @param {NormalModule} module fresh module
* @returns {Set<string>} available types (do not mutate)
* @returns {SourceTypes} available types (do not mutate)
*/
getTypes(module) {
return TYPES;
return CSS_TYPES;
}
/**

View File

@@ -86,19 +86,13 @@ class CssLoadingRuntimeModule extends RuntimeModule {
* @returns {boolean} true, if the chunk has css
*/
(chunk, chunkGraph) =>
!!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css")
Boolean(chunkGraph.getChunkModulesIterableBySourceType(chunk, "css"))
);
const hasCssMatcher = compileBooleanMatcher(conditionMap);
const withLoading =
_runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers) &&
hasCssMatcher !== false;
const withPrefetch = this._runtimeRequirements.has(
RuntimeGlobals.prefetchChunkHandlers
);
const withPreload = this._runtimeRequirements.has(
RuntimeGlobals.preloadChunkHandlers
);
/** @type {boolean} */
const withHmr = _runtimeRequirements.has(
RuntimeGlobals.hmrDownloadUpdateHandlers
@@ -118,6 +112,13 @@ class CssLoadingRuntimeModule extends RuntimeModule {
return null;
}
const withPrefetch =
this._runtimeRequirements.has(RuntimeGlobals.prefetchChunkHandlers) &&
chunk.hasChildByOrder(chunkGraph, "prefetch", true, chunkHasCss);
const withPreload =
this._runtimeRequirements.has(RuntimeGlobals.preloadChunkHandlers) &&
chunk.hasChildByOrder(chunkGraph, "preload", true, chunkHasCss);
const { linkPreload, linkPrefetch } =
CssLoadingRuntimeModule.getCompilationHooks(compilation);
@@ -210,7 +211,7 @@ class CssLoadingRuntimeModule extends RuntimeModule {
Template.indent([
"var style = cssRules[j--].style;",
"if(!style) continue;",
`data = style.getPropertyValue(name);`
"data = style.getPropertyValue(name);"
]),
"}"
]),
@@ -224,7 +225,7 @@ class CssLoadingRuntimeModule extends RuntimeModule {
withCompression
? Template.asString([
// LZW decode
`var map = {}, char = data[0], oldPhrase = char, decoded = char, code = 256, maxCode = ${"\uffff".charCodeAt(
`var map = {}, char = data[0], oldPhrase = char, decoded = char, code = 256, maxCode = ${"\uFFFF".charCodeAt(
0
)}, phrase;`,
"for (i = 1; i < data.length; i++) {",
@@ -255,12 +256,12 @@ class CssLoadingRuntimeModule extends RuntimeModule {
","
)}) { token = token.replace(/^_/, ""); target[token] = (${runtimeTemplate.basicFunction(
"exports, module",
`module.exports = exports;`
"module.exports = exports;"
)}).bind(null, exports); ${
withHmr ? "moduleIds.push(token); " : ""
}token = ""; token2 = ""; exports = {}; }`,
`else if(cc == ${cc("\\")}) { token += data[++i] }`,
`else { token += data[i]; }`
"else { token += data[i]; }"
]),
"}",
`${
@@ -271,9 +272,9 @@ class CssLoadingRuntimeModule extends RuntimeModule {
)}`,
'var loadingAttribute = "data-webpack-loading";',
`var loadStylesheet = ${runtimeTemplate.basicFunction(
"chunkId, url, done" +
(withHmr ? ", hmr" : "") +
(withFetchPriority ? ", fetchPriority" : ""),
`chunkId, url, done${withHmr ? ", hmr" : ""}${
withFetchPriority ? ", fetchPriority" : ""
}`,
[
'var link, needAttach, key = "chunk-" + chunkId;',
withHmr ? "if(!hmr) {" : "",
@@ -360,7 +361,7 @@ class CssLoadingRuntimeModule extends RuntimeModule {
Template.indent([
"// setup Promise in chunk cache",
`var promise = new Promise(${runtimeTemplate.expressionFunction(
`installedChunkData = installedChunks[chunkId] = [resolve, reject]`,
"installedChunkData = installedChunks[chunkId] = [resolve, reject]",
"resolve, reject"
)});`,
"promises.push(installedChunkData[2] = promise);",
@@ -516,7 +517,7 @@ class CssLoadingRuntimeModule extends RuntimeModule {
"}",
"while(newTags.length) {",
Template.indent([
`var info = newTags.pop();`,
"var info = newTags.pop();",
`var chunkModuleIds = loadCssChunkData(${RuntimeGlobals.moduleFactories}, info[1], info[0]);`,
`chunkModuleIds.forEach(${runtimeTemplate.expressionFunction(
"moduleIds.push(id)",

View File

@@ -5,13 +5,16 @@
"use strict";
const { SyncWaterfallHook, SyncHook } = require("tapable");
const {
ConcatSource,
PrefixSource,
ReplaceSource,
CachedSource
} = require("webpack-sources");
const Compilation = require("../Compilation");
const CssModule = require("../CssModule");
const { tryRunOrWebpackError } = require("../HookWebpackError");
const HotUpdateChunk = require("../HotUpdateChunk");
const {
CSS_MODULE_TYPE,
@@ -39,17 +42,49 @@ const CssGenerator = require("./CssGenerator");
const CssParser = require("./CssParser");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").Output} OutputOptions */
/** @typedef {import("../../declarations/WebpackOptions").OutputNormalized} OutputOptions */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../CssModule").Inheritance} Inheritance */
/** @typedef {import("../DependencyTemplate").CssExportsData} CssExportsData */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../Template").RuntimeTemplate} RuntimeTemplate */
/** @typedef {import("../TemplatedPathPlugin").TemplatePath} TemplatePath */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/createHash").Algorithm} Algorithm */
/** @typedef {import("../util/memoize")} Memoize */
/**
* @typedef {object} RenderContext
* @property {Chunk} chunk the chunk
* @property {ChunkGraph} chunkGraph the chunk graph
* @property {CodeGenerationResults} codeGenerationResults results of code generation
* @property {RuntimeTemplate} runtimeTemplate the runtime template
* @property {string} uniqueName the unique name
* @property {boolean} cssHeadDataCompression need compress
* @property {string} undoPath undo path to css file
* @property {CssModule[]} modules modules
*/
/**
* @typedef {object} ChunkRenderContext
* @property {Chunk} chunk the chunk
* @property {ChunkGraph} chunkGraph the chunk graph
* @property {CodeGenerationResults} codeGenerationResults results of code generation
* @property {RuntimeTemplate} runtimeTemplate the runtime template
* @property {string[]} metaData meta data for runtime
* @property {string} undoPath undo path to css file
*/
/**
* @typedef {object} CompilationHooks
* @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModulePackage
* @property {SyncHook<[Chunk, Hash, ChunkHashContext]>} chunkHash
*/
const getCssLoadingRuntimeModule = memoize(() =>
require("./CssLoadingRuntimeModule")
);
@@ -120,6 +155,9 @@ const validateParserOptions = {
)
};
/** @type {WeakMap<Compilation, CompilationHooks>} */
const compilationHooksMap = new WeakMap();
/**
* @param {string} str string
* @param {boolean=} omitOptionalUnderscore if true, optional underscore is not added
@@ -128,7 +166,7 @@ const validateParserOptions = {
const escapeCss = (str, omitOptionalUnderscore) => {
const escaped = `${str}`.replace(
// cspell:word uffff
/[^a-zA-Z0-9_\u0081-\uffff-]/g,
/[^a-zA-Z0-9_\u0081-\uFFFF-]/g,
s => `\\${s}`
);
return !omitOptionalUnderscore && /^(?!--)[0-9_-]/.test(escaped)
@@ -140,13 +178,13 @@ const escapeCss = (str, omitOptionalUnderscore) => {
* @param {string} str string
* @returns {string} encoded string
*/
const LZWEncode = str => {
const lzwEncode = str => {
/** @type {Map<string, string>} */
const map = new Map();
let encoded = "";
let phrase = str[0];
let code = 256;
let maxCode = "\uffff".charCodeAt(0);
const maxCode = "\uFFFF".charCodeAt(0);
for (let i = 1; i < str.length; i++) {
const c = str[i];
if (map.has(phrase + c)) {
@@ -165,9 +203,34 @@ const LZWEncode = str => {
return encoded;
};
const plugin = "CssModulesPlugin";
const PLUGIN_NAME = "CssModulesPlugin";
class CssModulesPlugin {
/**
* @param {Compilation} compilation the compilation
* @returns {CompilationHooks} the attached hooks
*/
static getCompilationHooks(compilation) {
if (!(compilation instanceof Compilation)) {
throw new TypeError(
"The 'compilation' argument must be an instance of Compilation"
);
}
let hooks = compilationHooksMap.get(compilation);
if (hooks === undefined) {
hooks = {
renderModulePackage: new SyncWaterfallHook([
"source",
"module",
"renderContext"
]),
chunkHash: new SyncHook(["chunk", "hash", "context"])
};
compilationHooksMap.set(compilation, hooks);
}
return hooks;
}
constructor() {
/** @type {WeakMap<Source, { undoPath: string, inheritance: Inheritance, source: CachedSource }>} */
this._moduleCache = new WeakMap();
@@ -180,8 +243,9 @@ class CssModulesPlugin {
*/
apply(compiler) {
compiler.hooks.compilation.tap(
plugin,
PLUGIN_NAME,
(compilation, { normalModuleFactory }) => {
const hooks = CssModulesPlugin.getCompilationHooks(compilation);
const selfFactory = new SelfModuleFactory(compilation.moduleGraph);
compilation.dependencyFactories.set(
CssUrlDependency,
@@ -227,19 +291,18 @@ class CssModulesPlugin {
]) {
normalModuleFactory.hooks.createParser
.for(type)
.tap(plugin, parserOptions => {
.tap(PLUGIN_NAME, parserOptions => {
validateParserOptions[type](parserOptions);
const { namedExports } = parserOptions;
switch (type) {
case CSS_MODULE_TYPE_GLOBAL:
case CSS_MODULE_TYPE_AUTO:
case CSS_MODULE_TYPE:
return new CssParser({
namedExports
});
case CSS_MODULE_TYPE:
case CSS_MODULE_TYPE_GLOBAL:
return new CssParser({
allowModeSwitch: false,
defaultMode: "global",
namedExports
});
case CSS_MODULE_TYPE_MODULE:
@@ -247,11 +310,16 @@ class CssModulesPlugin {
defaultMode: "local",
namedExports
});
case CSS_MODULE_TYPE_AUTO:
return new CssParser({
defaultMode: "auto",
namedExports
});
}
});
normalModuleFactory.hooks.createGenerator
.for(type)
.tap(plugin, generatorOptions => {
.tap(PLUGIN_NAME, generatorOptions => {
validateGeneratorOptions[type](generatorOptions);
return generatorOptions.exportsOnly
@@ -268,7 +336,7 @@ class CssModulesPlugin {
});
normalModuleFactory.hooks.createModuleClass
.for(type)
.tap(plugin, (createData, resolveData) => {
.tap(PLUGIN_NAME, (createData, resolveData) => {
if (resolveData.dependencies.length > 0) {
// When CSS is imported from CSS there is only one dependency
const dependency = resolveData.dependencies[0];
@@ -283,8 +351,7 @@ class CssModulesPlugin {
let inheritance;
if (
(parent.cssLayer !== null &&
parent.cssLayer !== undefined) ||
parent.cssLayer !== undefined ||
parent.supports ||
parent.media
) {
@@ -340,9 +407,18 @@ class CssModulesPlugin {
}
}
});
compilation.hooks.chunkHash.tap(
"CssModulesPlugin",
(chunk, hash, context) => {
hooks.chunkHash.call(chunk, hash, context);
}
);
compilation.hooks.contentHash.tap("CssModulesPlugin", chunk => {
const {
chunkGraph,
codeGenerationResults,
moduleGraph,
runtimeTemplate,
outputOptions: {
hashSalt,
hashDigest,
@@ -350,19 +426,31 @@ class CssModulesPlugin {
hashFunction
}
} = compilation;
const modules = orderedCssModulesPerChunk.get(chunk);
if (modules === undefined) return;
const hash = createHash(hashFunction);
const hash = createHash(/** @type {Algorithm} */ (hashFunction));
if (hashSalt) hash.update(hashSalt);
for (const module of modules) {
hash.update(chunkGraph.getModuleHash(module, chunk.runtime));
hooks.chunkHash.call(chunk, hash, {
chunkGraph,
codeGenerationResults,
moduleGraph,
runtimeTemplate
});
const modules = orderedCssModulesPerChunk.get(chunk);
if (modules) {
for (const module of modules) {
hash.update(chunkGraph.getModuleHash(module, chunk.runtime));
}
}
const digest = /** @type {string} */ (hash.digest(hashDigest));
chunk.contentHash.css = nonNumericOnlyHash(digest, hashDigestLength);
chunk.contentHash.css = nonNumericOnlyHash(
digest,
/** @type {number} */
(hashDigestLength)
);
});
compilation.hooks.renderManifest.tap(plugin, (result, options) => {
compilation.hooks.renderManifest.tap(PLUGIN_NAME, (result, options) => {
const { chunkGraph } = compilation;
const { hash, chunk, codeGenerationResults } = options;
const { hash, chunk, codeGenerationResults, runtimeTemplate } =
options;
if (chunk instanceof HotUpdateChunk) return result;
@@ -383,21 +471,26 @@ class CssModulesPlugin {
);
const undoPath = getUndoPath(
filename,
compilation.outputOptions.path,
/** @type {string} */
(compilation.outputOptions.path),
false
);
result.push({
render: () =>
this.renderChunk({
chunk,
chunkGraph,
codeGenerationResults,
uniqueName: compilation.outputOptions.uniqueName,
cssHeadDataCompression:
compilation.outputOptions.cssHeadDataCompression,
undoPath,
modules
}),
this.renderChunk(
{
chunk,
chunkGraph,
codeGenerationResults,
uniqueName: compilation.outputOptions.uniqueName,
cssHeadDataCompression:
compilation.outputOptions.cssHeadDataCompression,
undoPath,
modules,
runtimeTemplate
},
hooks
),
filename,
info,
identifier: `css${chunk.id}`,
@@ -429,9 +522,6 @@ class CssModulesPlugin {
onceForChunkSet.add(chunk);
if (!isEnabledForChunk(chunk)) return;
set.add(RuntimeGlobals.publicPath);
set.add(RuntimeGlobals.getChunkCssFilename);
set.add(RuntimeGlobals.hasOwnProperty);
set.add(RuntimeGlobals.moduleFactoriesAddOnly);
set.add(RuntimeGlobals.makeNamespaceObject);
@@ -440,13 +530,48 @@ class CssModulesPlugin {
};
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.hasCssModules)
.tap(plugin, handler);
.tap(PLUGIN_NAME, handler);
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.ensureChunkHandlers)
.tap(plugin, handler);
.tap(PLUGIN_NAME, (chunk, set, { chunkGraph }) => {
if (!isEnabledForChunk(chunk)) return;
if (
!chunkGraph.hasModuleInGraph(
chunk,
m =>
m.type === CSS_MODULE_TYPE ||
m.type === CSS_MODULE_TYPE_GLOBAL ||
m.type === CSS_MODULE_TYPE_MODULE ||
m.type === CSS_MODULE_TYPE_AUTO
)
) {
return;
}
set.add(RuntimeGlobals.hasOwnProperty);
set.add(RuntimeGlobals.publicPath);
set.add(RuntimeGlobals.getChunkCssFilename);
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.hmrDownloadUpdateHandlers)
.tap(plugin, handler);
.tap(PLUGIN_NAME, (chunk, set, { chunkGraph }) => {
if (!isEnabledForChunk(chunk)) return;
if (
!chunkGraph.hasModuleInGraph(
chunk,
m =>
m.type === CSS_MODULE_TYPE ||
m.type === CSS_MODULE_TYPE_GLOBAL ||
m.type === CSS_MODULE_TYPE_MODULE ||
m.type === CSS_MODULE_TYPE_AUTO
)
) {
return;
}
set.add(RuntimeGlobals.publicPath);
set.add(RuntimeGlobals.getChunkCssFilename);
set.add(RuntimeGlobals.moduleFactoriesAddOnly);
});
}
);
}
@@ -467,12 +592,10 @@ class CssModulesPlugin {
// Lists are in reverse order to allow to use Array.pop()
const modulesByChunkGroup = Array.from(chunk.groupsIterable, chunkGroup => {
const sortedModules = modulesList
.map(module => {
return {
module,
index: chunkGroup.getModulePostOrderIndex(module)
};
})
.map(module => ({
module,
index: chunkGroup.getModulePostOrderIndex(module)
}))
.filter(item => item.index !== undefined)
.sort(
(a, b) =>
@@ -486,13 +609,17 @@ class CssModulesPlugin {
if (modulesByChunkGroup.length === 1)
return modulesByChunkGroup[0].list.reverse();
/**
* @param {{ list: Module[] }} a a
* @param {{ list: Module[] }} b b
* @returns {-1 | 0 | 1} result
*/
const compareModuleLists = ({ list: a }, { list: b }) => {
if (a.length === 0) {
return b.length === 0 ? 0 : 1;
} else {
if (b.length === 0) return -1;
return compareModulesByIdentifier(a[a.length - 1], b[b.length - 1]);
}
if (b.length === 0) return -1;
return compareModulesByIdentifier(a[a.length - 1], b[b.length - 1]);
};
modulesByChunkGroup.sort(compareModuleLists);
@@ -509,7 +636,7 @@ class CssModulesPlugin {
}
/** @type {Module} */
let selectedModule = list[list.length - 1];
let hasFailed = undefined;
let hasFailed;
outer: for (;;) {
for (const { list, set } of modulesByChunkGroup) {
if (list.length === 0) continue;
@@ -595,23 +722,14 @@ class CssModulesPlugin {
}
/**
* @param {object} options options
* @param {string[]} options.metaData meta data
* @param {string} options.undoPath undo path for public path auto
* @param {Chunk} options.chunk chunk
* @param {ChunkGraph} options.chunkGraph chunk graph
* @param {CodeGenerationResults} options.codeGenerationResults code generation results
* @param {CssModule} options.module css module
* @param {CssModule} module css module
* @param {ChunkRenderContext} renderContext options object
* @param {CompilationHooks} hooks hooks
* @returns {Source} css module source
*/
renderModule({
metaData,
undoPath,
chunk,
chunkGraph,
codeGenerationResults,
module
}) {
renderModule(module, renderContext, hooks) {
const { codeGenerationResults, chunk, undoPath, chunkGraph, metaData } =
renderContext;
const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
const moduleSourceContent =
/** @type {Source} */
@@ -623,7 +741,7 @@ class CssModulesPlugin {
const cacheEntry = this._moduleCache.get(moduleSourceContent);
/** @type {Inheritance} */
let inheritance = [[module.cssLayer, module.supports, module.media]];
const inheritance = [[module.cssLayer, module.supports, module.media]];
if (module.inheritance) {
inheritance.push(...module.inheritance);
}
@@ -707,7 +825,7 @@ class CssModulesPlugin {
codeGenResult.data && codeGenResult.data.get("css-exports");
const exports = cssExportsData && cssExportsData.exports;
const esModule = cssExportsData && cssExportsData.esModule;
let moduleId = chunkGraph.getModuleId(module) + "";
let moduleId = String(chunkGraph.getModuleId(module));
// When `optimization.moduleIds` is `named` the module id is a path, so we need to normalize it between platforms
if (typeof moduleId === "string") {
@@ -724,72 +842,77 @@ class CssModulesPlugin {
: ""
}${esModule ? "&" : ""}${escapeCss(moduleId)}`
);
return source;
return tryRunOrWebpackError(
() => hooks.renderModulePackage.call(source, module, renderContext),
"CssModulesPlugin.getCompilationHooks().renderModulePackage"
);
}
/**
* @param {object} options options
* @param {string | undefined} options.uniqueName unique name
* @param {boolean | undefined} options.cssHeadDataCompression compress css head data
* @param {string} options.undoPath undo path for public path auto
* @param {Chunk} options.chunk chunk
* @param {ChunkGraph} options.chunkGraph chunk graph
* @param {CodeGenerationResults} options.codeGenerationResults code generation results
* @param {CssModule[]} options.modules ordered css modules
* @param {RenderContext} renderContext the render context
* @param {CompilationHooks} hooks hooks
* @returns {Source} generated source
*/
renderChunk({
uniqueName,
cssHeadDataCompression,
undoPath,
chunk,
chunkGraph,
codeGenerationResults,
modules
}) {
renderChunk(
{
uniqueName,
cssHeadDataCompression,
undoPath,
chunk,
chunkGraph,
codeGenerationResults,
modules,
runtimeTemplate
},
hooks
) {
const source = new ConcatSource();
/** @type {string[]} */
const metaData = [];
for (const module of modules) {
try {
const moduleSource = this.renderModule({
metaData,
undoPath,
chunk,
chunkGraph,
codeGenerationResults,
module
});
const moduleSource = this.renderModule(
module,
{
metaData,
undoPath,
chunk,
chunkGraph,
codeGenerationResults,
runtimeTemplate
},
hooks
);
source.add(moduleSource);
} catch (e) {
} catch (err) {
/** @type {Error} */
(e).message += `\nduring rendering of css ${module.identifier()}`;
throw e;
(err).message += `\nduring rendering of css ${module.identifier()}`;
throw err;
}
}
const metaDataStr = metaData.join(",");
source.add(
`head{--webpack-${escapeCss(
(uniqueName ? uniqueName + "-" : "") + chunk.id,
(uniqueName ? `${uniqueName}-` : "") + chunk.id,
true
)}:${cssHeadDataCompression ? LZWEncode(metaDataStr) : metaDataStr};}`
)}:${cssHeadDataCompression ? lzwEncode(metaDataStr) : metaDataStr};}`
);
chunk.rendered = true;
return source;
}
/**
* @param {Chunk} chunk chunk
* @param {OutputOptions} outputOptions output options
* @returns {Chunk["cssFilenameTemplate"] | OutputOptions["cssFilename"] | OutputOptions["cssChunkFilename"]} used filename template
* @returns {TemplatePath} used filename template
*/
static getChunkFilenameTemplate(chunk, outputOptions) {
if (chunk.cssFilenameTemplate) {
return chunk.cssFilenameTemplate;
} else if (chunk.canBeInitial()) {
return outputOptions.cssFilename;
} else {
return outputOptions.cssChunkFilename;
return /** @type {TemplatePath} */ (outputOptions.cssFilename);
}
return /** @type {TemplatePath} */ (outputOptions.cssChunkFilename);
}
/**
@@ -799,8 +922,10 @@ class CssModulesPlugin {
*/
static chunkHasCss(chunk, chunkGraph) {
return (
!!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css") ||
!!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css-import")
Boolean(chunkGraph.getChunkModulesIterableBySourceType(chunk, "css")) ||
Boolean(
chunkGraph.getChunkModulesIterableBySourceType(chunk, "css-import")
)
);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff