UNPKG

5.13 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, RawSource } = require("webpack-sources");
9const { RuntimeGlobals } = require("..");
10const HotUpdateChunk = require("../HotUpdateChunk");
11const Template = require("../Template");
12const {
13 getCompilationHooks,
14 getChunkFilenameTemplate
15} = require("../javascript/JavascriptModulesPlugin");
16const {
17 generateEntryStartup,
18 updateHashForEntryStartup
19} = require("../javascript/StartupHelpers");
20
21/** @typedef {import("../Compiler")} Compiler */
22
23class ModuleChunkFormatPlugin {
24 /**
25 * Apply the plugin
26 * @param {Compiler} compiler the compiler instance
27 * @returns {void}
28 */
29 apply(compiler) {
30 compiler.hooks.thisCompilation.tap(
31 "ModuleChunkFormatPlugin",
32 compilation => {
33 compilation.hooks.additionalChunkRuntimeRequirements.tap(
34 "ModuleChunkFormatPlugin",
35 (chunk, set) => {
36 if (chunk.hasRuntime()) return;
37 if (compilation.chunkGraph.getNumberOfEntryModules(chunk) > 0) {
38 set.add(RuntimeGlobals.require);
39 set.add(RuntimeGlobals.startupEntrypoint);
40 set.add(RuntimeGlobals.externalInstallChunk);
41 }
42 }
43 );
44 const hooks = getCompilationHooks(compilation);
45 hooks.renderChunk.tap(
46 "ModuleChunkFormatPlugin",
47 (modules, renderContext) => {
48 const { chunk, chunkGraph, runtimeTemplate } = renderContext;
49 const hotUpdateChunk =
50 chunk instanceof HotUpdateChunk ? chunk : null;
51 const source = new ConcatSource();
52 if (hotUpdateChunk) {
53 throw new Error(
54 "HMR is not implemented for module chunk format yet"
55 );
56 } else {
57 source.add(`export const id = ${JSON.stringify(chunk.id)};\n`);
58 source.add(`export const ids = ${JSON.stringify(chunk.ids)};\n`);
59 source.add(`export const modules = `);
60 source.add(modules);
61 source.add(`;\n`);
62 const runtimeModules =
63 chunkGraph.getChunkRuntimeModulesInOrder(chunk);
64 if (runtimeModules.length > 0) {
65 source.add("export const runtime =\n");
66 source.add(
67 Template.renderChunkRuntimeModules(
68 runtimeModules,
69 renderContext
70 )
71 );
72 }
73 const entries = Array.from(
74 chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
75 );
76 if (entries.length > 0) {
77 const runtimeChunk = entries[0][1].getRuntimeChunk();
78 const currentOutputName = compilation
79 .getPath(
80 getChunkFilenameTemplate(chunk, compilation.outputOptions),
81 {
82 chunk,
83 contentHashType: "javascript"
84 }
85 )
86 .split("/");
87 const runtimeOutputName = compilation
88 .getPath(
89 getChunkFilenameTemplate(
90 runtimeChunk,
91 compilation.outputOptions
92 ),
93 {
94 chunk: runtimeChunk,
95 contentHashType: "javascript"
96 }
97 )
98 .split("/");
99
100 // remove filename, we only need the directory
101 const outputFilename = currentOutputName.pop();
102
103 // remove common parts
104 while (
105 currentOutputName.length > 0 &&
106 runtimeOutputName.length > 0 &&
107 currentOutputName[0] === runtimeOutputName[0]
108 ) {
109 currentOutputName.shift();
110 runtimeOutputName.shift();
111 }
112
113 // create final path
114 const runtimePath =
115 (currentOutputName.length > 0
116 ? "../".repeat(currentOutputName.length)
117 : "./") + runtimeOutputName.join("/");
118
119 const entrySource = new ConcatSource();
120 entrySource.add(source);
121 entrySource.add(";\n\n// load runtime\n");
122 entrySource.add(
123 `import __webpack_require__ from ${JSON.stringify(
124 runtimePath
125 )};\n`
126 );
127 entrySource.add(
128 `import * as __webpack_self_exports__ from ${JSON.stringify(
129 "./" + outputFilename
130 )};\n`
131 );
132 entrySource.add(
133 `${RuntimeGlobals.externalInstallChunk}(__webpack_self_exports__);\n`
134 );
135 const startupSource = new RawSource(
136 generateEntryStartup(
137 chunkGraph,
138 runtimeTemplate,
139 entries,
140 chunk,
141 false
142 )
143 );
144 entrySource.add(
145 hooks.renderStartup.call(
146 startupSource,
147 entries[entries.length - 1][0],
148 {
149 ...renderContext,
150 inlined: false
151 }
152 )
153 );
154 return entrySource;
155 }
156 }
157 return source;
158 }
159 );
160 hooks.chunkHash.tap(
161 "ModuleChunkFormatPlugin",
162 (chunk, hash, { chunkGraph, runtimeTemplate }) => {
163 if (chunk.hasRuntime()) return;
164 hash.update("ModuleChunkFormatPlugin");
165 hash.update("1");
166 const entries = Array.from(
167 chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
168 );
169 updateHashForEntryStartup(hash, chunkGraph, entries, chunk);
170 }
171 );
172 }
173 );
174 }
175}
176
177module.exports = ModuleChunkFormatPlugin;