UNPKG

4.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 Entrypoint = require("../Entrypoint");
9const RuntimeGlobals = require("../RuntimeGlobals");
10const Template = require("../Template");
11const { isSubset } = require("../util/SetHelpers");
12const { chunkHasJs } = require("./JavascriptModulesPlugin");
13
14/** @typedef {import("../util/Hash")} Hash */
15/** @typedef {import("../Chunk")} Chunk */
16/** @typedef {import("../Compilation")} Compilation */
17/** @typedef {import("../ChunkGraph")} ChunkGraph */
18/** @typedef {import("../ChunkGroup")} ChunkGroup */
19/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
20/** @typedef {(string|number)[]} EntryItem */
21
22// TODO move to this file to ../javascript/ChunkHelpers.js
23
24/**
25 * @param {Entrypoint} entrypoint a chunk group
26 * @param {Chunk} excludedChunk1 current chunk which is excluded
27 * @param {Chunk} excludedChunk2 runtime chunk which is excluded
28 * @returns {Set<Chunk>} chunks
29 */
30const getAllChunks = (entrypoint, excludedChunk1, excludedChunk2) => {
31 const queue = new Set([entrypoint]);
32 const chunks = new Set();
33 for (const entrypoint of queue) {
34 for (const chunk of entrypoint.chunks) {
35 if (chunk === excludedChunk1) continue;
36 if (chunk === excludedChunk2) continue;
37 chunks.add(chunk);
38 }
39 for (const parent of entrypoint.parentsIterable) {
40 if (parent instanceof Entrypoint) queue.add(parent);
41 }
42 }
43 return chunks;
44};
45
46const EXPORT_PREFIX = "var __webpack_exports__ = ";
47
48/**
49 * @param {ChunkGraph} chunkGraph chunkGraph
50 * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
51 * @param {import("../ChunkGraph").EntryModuleWithChunkGroup[]} entries entries
52 * @param {Chunk} chunk chunk
53 * @param {boolean} passive true: passive startup with on chunks loaded
54 * @returns {string} runtime code
55 */
56exports.generateEntryStartup = (
57 chunkGraph,
58 runtimeTemplate,
59 entries,
60 chunk,
61 passive
62) => {
63 /** @type {string[]} */
64 const runtime = [
65 `var __webpack_exec__ = ${runtimeTemplate.returningFunction(
66 `__webpack_require__(${RuntimeGlobals.entryModuleId} = moduleId)`,
67 "moduleId"
68 )}`
69 ];
70
71 const runModule = id => {
72 return `__webpack_exec__(${JSON.stringify(id)})`;
73 };
74 const outputCombination = (chunks, moduleIds, final) => {
75 if (chunks.size === 0) {
76 runtime.push(
77 `${final ? EXPORT_PREFIX : ""}(${moduleIds.map(runModule).join(", ")});`
78 );
79 } else {
80 const fn = runtimeTemplate.returningFunction(
81 moduleIds.map(runModule).join(", ")
82 );
83 runtime.push(
84 `${final && !passive ? EXPORT_PREFIX : ""}${
85 passive
86 ? RuntimeGlobals.onChunksLoaded
87 : RuntimeGlobals.startupEntrypoint
88 }(0, ${JSON.stringify(Array.from(chunks, c => c.id))}, ${fn});`
89 );
90 if (final && passive) {
91 runtime.push(`${EXPORT_PREFIX}${RuntimeGlobals.onChunksLoaded}();`);
92 }
93 }
94 };
95
96 let currentChunks = undefined;
97 let currentModuleIds = undefined;
98
99 for (const [module, entrypoint] of entries) {
100 const runtimeChunk = entrypoint.getRuntimeChunk();
101 const moduleId = chunkGraph.getModuleId(module);
102 const chunks = getAllChunks(entrypoint, chunk, runtimeChunk);
103 if (
104 currentChunks &&
105 currentChunks.size === chunks.size &&
106 isSubset(currentChunks, chunks)
107 ) {
108 currentModuleIds.push(moduleId);
109 } else {
110 if (currentChunks) {
111 outputCombination(currentChunks, currentModuleIds);
112 }
113 currentChunks = chunks;
114 currentModuleIds = [moduleId];
115 }
116 }
117
118 // output current modules with export prefix
119 if (currentChunks) {
120 outputCombination(currentChunks, currentModuleIds, true);
121 }
122 runtime.push("");
123 return Template.asString(runtime);
124};
125
126/**
127 * @param {Hash} hash the hash to update
128 * @param {ChunkGraph} chunkGraph chunkGraph
129 * @param {import("../ChunkGraph").EntryModuleWithChunkGroup[]} entries entries
130 * @param {Chunk} chunk chunk
131 * @returns {void}
132 */
133exports.updateHashForEntryStartup = (hash, chunkGraph, entries, chunk) => {
134 for (const [module, entrypoint] of entries) {
135 const runtimeChunk = entrypoint.getRuntimeChunk();
136 const moduleId = chunkGraph.getModuleId(module);
137 hash.update(`${moduleId}`);
138 for (const c of getAllChunks(entrypoint, chunk, runtimeChunk))
139 hash.update(`${c.id}`);
140 }
141};
142
143/**
144 * @param {Chunk} chunk the chunk
145 * @param {ChunkGraph} chunkGraph the chunk graph
146 * @returns {Set<number | string>} initially fulfilled chunk ids
147 */
148exports.getInitialChunkIds = (chunk, chunkGraph) => {
149 const initialChunkIds = new Set(chunk.ids);
150 for (const c of chunk.getAllInitialChunks()) {
151 if (c === chunk || chunkHasJs(c, chunkGraph)) continue;
152 for (const id of c.ids) initialChunkIds.add(id);
153 }
154 return initialChunkIds;
155};