马宇豪
2024-07-16 f591c27b57e2418c9495bc02ae8cfff84d35bc18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Tobias Koppers @sokra
*/
 
"use strict";
 
const { ConcatSource, PrefixSource, RawSource } = require("webpack-sources");
const { RuntimeGlobals } = require("..");
const HotUpdateChunk = require("../HotUpdateChunk");
const Template = require("../Template");
const { getCompilationHooks } = require("./JavascriptModulesPlugin");
const {
    generateEntryStartup,
    updateHashForEntryStartup
} = require("./StartupHelpers");
 
/** @typedef {import("../Compiler")} Compiler */
 
class ArrayPushCallbackChunkFormatPlugin {
    /**
     * Apply the plugin
     * @param {Compiler} compiler the compiler instance
     * @returns {void}
     */
    apply(compiler) {
        compiler.hooks.thisCompilation.tap(
            "ArrayPushCallbackChunkFormatPlugin",
            compilation => {
                compilation.hooks.additionalChunkRuntimeRequirements.tap(
                    "ArrayPushCallbackChunkFormatPlugin",
                    (chunk, set, { chunkGraph }) => {
                        if (chunk.hasRuntime()) return;
                        if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
                            set.add(RuntimeGlobals.onChunksLoaded);
                            set.add(RuntimeGlobals.require);
                        }
                        set.add(RuntimeGlobals.chunkCallback);
                    }
                );
                const hooks = getCompilationHooks(compilation);
                hooks.renderChunk.tap(
                    "ArrayPushCallbackChunkFormatPlugin",
                    (modules, renderContext) => {
                        const { chunk, chunkGraph, runtimeTemplate } = renderContext;
                        const hotUpdateChunk =
                            chunk instanceof HotUpdateChunk ? chunk : null;
                        const globalObject = runtimeTemplate.globalObject;
                        const source = new ConcatSource();
                        const runtimeModules =
                            chunkGraph.getChunkRuntimeModulesInOrder(chunk);
                        if (hotUpdateChunk) {
                            const hotUpdateGlobal =
                                runtimeTemplate.outputOptions.hotUpdateGlobal;
                            source.add(
                                `${globalObject}[${JSON.stringify(hotUpdateGlobal)}](`
                            );
                            source.add(`${JSON.stringify(chunk.id)},`);
                            source.add(modules);
                            if (runtimeModules.length > 0) {
                                source.add(",\n");
                                const runtimePart = Template.renderChunkRuntimeModules(
                                    runtimeModules,
                                    renderContext
                                );
                                source.add(runtimePart);
                            }
                            source.add(")");
                        } else {
                            const chunkLoadingGlobal =
                                runtimeTemplate.outputOptions.chunkLoadingGlobal;
                            source.add(
                                `(${globalObject}[${JSON.stringify(
                                    chunkLoadingGlobal
                                )}] = ${globalObject}[${JSON.stringify(
                                    chunkLoadingGlobal
                                )}] || []).push([`
                            );
                            source.add(`${JSON.stringify(chunk.ids)},`);
                            source.add(modules);
                            const entries = Array.from(
                                chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
                            );
                            if (runtimeModules.length > 0 || entries.length > 0) {
                                const runtime = new ConcatSource(
                                    (runtimeTemplate.supportsArrowFunction()
                                        ? `${RuntimeGlobals.require} =>`
                                        : `function(${RuntimeGlobals.require})`) +
                                        " { // webpackRuntimeModules\n"
                                );
                                if (runtimeModules.length > 0) {
                                    runtime.add(
                                        Template.renderRuntimeModules(runtimeModules, {
                                            ...renderContext,
                                            codeGenerationResults: compilation.codeGenerationResults
                                        })
                                    );
                                }
                                if (entries.length > 0) {
                                    const startupSource = new RawSource(
                                        generateEntryStartup(
                                            chunkGraph,
                                            runtimeTemplate,
                                            entries,
                                            chunk,
                                            true
                                        )
                                    );
                                    runtime.add(
                                        hooks.renderStartup.call(
                                            startupSource,
                                            entries[entries.length - 1][0],
                                            {
                                                ...renderContext,
                                                inlined: false
                                            }
                                        )
                                    );
                                    if (
                                        chunkGraph
                                            .getChunkRuntimeRequirements(chunk)
                                            .has(RuntimeGlobals.returnExportsFromRuntime)
                                    ) {
                                        runtime.add(`return ${RuntimeGlobals.exports};\n`);
                                    }
                                }
                                runtime.add("}\n");
                                source.add(",\n");
                                source.add(new PrefixSource("/******/ ", runtime));
                            }
                            source.add("])");
                        }
                        return source;
                    }
                );
                hooks.chunkHash.tap(
                    "ArrayPushCallbackChunkFormatPlugin",
                    (chunk, hash, { chunkGraph, runtimeTemplate }) => {
                        if (chunk.hasRuntime()) return;
                        hash.update(
                            `ArrayPushCallbackChunkFormatPlugin1${runtimeTemplate.outputOptions.chunkLoadingGlobal}${runtimeTemplate.outputOptions.hotUpdateGlobal}${runtimeTemplate.globalObject}`
                        );
                        const entries = Array.from(
                            chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
                        );
                        updateHashForEntryStartup(hash, chunkGraph, entries, chunk);
                    }
                );
            }
        );
    }
}
 
module.exports = ArrayPushCallbackChunkFormatPlugin;