source: trip-planner-front/node_modules/webpack/lib/runtime/GetChunkFilenameRuntimeModule.js@ 571e0df

Last change on this file since 571e0df was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 8.2 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3*/
4
5"use strict";
6
7const RuntimeGlobals = require("../RuntimeGlobals");
8const RuntimeModule = require("../RuntimeModule");
9const Template = require("../Template");
10const { first } = require("../util/SetHelpers");
11
12/** @typedef {import("../Chunk")} Chunk */
13/** @typedef {import("../Compilation")} Compilation */
14/** @typedef {import("../Compilation").AssetInfo} AssetInfo */
15/** @typedef {import("../Compilation").PathData} PathData */
16
17/** @typedef {function(PathData, AssetInfo=): string} FilenameFunction */
18
19class GetChunkFilenameRuntimeModule extends RuntimeModule {
20 /**
21 * @param {string} contentType the contentType to use the content hash for
22 * @param {string} name kind of filename
23 * @param {string} global function name to be assigned
24 * @param {function(Chunk): string | FilenameFunction} getFilenameForChunk functor to get the filename or function
25 * @param {boolean} allChunks when false, only async chunks are included
26 */
27 constructor(contentType, name, global, getFilenameForChunk, allChunks) {
28 super(`get ${name} chunk filename`);
29 this.contentType = contentType;
30 this.global = global;
31 this.getFilenameForChunk = getFilenameForChunk;
32 this.allChunks = allChunks;
33 }
34
35 /**
36 * @returns {string} runtime code
37 */
38 generate() {
39 const {
40 global,
41 chunk,
42 chunkGraph,
43 contentType,
44 getFilenameForChunk,
45 allChunks,
46 compilation
47 } = this;
48 const { runtimeTemplate } = compilation;
49
50 /** @type {Map<string | FilenameFunction, Set<Chunk>>} */
51 const chunkFilenames = new Map();
52 let maxChunks = 0;
53 /** @type {string} */
54 let dynamicFilename;
55
56 /**
57 * @param {Chunk} c the chunk
58 * @returns {void}
59 */
60 const addChunk = c => {
61 const chunkFilename = getFilenameForChunk(c);
62 if (chunkFilename) {
63 let set = chunkFilenames.get(chunkFilename);
64 if (set === undefined) {
65 chunkFilenames.set(chunkFilename, (set = new Set()));
66 }
67 set.add(c);
68 if (typeof chunkFilename === "string") {
69 if (set.size < maxChunks) return;
70 if (set.size === maxChunks) {
71 if (chunkFilename.length < dynamicFilename.length) return;
72 if (chunkFilename.length === dynamicFilename.length) {
73 if (chunkFilename < dynamicFilename) return;
74 }
75 }
76 maxChunks = set.size;
77 dynamicFilename = chunkFilename;
78 }
79 }
80 };
81
82 /** @type {string[]} */
83 const includedChunksMessages = [];
84 if (allChunks) {
85 includedChunksMessages.push("all chunks");
86 for (const c of chunk.getAllReferencedChunks()) {
87 addChunk(c);
88 }
89 } else {
90 includedChunksMessages.push("async chunks");
91 for (const c of chunk.getAllAsyncChunks()) {
92 addChunk(c);
93 }
94 const includeEntries = chunkGraph
95 .getTreeRuntimeRequirements(chunk)
96 .has(RuntimeGlobals.ensureChunkIncludeEntries);
97 if (includeEntries) {
98 includedChunksMessages.push("sibling chunks for the entrypoint");
99 for (const c of chunkGraph.getChunkEntryDependentChunksIterable(
100 chunk
101 )) {
102 addChunk(c);
103 }
104 }
105 }
106 for (const entrypoint of chunk.getAllReferencedAsyncEntrypoints()) {
107 addChunk(entrypoint.chunks[entrypoint.chunks.length - 1]);
108 }
109
110 /** @type {Map<string, Set<string | number>>} */
111 const staticUrls = new Map();
112 /** @type {Set<Chunk>} */
113 const dynamicUrlChunks = new Set();
114
115 /**
116 * @param {Chunk} c the chunk
117 * @param {string | FilenameFunction} chunkFilename the filename template for the chunk
118 * @returns {void}
119 */
120 const addStaticUrl = (c, chunkFilename) => {
121 /**
122 * @param {string | number} value a value
123 * @returns {string} string to put in quotes
124 */
125 const unquotedStringify = value => {
126 const str = `${value}`;
127 if (str.length >= 5 && str === `${c.id}`) {
128 // This is shorter and generates the same result
129 return '" + chunkId + "';
130 }
131 const s = JSON.stringify(str);
132 return s.slice(1, s.length - 1);
133 };
134 const unquotedStringifyWithLength = value => length =>
135 unquotedStringify(`${value}`.slice(0, length));
136 const chunkFilenameValue =
137 typeof chunkFilename === "function"
138 ? JSON.stringify(
139 chunkFilename({
140 chunk: c,
141 contentHashType: contentType
142 })
143 )
144 : JSON.stringify(chunkFilename);
145 const staticChunkFilename = compilation.getPath(chunkFilenameValue, {
146 hash: `" + ${RuntimeGlobals.getFullHash}() + "`,
147 hashWithLength: length =>
148 `" + ${RuntimeGlobals.getFullHash}().slice(0, ${length}) + "`,
149 chunk: {
150 id: unquotedStringify(c.id),
151 hash: unquotedStringify(c.renderedHash),
152 hashWithLength: unquotedStringifyWithLength(c.renderedHash),
153 name: unquotedStringify(c.name || c.id),
154 contentHash: {
155 [contentType]: unquotedStringify(c.contentHash[contentType])
156 },
157 contentHashWithLength: {
158 [contentType]: unquotedStringifyWithLength(
159 c.contentHash[contentType]
160 )
161 }
162 },
163 contentHashType: contentType
164 });
165 let set = staticUrls.get(staticChunkFilename);
166 if (set === undefined) {
167 staticUrls.set(staticChunkFilename, (set = new Set()));
168 }
169 set.add(c.id);
170 };
171
172 for (const [filename, chunks] of chunkFilenames) {
173 if (filename !== dynamicFilename) {
174 for (const c of chunks) addStaticUrl(c, filename);
175 } else {
176 for (const c of chunks) dynamicUrlChunks.add(c);
177 }
178 }
179
180 /**
181 * @param {function(Chunk): string | number} fn function from chunk to value
182 * @returns {string} code with static mapping of results of fn
183 */
184 const createMap = fn => {
185 const obj = {};
186 let useId = false;
187 let lastKey;
188 let entries = 0;
189 for (const c of dynamicUrlChunks) {
190 const value = fn(c);
191 if (value === c.id) {
192 useId = true;
193 } else {
194 obj[c.id] = value;
195 lastKey = c.id;
196 entries++;
197 }
198 }
199 if (entries === 0) return "chunkId";
200 if (entries === 1) {
201 return useId
202 ? `(chunkId === ${JSON.stringify(lastKey)} ? ${JSON.stringify(
203 obj[lastKey]
204 )} : chunkId)`
205 : JSON.stringify(obj[lastKey]);
206 }
207 return useId
208 ? `(${JSON.stringify(obj)}[chunkId] || chunkId)`
209 : `${JSON.stringify(obj)}[chunkId]`;
210 };
211
212 /**
213 * @param {function(Chunk): string | number} fn function from chunk to value
214 * @returns {string} code with static mapping of results of fn for including in quoted string
215 */
216 const mapExpr = fn => {
217 return `" + ${createMap(fn)} + "`;
218 };
219
220 /**
221 * @param {function(Chunk): string | number} fn function from chunk to value
222 * @returns {function(number): string} function which generates code with static mapping of results of fn for including in quoted string for specific length
223 */
224 const mapExprWithLength = fn => length => {
225 return `" + ${createMap(c => `${fn(c)}`.slice(0, length))} + "`;
226 };
227
228 const url =
229 dynamicFilename &&
230 compilation.getPath(JSON.stringify(dynamicFilename), {
231 hash: `" + ${RuntimeGlobals.getFullHash}() + "`,
232 hashWithLength: length =>
233 `" + ${RuntimeGlobals.getFullHash}().slice(0, ${length}) + "`,
234 chunk: {
235 id: `" + chunkId + "`,
236 hash: mapExpr(c => c.renderedHash),
237 hashWithLength: mapExprWithLength(c => c.renderedHash),
238 name: mapExpr(c => c.name || c.id),
239 contentHash: {
240 [contentType]: mapExpr(c => c.contentHash[contentType])
241 },
242 contentHashWithLength: {
243 [contentType]: mapExprWithLength(c => c.contentHash[contentType])
244 }
245 },
246 contentHashType: contentType
247 });
248
249 return Template.asString([
250 `// This function allow to reference ${includedChunksMessages.join(
251 " and "
252 )}`,
253 `${global} = ${runtimeTemplate.basicFunction(
254 "chunkId",
255
256 staticUrls.size > 0
257 ? [
258 "// return url for filenames not based on template",
259 // it minimizes to `x===1?"...":x===2?"...":"..."`
260 Template.asString(
261 Array.from(staticUrls, ([url, ids]) => {
262 const condition =
263 ids.size === 1
264 ? `chunkId === ${JSON.stringify(first(ids))}`
265 : `{${Array.from(
266 ids,
267 id => `${JSON.stringify(id)}:1`
268 ).join(",")}}[chunkId]`;
269 return `if (${condition}) return ${url};`;
270 })
271 ),
272 "// return url for filenames based on template",
273 `return ${url};`
274 ]
275 : ["// return url for filenames based on template", `return ${url};`]
276 )};`
277 ]);
278 }
279}
280
281module.exports = GetChunkFilenameRuntimeModule;
Note: See TracBrowser for help on using the repository browser.