UNPKG

5.42 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5"use strict";
6
7const Parser = require("./Parser");
8const Template = require("./Template");
9const { ConcatSource } = require("webpack-sources");
10const JavascriptGenerator = require("./JavascriptGenerator");
11const createHash = require("./util/createHash");
12
13class 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 = /** @type {string} */ (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
185module.exports = JavascriptModulesPlugin;