1 |
|
2 |
|
3 |
|
4 |
|
5 | "use strict";
|
6 |
|
7 | const Parser = require("./Parser");
|
8 | const Template = require("./Template");
|
9 | const { ConcatSource } = require("webpack-sources");
|
10 | const JavascriptGenerator = require("./JavascriptGenerator");
|
11 | const createHash = require("./util/createHash");
|
12 |
|
13 | class JavascriptModulesPlugin {
|
14 | apply(compiler) {
|
15 | compiler.hooks.compilation.tap(
|
16 | "JavascriptModulesPlugin",
|
17 | (compilation, { normalModuleFactory }) => {
|
18 | normalModuleFactory.hooks.createParser
|
19 | .for("javascript/auto")
|
20 | .tap("JavascriptModulesPlugin", options => {
|
21 | return new Parser(options, "auto");
|
22 | });
|
23 | normalModuleFactory.hooks.createParser
|
24 | .for("javascript/dynamic")
|
25 | .tap("JavascriptModulesPlugin", options => {
|
26 | return new Parser(options, "script");
|
27 | });
|
28 | normalModuleFactory.hooks.createParser
|
29 | .for("javascript/esm")
|
30 | .tap("JavascriptModulesPlugin", options => {
|
31 | return new Parser(options, "module");
|
32 | });
|
33 | normalModuleFactory.hooks.createGenerator
|
34 | .for("javascript/auto")
|
35 | .tap("JavascriptModulesPlugin", () => {
|
36 | return new JavascriptGenerator();
|
37 | });
|
38 | normalModuleFactory.hooks.createGenerator
|
39 | .for("javascript/dynamic")
|
40 | .tap("JavascriptModulesPlugin", () => {
|
41 | return new JavascriptGenerator();
|
42 | });
|
43 | normalModuleFactory.hooks.createGenerator
|
44 | .for("javascript/esm")
|
45 | .tap("JavascriptModulesPlugin", () => {
|
46 | return new JavascriptGenerator();
|
47 | });
|
48 | compilation.mainTemplate.hooks.renderManifest.tap(
|
49 | "JavascriptModulesPlugin",
|
50 | (result, options) => {
|
51 | const chunk = options.chunk;
|
52 | const hash = options.hash;
|
53 | const fullHash = options.fullHash;
|
54 | const outputOptions = options.outputOptions;
|
55 | const moduleTemplates = options.moduleTemplates;
|
56 | const dependencyTemplates = options.dependencyTemplates;
|
57 |
|
58 | const filenameTemplate =
|
59 | chunk.filenameTemplate || outputOptions.filename;
|
60 |
|
61 | const useChunkHash = compilation.mainTemplate.useChunkHash(chunk);
|
62 |
|
63 | result.push({
|
64 | render: () =>
|
65 | compilation.mainTemplate.render(
|
66 | hash,
|
67 | chunk,
|
68 | moduleTemplates.javascript,
|
69 | dependencyTemplates
|
70 | ),
|
71 | filenameTemplate,
|
72 | pathOptions: {
|
73 | noChunkHash: !useChunkHash,
|
74 | contentHashType: "javascript",
|
75 | chunk
|
76 | },
|
77 | identifier: `chunk${chunk.id}`,
|
78 | hash: useChunkHash ? chunk.hash : fullHash
|
79 | });
|
80 | return result;
|
81 | }
|
82 | );
|
83 | compilation.mainTemplate.hooks.modules.tap(
|
84 | "JavascriptModulesPlugin",
|
85 | (source, chunk, hash, moduleTemplate, dependencyTemplates) => {
|
86 | return Template.renderChunkModules(
|
87 | chunk,
|
88 | m => typeof m.source === "function",
|
89 | moduleTemplate,
|
90 | dependencyTemplates,
|
91 | "/******/ "
|
92 | );
|
93 | }
|
94 | );
|
95 | compilation.chunkTemplate.hooks.renderManifest.tap(
|
96 | "JavascriptModulesPlugin",
|
97 | (result, options) => {
|
98 | const chunk = options.chunk;
|
99 | const outputOptions = options.outputOptions;
|
100 | const moduleTemplates = options.moduleTemplates;
|
101 | const dependencyTemplates = options.dependencyTemplates;
|
102 | const filenameTemplate =
|
103 | chunk.filenameTemplate || outputOptions.chunkFilename;
|
104 |
|
105 | result.push({
|
106 | render: () =>
|
107 | this.renderJavascript(
|
108 | compilation.chunkTemplate,
|
109 | chunk,
|
110 | moduleTemplates.javascript,
|
111 | dependencyTemplates
|
112 | ),
|
113 | filenameTemplate,
|
114 | pathOptions: {
|
115 | chunk,
|
116 | contentHashType: "javascript"
|
117 | },
|
118 | identifier: `chunk${chunk.id}`,
|
119 | hash: chunk.hash
|
120 | });
|
121 |
|
122 | return result;
|
123 | }
|
124 | );
|
125 | compilation.hooks.contentHash.tap("JavascriptModulesPlugin", chunk => {
|
126 | const outputOptions = compilation.outputOptions;
|
127 | const {
|
128 | hashSalt,
|
129 | hashDigest,
|
130 | hashDigestLength,
|
131 | hashFunction
|
132 | } = outputOptions;
|
133 | const hash = createHash(hashFunction);
|
134 | if (hashSalt) hash.update(hashSalt);
|
135 | const template = chunk.hasRuntime()
|
136 | ? compilation.mainTemplate
|
137 | : compilation.chunkTemplate;
|
138 | hash.update(`${chunk.id} `);
|
139 | hash.update(chunk.ids ? chunk.ids.join(",") : "");
|
140 | template.updateHashForChunk(
|
141 | hash,
|
142 | chunk,
|
143 | compilation.moduleTemplates.javascript,
|
144 | compilation.dependencyTemplates
|
145 | );
|
146 | for (const m of chunk.modulesIterable) {
|
147 | if (typeof m.source === "function") {
|
148 | hash.update(m.hash);
|
149 | }
|
150 | }
|
151 | const digest = (hash.digest(hashDigest));
|
152 | chunk.contentHash.javascript = digest.substr(0, hashDigestLength);
|
153 | });
|
154 | }
|
155 | );
|
156 | }
|
157 |
|
158 | renderJavascript(chunkTemplate, chunk, moduleTemplate, dependencyTemplates) {
|
159 | const moduleSources = Template.renderChunkModules(
|
160 | chunk,
|
161 | m => typeof m.source === "function",
|
162 | moduleTemplate,
|
163 | dependencyTemplates
|
164 | );
|
165 | const core = chunkTemplate.hooks.modules.call(
|
166 | moduleSources,
|
167 | chunk,
|
168 | moduleTemplate,
|
169 | dependencyTemplates
|
170 | );
|
171 | let source = chunkTemplate.hooks.render.call(
|
172 | core,
|
173 | chunk,
|
174 | moduleTemplate,
|
175 | dependencyTemplates
|
176 | );
|
177 | if (chunk.hasEntryModule()) {
|
178 | source = chunkTemplate.hooks.renderWithEntry.call(source, chunk);
|
179 | }
|
180 | chunk.rendered = true;
|
181 | return new ConcatSource(source, ";");
|
182 | }
|
183 | }
|
184 |
|
185 | module.exports = JavascriptModulesPlugin;
|