mirror of https://github.com/webpack/webpack.git
refactor: logic
This commit is contained in:
parent
fe51e3e48b
commit
7298d19d4a
|
@ -8,8 +8,8 @@
|
|||
const { ConcatSource, RawSource, CachedSource } = require("webpack-sources");
|
||||
const { UsageState } = require("./ExportsInfo");
|
||||
const Template = require("./Template");
|
||||
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
|
||||
const CssModulesPlugin = require("./css/CssModulesPlugin");
|
||||
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
@ -164,8 +164,9 @@ class ModuleInfoHeaderPlugin {
|
|||
apply(compiler) {
|
||||
const { _verbose: verbose } = this;
|
||||
compiler.hooks.compilation.tap("ModuleInfoHeaderPlugin", compilation => {
|
||||
const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
|
||||
hooks.renderModulePackage.tap(
|
||||
const javascriptHooks =
|
||||
JavascriptModulesPlugin.getCompilationHooks(compilation);
|
||||
javascriptHooks.renderModulePackage.tap(
|
||||
"ModuleInfoHeaderPlugin",
|
||||
(
|
||||
moduleSource,
|
||||
|
@ -245,10 +246,13 @@ class ModuleInfoHeaderPlugin {
|
|||
return cachedSource;
|
||||
}
|
||||
);
|
||||
hooks.chunkHash.tap("ModuleInfoHeaderPlugin", (chunk, hash) => {
|
||||
hash.update("ModuleInfoHeaderPlugin");
|
||||
hash.update("1");
|
||||
});
|
||||
javascriptHooks.chunkHash.tap(
|
||||
"ModuleInfoHeaderPlugin",
|
||||
(_chunk, hash) => {
|
||||
hash.update("ModuleInfoHeaderPlugin");
|
||||
hash.update("1");
|
||||
}
|
||||
);
|
||||
const cssHooks = CssModulesPlugin.getCompilationHooks(compilation);
|
||||
cssHooks.renderModulePackage.tap(
|
||||
"ModuleInfoHeaderPlugin",
|
||||
|
@ -287,13 +291,17 @@ class ModuleInfoHeaderPlugin {
|
|||
return cachedSource;
|
||||
}
|
||||
);
|
||||
cssHooks.chunkHash.tap("ModuleInfoHeaderPlugin", (_chunk, hash) => {
|
||||
hash.update("ModuleInfoHeaderPlugin");
|
||||
hash.update("1");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module the module
|
||||
* @param {RequestShortener} requestShortener request shortener
|
||||
* @returns {Source} the header
|
||||
* @returns {RawSource} the header
|
||||
*/
|
||||
generateHeader(module, requestShortener) {
|
||||
const req = module.readableIdentifier(requestShortener);
|
||||
|
|
|
@ -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,
|
||||
|
@ -37,21 +40,20 @@ const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
|
|||
const CssExportsGenerator = require("./CssExportsGenerator");
|
||||
const CssGenerator = require("./CssGenerator");
|
||||
const CssParser = require("./CssParser");
|
||||
const { SyncWaterfallHook } = require("tapable");
|
||||
const Compilation = require("../Compilation");
|
||||
const { tryRunOrWebpackError } = require("../HookWebpackError");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").Output} OutputOptions */
|
||||
/** @typedef {import("../Chunk")} Chunk */
|
||||
/** @typedef {import("../ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
|
||||
/** @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("../util/memoize")} Memoize */
|
||||
/** @typedef {import("../Template").RuntimeTemplate} RuntimeTemplate */
|
||||
/** @typedef {import("../util/Hash")} Hash */
|
||||
/** @typedef {import("../util/memoize")} Memoize */
|
||||
|
||||
/**
|
||||
* @typedef {object} ChunkRenderContext
|
||||
|
@ -61,6 +63,7 @@ const { tryRunOrWebpackError } = require("../HookWebpackError");
|
|||
/**
|
||||
* @typedef {object} CompilationHooks
|
||||
* @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModulePackage
|
||||
* @property {SyncHook<[Chunk, Hash, ChunkHashContext]>} chunkHash
|
||||
*/
|
||||
|
||||
const getCssLoadingRuntimeModule = memoize(() =>
|
||||
|
@ -181,7 +184,7 @@ const lzwEncode = str => {
|
|||
return encoded;
|
||||
};
|
||||
|
||||
const plugin = "CssModulesPlugin";
|
||||
const PLUGIN_NAME = "CssModulesPlugin";
|
||||
|
||||
class CssModulesPlugin {
|
||||
/**
|
||||
|
@ -201,7 +204,8 @@ class CssModulesPlugin {
|
|||
"source",
|
||||
"module",
|
||||
"renderContext"
|
||||
])
|
||||
]),
|
||||
chunkHash: new SyncHook(["chunk", "hash", "context"])
|
||||
};
|
||||
compilationHooksMap.set(compilation, hooks);
|
||||
}
|
||||
|
@ -220,7 +224,7 @@ class CssModulesPlugin {
|
|||
*/
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap(
|
||||
plugin,
|
||||
PLUGIN_NAME,
|
||||
(compilation, { normalModuleFactory }) => {
|
||||
const hooks = CssModulesPlugin.getCompilationHooks(compilation);
|
||||
const selfFactory = new SelfModuleFactory(compilation.moduleGraph);
|
||||
|
@ -268,7 +272,7 @@ class CssModulesPlugin {
|
|||
]) {
|
||||
normalModuleFactory.hooks.createParser
|
||||
.for(type)
|
||||
.tap(plugin, parserOptions => {
|
||||
.tap(PLUGIN_NAME, parserOptions => {
|
||||
validateParserOptions[type](parserOptions);
|
||||
const { namedExports } = parserOptions;
|
||||
|
||||
|
@ -292,7 +296,7 @@ class CssModulesPlugin {
|
|||
});
|
||||
normalModuleFactory.hooks.createGenerator
|
||||
.for(type)
|
||||
.tap(plugin, generatorOptions => {
|
||||
.tap(PLUGIN_NAME, generatorOptions => {
|
||||
validateGeneratorOptions[type](generatorOptions);
|
||||
|
||||
return generatorOptions.exportsOnly
|
||||
|
@ -309,7 +313,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];
|
||||
|
@ -381,9 +385,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,
|
||||
|
@ -391,17 +404,24 @@ class CssModulesPlugin {
|
|||
hashFunction
|
||||
}
|
||||
} = compilation;
|
||||
const modules = orderedCssModulesPerChunk.get(chunk);
|
||||
if (modules === undefined) return;
|
||||
const hash = createHash(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);
|
||||
});
|
||||
compilation.hooks.renderManifest.tap(plugin, (result, options) => {
|
||||
compilation.hooks.renderManifest.tap(PLUGIN_NAME, (result, options) => {
|
||||
const { chunkGraph } = compilation;
|
||||
const { hash, chunk, codeGenerationResults, runtimeTemplate } =
|
||||
options;
|
||||
|
@ -484,13 +504,13 @@ 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, handler);
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.hmrDownloadUpdateHandlers)
|
||||
.tap(plugin, handler);
|
||||
.tap(PLUGIN_NAME, handler);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -831,6 +851,7 @@ class CssModulesPlugin {
|
|||
true
|
||||
)}:${cssHeadDataCompression ? lzwEncode(metaDataStr) : metaDataStr};}`
|
||||
);
|
||||
chunk.rendered = true;
|
||||
return source;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import * as style from "./style.css";
|
||||
|
||||
it("should compile and load style on demand", done => {
|
||||
expect(style).toEqual(nsObj({}));
|
||||
import("./style2.css").then(x => {
|
||||
expect(x).toEqual(nsObj({}));
|
||||
const style = getComputedStyle(document.body);
|
||||
expect(style.getPropertyValue("background")).toBe(" red");
|
||||
expect(style.getPropertyValue("margin")).toBe(" 10px");
|
||||
expect(style.getPropertyValue("color")).toBe(" green");
|
||||
expect(style.getPropertyValue("padding")).toBe(" 20px 10px");
|
||||
done();
|
||||
}, done);
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
margin: 10px;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
@import "style-imported.css";
|
||||
body {
|
||||
background: red;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
padding: 20px 10px;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
@import "./style2-imported.css";
|
||||
body {
|
||||
color: green;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
moduleScope(scope) {
|
||||
const link = scope.window.document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = "bundle0.css";
|
||||
scope.window.document.head.appendChild(link);
|
||||
},
|
||||
findBundle: function (i, options) {
|
||||
const source = fs.readFileSync(
|
||||
path.resolve(options.output.path, "bundle0.css"),
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
if (
|
||||
!source.includes(`/*!********************************!*\\
|
||||
!*** css ./style-imported.css ***!
|
||||
\\********************************/`) &&
|
||||
!source.includes(`/*!***********************!*\\
|
||||
!*** css ./style.css ***!
|
||||
\\***********************/`)
|
||||
) {
|
||||
throw new Error("The `pathinfo` option doesn't work.");
|
||||
}
|
||||
|
||||
return "./bundle0.js";
|
||||
}
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
/** @type {import("../../../../").Configuration} */
|
||||
module.exports = {
|
||||
target: "web",
|
||||
mode: "development",
|
||||
devtool: false,
|
||||
output: {
|
||||
pathinfo: true,
|
||||
cssChunkFilename: "[name].[chunkhash].css"
|
||||
},
|
||||
experiments: {
|
||||
css: true
|
||||
}
|
||||
};
|
|
@ -207,23 +207,26 @@ class FakeSheet {
|
|||
.replace(/^https:\/\/example\.com\//, "")
|
||||
);
|
||||
let css = fs.readFileSync(filepath, "utf-8");
|
||||
css = css.replace(/@import url\("([^"]+)"\);/g, (match, url) => {
|
||||
if (!/^https:\/\/test\.cases\/path\//.test(url)) {
|
||||
return url;
|
||||
}
|
||||
css = css
|
||||
// Remove comments
|
||||
.replace(/\/\*.*?\*\//gms, "")
|
||||
.replace(/@import url\("([^"]+)"\);/g, (match, url) => {
|
||||
if (!/^https:\/\/test\.cases\/path\//.test(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (url.startsWith("#")) {
|
||||
return url;
|
||||
}
|
||||
if (url.startsWith("#")) {
|
||||
return url;
|
||||
}
|
||||
|
||||
return fs.readFileSync(
|
||||
path.resolve(
|
||||
this._basePath,
|
||||
url.replace(/^https:\/\/test\.cases\/path\//, "")
|
||||
),
|
||||
"utf-8"
|
||||
);
|
||||
});
|
||||
return fs.readFileSync(
|
||||
path.resolve(
|
||||
this._basePath,
|
||||
url.replace(/^https:\/\/test\.cases\/path\//, "")
|
||||
),
|
||||
"utf-8"
|
||||
);
|
||||
});
|
||||
walkCssTokens(css, {
|
||||
isSelector() {
|
||||
return selector === undefined;
|
||||
|
|
Loading…
Reference in New Issue