[79a0317] | 1 | /*
|
---|
| 2 | MIT License http://www.opensource.org/licenses/mit-license.php
|
---|
| 3 | Author Tobias Koppers @sokra
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | "use strict";
|
---|
| 7 |
|
---|
| 8 | const asyncLib = require("neo-async");
|
---|
| 9 | const EntryDependency = require("./dependencies/EntryDependency");
|
---|
| 10 | const { someInIterable } = require("./util/IterableHelpers");
|
---|
| 11 | const { compareModulesById } = require("./util/comparators");
|
---|
| 12 | const { dirname, mkdirp } = require("./util/fs");
|
---|
| 13 |
|
---|
| 14 | /** @typedef {import("./ChunkGraph").ModuleId} ModuleId */
|
---|
| 15 | /** @typedef {import("./Compiler")} Compiler */
|
---|
| 16 | /** @typedef {import("./Compiler").IntermediateFileSystem} IntermediateFileSystem */
|
---|
| 17 | /** @typedef {import("./Module").BuildMeta} BuildMeta */
|
---|
| 18 |
|
---|
| 19 | /**
|
---|
| 20 | * @typedef {object} ManifestModuleData
|
---|
| 21 | * @property {string | number} id
|
---|
| 22 | * @property {BuildMeta} buildMeta
|
---|
| 23 | * @property {boolean | string[] | undefined} exports
|
---|
| 24 | */
|
---|
| 25 |
|
---|
| 26 | /**
|
---|
| 27 | * @typedef {object} LibManifestPluginOptions
|
---|
| 28 | * @property {string=} context Context of requests in the manifest file (defaults to the webpack context).
|
---|
| 29 | * @property {boolean=} entryOnly If true, only entry points will be exposed (default: true).
|
---|
| 30 | * @property {boolean=} format If true, manifest json file (output) will be formatted.
|
---|
| 31 | * @property {string=} name Name of the exposed dll function (external name, use value of 'output.library').
|
---|
| 32 | * @property {string} path Absolute path to the manifest json file (output).
|
---|
| 33 | * @property {string=} type Type of the dll bundle (external type, use value of 'output.libraryTarget').
|
---|
| 34 | */
|
---|
| 35 |
|
---|
| 36 | class LibManifestPlugin {
|
---|
| 37 | /**
|
---|
| 38 | * @param {LibManifestPluginOptions} options the options
|
---|
| 39 | */
|
---|
| 40 | constructor(options) {
|
---|
| 41 | this.options = options;
|
---|
| 42 | }
|
---|
| 43 |
|
---|
| 44 | /**
|
---|
| 45 | * Apply the plugin
|
---|
| 46 | * @param {Compiler} compiler the compiler instance
|
---|
| 47 | * @returns {void}
|
---|
| 48 | */
|
---|
| 49 | apply(compiler) {
|
---|
| 50 | compiler.hooks.emit.tapAsync(
|
---|
| 51 | {
|
---|
| 52 | name: "LibManifestPlugin",
|
---|
| 53 | stage: 110
|
---|
| 54 | },
|
---|
| 55 | (compilation, callback) => {
|
---|
| 56 | const moduleGraph = compilation.moduleGraph;
|
---|
| 57 | // store used paths to detect issue and output an error. #18200
|
---|
| 58 | const usedPaths = new Set();
|
---|
| 59 | asyncLib.each(
|
---|
| 60 | Array.from(compilation.chunks),
|
---|
| 61 | (chunk, callback) => {
|
---|
| 62 | if (!chunk.canBeInitial()) {
|
---|
| 63 | callback();
|
---|
| 64 | return;
|
---|
| 65 | }
|
---|
| 66 | const chunkGraph = compilation.chunkGraph;
|
---|
| 67 | const targetPath = compilation.getPath(this.options.path, {
|
---|
| 68 | chunk
|
---|
| 69 | });
|
---|
| 70 | if (usedPaths.has(targetPath)) {
|
---|
| 71 | callback(new Error("each chunk must have a unique path"));
|
---|
| 72 | return;
|
---|
| 73 | }
|
---|
| 74 | usedPaths.add(targetPath);
|
---|
| 75 | const name =
|
---|
| 76 | this.options.name &&
|
---|
| 77 | compilation.getPath(this.options.name, {
|
---|
| 78 | chunk,
|
---|
| 79 | contentHashType: "javascript"
|
---|
| 80 | });
|
---|
| 81 | const content = Object.create(null);
|
---|
| 82 | for (const module of chunkGraph.getOrderedChunkModulesIterable(
|
---|
| 83 | chunk,
|
---|
| 84 | compareModulesById(chunkGraph)
|
---|
| 85 | )) {
|
---|
| 86 | if (
|
---|
| 87 | this.options.entryOnly &&
|
---|
| 88 | !someInIterable(
|
---|
| 89 | moduleGraph.getIncomingConnections(module),
|
---|
| 90 | c => c.dependency instanceof EntryDependency
|
---|
| 91 | )
|
---|
| 92 | ) {
|
---|
| 93 | continue;
|
---|
| 94 | }
|
---|
| 95 | const ident = module.libIdent({
|
---|
| 96 | context:
|
---|
| 97 | this.options.context ||
|
---|
| 98 | /** @type {string} */ (compiler.options.context),
|
---|
| 99 | associatedObjectForCache: compiler.root
|
---|
| 100 | });
|
---|
| 101 | if (ident) {
|
---|
| 102 | const exportsInfo = moduleGraph.getExportsInfo(module);
|
---|
| 103 | const providedExports = exportsInfo.getProvidedExports();
|
---|
| 104 | /** @type {ManifestModuleData} */
|
---|
| 105 | const data = {
|
---|
| 106 | id: /** @type {ModuleId} */ (chunkGraph.getModuleId(module)),
|
---|
| 107 | buildMeta: /** @type {BuildMeta} */ (module.buildMeta),
|
---|
| 108 | exports: Array.isArray(providedExports)
|
---|
| 109 | ? providedExports
|
---|
| 110 | : undefined
|
---|
| 111 | };
|
---|
| 112 | content[ident] = data;
|
---|
| 113 | }
|
---|
| 114 | }
|
---|
| 115 | const manifest = {
|
---|
| 116 | name,
|
---|
| 117 | type: this.options.type,
|
---|
| 118 | content
|
---|
| 119 | };
|
---|
| 120 | // Apply formatting to content if format flag is true;
|
---|
| 121 | const manifestContent = this.options.format
|
---|
| 122 | ? JSON.stringify(manifest, null, 2)
|
---|
| 123 | : JSON.stringify(manifest);
|
---|
| 124 | const buffer = Buffer.from(manifestContent, "utf8");
|
---|
| 125 | const intermediateFileSystem =
|
---|
| 126 | /** @type {IntermediateFileSystem} */ (
|
---|
| 127 | compiler.intermediateFileSystem
|
---|
| 128 | );
|
---|
| 129 | mkdirp(
|
---|
| 130 | intermediateFileSystem,
|
---|
| 131 | dirname(intermediateFileSystem, targetPath),
|
---|
| 132 | err => {
|
---|
| 133 | if (err) return callback(err);
|
---|
| 134 | intermediateFileSystem.writeFile(targetPath, buffer, callback);
|
---|
| 135 | }
|
---|
| 136 | );
|
---|
| 137 | },
|
---|
| 138 | callback
|
---|
| 139 | );
|
---|
| 140 | }
|
---|
| 141 | );
|
---|
| 142 | }
|
---|
| 143 | }
|
---|
| 144 | module.exports = LibManifestPlugin;
|
---|