UNPKG

5.68 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 { ConcatSource } = require("webpack-sources");
9const { UsageState } = require("./ExportsInfo");
10const Template = require("./Template");
11const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
12
13/** @typedef {import("./Compiler")} Compiler */
14/** @typedef {import("./ExportsInfo")} ExportsInfo */
15/** @typedef {import("./ExportsInfo").ExportInfo} ExportInfo */
16/** @typedef {import("./ModuleGraph")} ModuleGraph */
17/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
18/** @typedef {import("./RequestShortener")} RequestShortener */
19
20const joinIterableWithComma = iterable => {
21 // This is more performant than Array.from().join(", ")
22 // as it doesn't create an array
23 let str = "";
24 let first = true;
25 for (const item of iterable) {
26 if (first) {
27 first = false;
28 } else {
29 str += ", ";
30 }
31 str += item;
32 }
33 return str;
34};
35
36/**
37 * @param {ConcatSource} source output
38 * @param {string} indent spacing
39 * @param {ExportsInfo} exportsInfo data
40 * @param {ModuleGraph} moduleGraph moduleGraph
41 * @param {RequestShortener} requestShortener requestShortener
42 * @param {Set<ExportInfo>} alreadyPrinted deduplication set
43 * @returns {void}
44 */
45const printExportsInfoToSource = (
46 source,
47 indent,
48 exportsInfo,
49 moduleGraph,
50 requestShortener,
51 alreadyPrinted = new Set()
52) => {
53 const otherExportsInfo = exportsInfo.otherExportsInfo;
54
55 let alreadyPrintedExports = 0;
56
57 // determine exports to print
58 const printedExports = [];
59 for (const exportInfo of exportsInfo.orderedExports) {
60 if (!alreadyPrinted.has(exportInfo)) {
61 alreadyPrinted.add(exportInfo);
62 printedExports.push(exportInfo);
63 } else {
64 alreadyPrintedExports++;
65 }
66 }
67 let showOtherExports = false;
68 if (!alreadyPrinted.has(otherExportsInfo)) {
69 alreadyPrinted.add(otherExportsInfo);
70 showOtherExports = true;
71 } else {
72 alreadyPrintedExports++;
73 }
74
75 // print the exports
76 for (const exportInfo of printedExports) {
77 const target = exportInfo.getTarget(moduleGraph);
78 source.add(
79 Template.toComment(
80 `${indent}export ${JSON.stringify(exportInfo.name).slice(
81 1,
82 -1
83 )} [${exportInfo.getProvidedInfo()}] [${exportInfo.getUsedInfo()}] [${exportInfo.getRenameInfo()}]${
84 target
85 ? ` -> ${target.module.readableIdentifier(requestShortener)}${
86 target.export
87 ? ` .${target.export
88 .map(e => JSON.stringify(e).slice(1, -1))
89 .join(".")}`
90 : ""
91 }`
92 : ""
93 }`
94 ) + "\n"
95 );
96 if (exportInfo.exportsInfo) {
97 printExportsInfoToSource(
98 source,
99 indent + " ",
100 exportInfo.exportsInfo,
101 moduleGraph,
102 requestShortener,
103 alreadyPrinted
104 );
105 }
106 }
107
108 if (alreadyPrintedExports) {
109 source.add(
110 Template.toComment(
111 `${indent}... (${alreadyPrintedExports} already listed exports)`
112 ) + "\n"
113 );
114 }
115
116 if (showOtherExports) {
117 const target = otherExportsInfo.getTarget(moduleGraph);
118 if (
119 target ||
120 otherExportsInfo.provided !== false ||
121 otherExportsInfo.getUsed(undefined) !== UsageState.Unused
122 ) {
123 const title =
124 printedExports.length > 0 || alreadyPrintedExports > 0
125 ? "other exports"
126 : "exports";
127 source.add(
128 Template.toComment(
129 `${indent}${title} [${otherExportsInfo.getProvidedInfo()}] [${otherExportsInfo.getUsedInfo()}]${
130 target
131 ? ` -> ${target.module.readableIdentifier(requestShortener)}`
132 : ""
133 }`
134 ) + "\n"
135 );
136 }
137 }
138};
139
140class ModuleInfoHeaderPlugin {
141 /**
142 * @param {Compiler} compiler the compiler
143 * @returns {void}
144 */
145 apply(compiler) {
146 compiler.hooks.compilation.tap("ModuleInfoHeaderPlugin", compilation => {
147 const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
148 hooks.renderModulePackage.tap(
149 "ModuleInfoHeaderPlugin",
150 (
151 moduleSource,
152 module,
153 { chunk, chunkGraph, moduleGraph, runtimeTemplate }
154 ) => {
155 const { requestShortener } = runtimeTemplate;
156 const source = new ConcatSource();
157 const req = module.readableIdentifier(requestShortener);
158 const reqStr = req.replace(/\*\//g, "*_/");
159 const reqStrStar = "*".repeat(reqStr.length);
160 source.add("/*!****" + reqStrStar + "****!*\\\n");
161 source.add(" !*** " + reqStr + " ***!\n");
162 source.add(" \\****" + reqStrStar + "****/\n");
163 const exportsType = module.buildMeta.exportsType;
164 source.add(
165 Template.toComment(
166 exportsType
167 ? `${exportsType} exports`
168 : "unknown exports (runtime-defined)"
169 ) + "\n"
170 );
171 if (exportsType) {
172 const exportsInfo = moduleGraph.getExportsInfo(module);
173 printExportsInfoToSource(
174 source,
175 "",
176 exportsInfo,
177 moduleGraph,
178 requestShortener
179 );
180 }
181 source.add(
182 Template.toComment(
183 `runtime requirements: ${joinIterableWithComma(
184 chunkGraph.getModuleRuntimeRequirements(module, chunk.runtime)
185 )}`
186 ) + "\n"
187 );
188 const optimizationBailout = moduleGraph.getOptimizationBailout(
189 module
190 );
191 if (optimizationBailout) {
192 for (const text of optimizationBailout) {
193 let code;
194 if (typeof text === "function") {
195 code = text(requestShortener);
196 } else {
197 code = text;
198 }
199 source.add(Template.toComment(`${code}`) + "\n");
200 }
201 }
202 source.add(moduleSource);
203 return source;
204 }
205 );
206 hooks.chunkHash.tap("ModuleInfoHeaderPlugin", (chunk, hash) => {
207 hash.update("ModuleInfoHeaderPlugin");
208 hash.update("1");
209 });
210 });
211 }
212}
213module.exports = ModuleInfoHeaderPlugin;