UNPKG

3.37 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const asyncLib = require("neo-async");
9const EntryDependency = require("./dependencies/EntryDependency");
10const { compareModulesById } = require("./util/comparators");
11const { dirname, mkdirp } = require("./util/fs");
12
13/** @typedef {import("./Compiler")} Compiler */
14
15/**
16 * @typedef {Object} ManifestModuleData
17 * @property {string | number} id
18 * @property {Object} buildMeta
19 * @property {boolean | string[]} exports
20 */
21
22/**
23 * @template T
24 * @param {Iterable<T>} iterable iterable
25 * @param {function(T): boolean} filter predicate
26 * @returns {boolean} true, if some items match the filter predicate
27 */
28const someInIterable = (iterable, filter) => {
29 for (const item of iterable) {
30 if (filter(item)) return true;
31 }
32 return false;
33};
34
35class LibManifestPlugin {
36 constructor(options) {
37 this.options = options;
38 }
39
40 /**
41 * Apply the plugin
42 * @param {Compiler} compiler the compiler instance
43 * @returns {void}
44 */
45 apply(compiler) {
46 compiler.hooks.emit.tapAsync(
47 "LibManifestPlugin",
48 (compilation, callback) => {
49 const moduleGraph = compilation.moduleGraph;
50 asyncLib.forEach(
51 Array.from(compilation.chunks),
52 (chunk, callback) => {
53 if (!chunk.canBeInitial()) {
54 callback();
55 return;
56 }
57 const chunkGraph = compilation.chunkGraph;
58 const targetPath = compilation.getPath(this.options.path, {
59 chunk
60 });
61 const name =
62 this.options.name &&
63 compilation.getPath(this.options.name, {
64 chunk
65 });
66 const content = Object.create(null);
67 for (const module of chunkGraph.getOrderedChunkModulesIterable(
68 chunk,
69 compareModulesById(chunkGraph)
70 )) {
71 if (
72 this.options.entryOnly &&
73 !someInIterable(
74 moduleGraph.getIncomingConnections(module),
75 c => c.dependency instanceof EntryDependency
76 )
77 ) {
78 continue;
79 }
80 const ident = module.libIdent({
81 context: this.options.context || compiler.options.context,
82 associatedObjectForCache: compiler.root
83 });
84 if (ident) {
85 const exportsInfo = moduleGraph.getExportsInfo(module);
86 const providedExports = exportsInfo.getProvidedExports();
87 /** @type {ManifestModuleData} */
88 const data = {
89 id: chunkGraph.getModuleId(module),
90 buildMeta: module.buildMeta,
91 exports: Array.isArray(providedExports)
92 ? providedExports
93 : undefined
94 };
95 content[ident] = data;
96 }
97 }
98 const manifest = {
99 name,
100 type: this.options.type,
101 content
102 };
103 // Apply formatting to content if format flag is true;
104 const manifestContent = this.options.format
105 ? JSON.stringify(manifest, null, 2)
106 : JSON.stringify(manifest);
107 const buffer = Buffer.from(manifestContent, "utf8");
108 mkdirp(
109 compiler.intermediateFileSystem,
110 dirname(compiler.intermediateFileSystem, targetPath),
111 err => {
112 if (err) return callback(err);
113 compiler.intermediateFileSystem.writeFile(
114 targetPath,
115 buffer,
116 callback
117 );
118 }
119 );
120 },
121 callback
122 );
123 }
124 );
125 }
126}
127module.exports = LibManifestPlugin;