add experimental SyncModuleIdsPlugin
This commit is contained in:
parent
1489b91a98
commit
8828dfa394
|
@ -165,6 +165,11 @@ class Compiler {
|
|||
/** @type {AsyncSeriesHook<[Compilation]>} */
|
||||
afterCompile: new AsyncSeriesHook(["compilation"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<[]>} */
|
||||
readRecords: new AsyncSeriesHook([]),
|
||||
/** @type {AsyncSeriesHook<[]>} */
|
||||
emitRecords: new AsyncSeriesHook([]),
|
||||
|
||||
/** @type {AsyncSeriesHook<[Compiler]>} */
|
||||
watchRun: new AsyncSeriesHook(["compiler"]),
|
||||
/** @type {SyncHook<[Error]>} */
|
||||
|
@ -882,8 +887,32 @@ ${other}`);
|
|||
* @returns {void}
|
||||
*/
|
||||
emitRecords(callback) {
|
||||
if (!this.recordsOutputPath) return callback();
|
||||
if (this.hooks.emitRecords.isUsed()) {
|
||||
if (this.recordsOutputPath) {
|
||||
asyncLib.parallel(
|
||||
[
|
||||
cb => this.hooks.emitRecords.callAsync(cb),
|
||||
this._emitRecords.bind(this)
|
||||
],
|
||||
err => callback(err)
|
||||
);
|
||||
} else {
|
||||
this.hooks.emitRecords.callAsync(callback);
|
||||
}
|
||||
} else {
|
||||
if (this.recordsOutputPath) {
|
||||
this._emitRecords(callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Callback<void>} callback signals when the call finishes
|
||||
* @returns {void}
|
||||
*/
|
||||
_emitRecords(callback) {
|
||||
const writeFile = () => {
|
||||
this.outputFileSystem.writeFile(
|
||||
this.recordsOutputPath,
|
||||
|
@ -926,6 +955,31 @@ ${other}`);
|
|||
* @returns {void}
|
||||
*/
|
||||
readRecords(callback) {
|
||||
if (this.hooks.readRecords.isUsed()) {
|
||||
if (this.recordsInputPath) {
|
||||
asyncLib.parallel([
|
||||
cb => this.hooks.readRecords.callAsync(cb),
|
||||
this._readRecords.bind(this)
|
||||
]);
|
||||
} else {
|
||||
this.records = {};
|
||||
this.hooks.readRecords.callAsync(callback);
|
||||
}
|
||||
} else {
|
||||
if (this.recordsInputPath) {
|
||||
this._readRecords(callback);
|
||||
} else {
|
||||
this.records = {};
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Callback<void>} callback signals when the call finishes
|
||||
* @returns {void}
|
||||
*/
|
||||
_readRecords(callback) {
|
||||
if (!this.recordsInputPath) {
|
||||
this.records = {};
|
||||
return callback();
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const { WebpackError } = require("..");
|
||||
const { getUsedModuleIdsAndModules } = require("./IdHelpers");
|
||||
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
/** @typedef {import("../Module")} Module */
|
||||
|
||||
const plugin = "SyncModuleIdsPlugin";
|
||||
|
||||
class SyncModuleIdsPlugin {
|
||||
/**
|
||||
* @param {Object} options options
|
||||
* @param {string} options.path path to file
|
||||
* @param {string=} options.context context for module names
|
||||
* @param {function(Module): boolean} options.test selector for modules
|
||||
* @param {"read" | "create" | "merge" | "update"=} options.mode operation mode (defaults to merge)
|
||||
*/
|
||||
constructor({ path, context, test, mode }) {
|
||||
this._path = path;
|
||||
this._context = context;
|
||||
this._test = test || (() => true);
|
||||
const readAndWrite = !mode || mode === "merge" || mode === "update";
|
||||
this._read = readAndWrite || mode === "read";
|
||||
this._write = readAndWrite || mode === "create";
|
||||
this._prune = mode === "update";
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the plugin
|
||||
* @param {Compiler} compiler the compiler instance
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compiler) {
|
||||
/** @type {Map<string, string | number>} */
|
||||
let data;
|
||||
let dataChanged = false;
|
||||
if (this._read) {
|
||||
compiler.hooks.readRecords.tapAsync(plugin, callback => {
|
||||
const fs = compiler.intermediateFileSystem;
|
||||
fs.readFile(this._path, (err, buffer) => {
|
||||
if (err) {
|
||||
if (err.code !== "ENOENT") {
|
||||
return callback(err);
|
||||
}
|
||||
return callback();
|
||||
}
|
||||
const json = JSON.parse(buffer.toString());
|
||||
data = new Map();
|
||||
for (const key of Object.keys(json)) {
|
||||
data.set(key, json[key]);
|
||||
}
|
||||
dataChanged = false;
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
if (this._write) {
|
||||
compiler.hooks.emitRecords.tapAsync(plugin, callback => {
|
||||
if (!data || !dataChanged) return callback();
|
||||
const json = {};
|
||||
const sorted = Array.from(data).sort(([a], [b]) => (a < b ? -1 : 1));
|
||||
for (const [key, value] of sorted) {
|
||||
json[key] = value;
|
||||
}
|
||||
const fs = compiler.intermediateFileSystem;
|
||||
fs.writeFile(this._path, JSON.stringify(json), callback);
|
||||
});
|
||||
}
|
||||
compiler.hooks.thisCompilation.tap(plugin, compilation => {
|
||||
const associatedObjectForCache = compiler.root;
|
||||
const context = this._context || compiler.context;
|
||||
if (this._read) {
|
||||
compilation.hooks.reviveModules.tap(plugin, (_1, _2) => {
|
||||
if (!data) return;
|
||||
const { chunkGraph } = compilation;
|
||||
const [usedIds, modules] = getUsedModuleIdsAndModules(
|
||||
compilation,
|
||||
this._test
|
||||
);
|
||||
for (const module of modules) {
|
||||
const name = module.libIdent({
|
||||
context,
|
||||
associatedObjectForCache
|
||||
});
|
||||
if (!name) continue;
|
||||
const id = data.get(name);
|
||||
const idAsString = `${id}`;
|
||||
if (usedIds.has(idAsString)) {
|
||||
const err = new WebpackError(
|
||||
`SyncModuleIdsPlugin: Unable to restore id '${id}' from '${this._path}' as it's already used.`
|
||||
);
|
||||
err.module = module;
|
||||
compilation.errors.push(err);
|
||||
}
|
||||
chunkGraph.setModuleId(module, id);
|
||||
usedIds.add(idAsString);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this._write) {
|
||||
compilation.hooks.recordModules.tap(plugin, modules => {
|
||||
const { chunkGraph } = compilation;
|
||||
let oldData = data;
|
||||
if (!oldData) {
|
||||
oldData = data = new Map();
|
||||
} else if (this._prune) {
|
||||
data = new Map();
|
||||
}
|
||||
for (const module of modules) {
|
||||
if (this._test(module)) {
|
||||
const name = module.libIdent({
|
||||
context,
|
||||
associatedObjectForCache
|
||||
});
|
||||
if (!name) continue;
|
||||
const id = chunkGraph.getModuleId(module);
|
||||
if (id === null) continue;
|
||||
const oldId = oldData.get(name);
|
||||
if (oldId !== id) {
|
||||
dataChanged = true;
|
||||
} else if (data === oldData) {
|
||||
continue;
|
||||
}
|
||||
data.set(name, id);
|
||||
}
|
||||
}
|
||||
if (data.size !== oldData.size) dataChanged = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SyncModuleIdsPlugin;
|
|
@ -564,6 +564,11 @@ module.exports = mergeExports(fn, {
|
|||
get HttpUriPlugin() {
|
||||
return require("./schemes/HttpUriPlugin");
|
||||
}
|
||||
},
|
||||
ids: {
|
||||
get SyncModuleIdsPlugin() {
|
||||
return require("./ids/SyncModuleIdsPlugin");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
module.exports = require("../css-modules/warnings");
|
||||
for (const item of module.exports.slice(0, module.exports.length / 2))
|
||||
module.exports.push(item);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const path = require("path");
|
||||
const webpack = require("../../../../");
|
||||
|
||||
/** @type {import("../../../../").Configuration[]} */
|
||||
module.exports = [
|
||||
/** @type {function(any, any): import("../../../../").Configuration[]} */
|
||||
module.exports = (env, { testPath }) => [
|
||||
{
|
||||
context: path.join(__dirname, "../css-modules"),
|
||||
entry: "../css-modules-in-node/index.js",
|
||||
|
@ -31,5 +31,24 @@ module.exports = [
|
|||
test: m => m.type.startsWith("css")
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
context: path.join(__dirname, "../css-modules"),
|
||||
entry: "../css-modules-in-node/index.js",
|
||||
target: "node",
|
||||
mode: "production",
|
||||
output: {
|
||||
uniqueName: "my-app"
|
||||
},
|
||||
experiments: {
|
||||
css: true
|
||||
},
|
||||
plugins: [
|
||||
new webpack.experiments.ids.SyncModuleIdsPlugin({
|
||||
test: m => m.type.startsWith("css"),
|
||||
path: path.resolve(testPath, "../css-modules/module-ids.json"),
|
||||
mode: "read"
|
||||
})
|
||||
]
|
||||
}
|
||||
];
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const webpack = require("../../../../");
|
||||
const path = require("path");
|
||||
|
||||
/** @type {import("../../../../").Configuration[]} */
|
||||
module.exports = [
|
||||
/** @type {function(any, any): import("../../../../").Configuration[]} */
|
||||
module.exports = (env, { testPath }) => [
|
||||
{
|
||||
target: "web",
|
||||
mode: "development",
|
||||
|
@ -24,6 +25,11 @@ module.exports = [
|
|||
failOnConflict: true,
|
||||
fixedLength: true,
|
||||
test: m => m.type.startsWith("css")
|
||||
}),
|
||||
new webpack.experiments.ids.SyncModuleIdsPlugin({
|
||||
test: m => m.type.startsWith("css"),
|
||||
path: path.resolve(testPath, "module-ids.json"),
|
||||
mode: "create"
|
||||
})
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1900,6 +1900,8 @@ declare class Compiler {
|
|||
make: AsyncParallelHook<[Compilation]>;
|
||||
finishMake: AsyncParallelHook<[Compilation]>;
|
||||
afterCompile: AsyncSeriesHook<[Compilation]>;
|
||||
readRecords: AsyncSeriesHook<[]>;
|
||||
emitRecords: AsyncSeriesHook<[]>;
|
||||
watchRun: AsyncSeriesHook<[Compiler]>;
|
||||
failed: SyncHook<[Error]>;
|
||||
invalid: SyncHook<[null | string, number]>;
|
||||
|
@ -11599,6 +11601,31 @@ type StatsValue =
|
|||
| "minimal"
|
||||
| "normal"
|
||||
| "detailed";
|
||||
declare class SyncModuleIdsPlugin {
|
||||
constructor(__0: {
|
||||
/**
|
||||
* path to file
|
||||
*/
|
||||
path: string;
|
||||
/**
|
||||
* context for module names
|
||||
*/
|
||||
context?: string;
|
||||
/**
|
||||
* selector for modules
|
||||
*/
|
||||
test: (arg0: Module) => boolean;
|
||||
/**
|
||||
* operation mode (defaults to merge)
|
||||
*/
|
||||
mode?: "read" | "create" | "merge" | "update";
|
||||
});
|
||||
|
||||
/**
|
||||
* Apply the plugin
|
||||
*/
|
||||
apply(compiler: Compiler): void;
|
||||
}
|
||||
declare interface SyntheticDependencyLocation {
|
||||
name: string;
|
||||
index?: number;
|
||||
|
@ -12811,6 +12838,9 @@ declare namespace exports {
|
|||
export namespace schemes {
|
||||
export { HttpUriPlugin };
|
||||
}
|
||||
export namespace ids {
|
||||
export { SyncModuleIdsPlugin };
|
||||
}
|
||||
}
|
||||
export type WebpackPluginFunction = (
|
||||
this: Compiler,
|
||||
|
|
Loading…
Reference in New Issue