123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- /*
- 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(/** @type {Buffer} */ (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();
- /** @type {{[key: string]: string | number}} */
- 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, /** @type {string | number} */ (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;
|