UNPKG

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