保誠-保戶業務員媒合平台
HelenHuang
2022-06-09 9bdb95c9e34cef640534e5e5a1e2225a80442000
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
/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Tobias Koppers @sokra
*/
"use strict";
 
const Queue = require("../util/Queue");
const { intersect } = require("../util/SetHelpers");
 
const getParentChunksWithModule = (currentChunk, module) => {
    const chunks = [];
    const stack = new Set(currentChunk.parentsIterable);
 
    for (const chunk of stack) {
        if (chunk.containsModule(module)) {
            chunks.push(chunk);
        } else {
            for (const parent of chunk.parentsIterable) {
                stack.add(parent);
            }
        }
    }
 
    return chunks;
};
 
class RemoveParentModulesPlugin {
    apply(compiler) {
        compiler.hooks.compilation.tap("RemoveParentModulesPlugin", compilation => {
            const handler = (chunks, chunkGroups) => {
                const queue = new Queue();
                const availableModulesMap = new WeakMap();
 
                for (const chunkGroup of compilation.entrypoints.values()) {
                    // initialize available modules for chunks without parents
                    availableModulesMap.set(chunkGroup, new Set());
                    for (const child of chunkGroup.childrenIterable) {
                        queue.enqueue(child);
                    }
                }
 
                while (queue.length > 0) {
                    const chunkGroup = queue.dequeue();
                    let availableModules = availableModulesMap.get(chunkGroup);
                    let changed = false;
                    for (const parent of chunkGroup.parentsIterable) {
                        const availableModulesInParent = availableModulesMap.get(parent);
                        if (availableModulesInParent !== undefined) {
                            // If we know the available modules in parent: process these
                            if (availableModules === undefined) {
                                // if we have not own info yet: create new entry
                                availableModules = new Set(availableModulesInParent);
                                for (const chunk of parent.chunks) {
                                    for (const m of chunk.modulesIterable) {
                                        availableModules.add(m);
                                    }
                                }
                                availableModulesMap.set(chunkGroup, availableModules);
                                changed = true;
                            } else {
                                for (const m of availableModules) {
                                    if (
                                        !parent.containsModule(m) &&
                                        !availableModulesInParent.has(m)
                                    ) {
                                        availableModules.delete(m);
                                        changed = true;
                                    }
                                }
                            }
                        }
                    }
                    if (changed) {
                        // if something changed: enqueue our children
                        for (const child of chunkGroup.childrenIterable) {
                            queue.enqueue(child);
                        }
                    }
                }
 
                // now we have available modules for every chunk
                for (const chunk of chunks) {
                    const availableModulesSets = Array.from(
                        chunk.groupsIterable,
                        chunkGroup => availableModulesMap.get(chunkGroup)
                    );
                    if (availableModulesSets.some(s => s === undefined)) continue; // No info about this chunk group
                    const availableModules =
                        availableModulesSets.length === 1
                            ? availableModulesSets[0]
                            : intersect(availableModulesSets);
                    const numberOfModules = chunk.getNumberOfModules();
                    const toRemove = new Set();
                    if (numberOfModules < availableModules.size) {
                        for (const m of chunk.modulesIterable) {
                            if (availableModules.has(m)) {
                                toRemove.add(m);
                            }
                        }
                    } else {
                        for (const m of availableModules) {
                            if (chunk.containsModule(m)) {
                                toRemove.add(m);
                            }
                        }
                    }
                    for (const module of toRemove) {
                        module.rewriteChunkInReasons(
                            chunk,
                            getParentChunksWithModule(chunk, module)
                        );
                        chunk.removeModule(module);
                    }
                }
            };
            compilation.hooks.optimizeChunksBasic.tap(
                "RemoveParentModulesPlugin",
                handler
            );
            compilation.hooks.optimizeExtractedChunksBasic.tap(
                "RemoveParentModulesPlugin",
                handler
            );
        });
    }
}
module.exports = RemoveParentModulesPlugin;