保誠-保戶業務員媒合平台
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
const pluginCompat = require('./util/plugin-compat');
const relateContext = require('./util/relate-context');
const { parityCacheFromCache, pushParityWriteOps } = require('./util/parity');
 
const relateNormalPath = relateContext.relateNormalPath;
 
function relateNormalRequest(compiler, key) {
  return key
    .split('!')
    .map(subkey => relateNormalPath(compiler, subkey))
    .join('!');
}
 
function relateNormalModuleId(compiler, id) {
  return id.substring(0, 24) + relateNormalRequest(compiler, id.substring(24));
}
 
class ModuleCache {
  apply(compiler) {
    const compilerHooks = pluginCompat.hooks(compiler);
 
    let moduleCache = {};
    let parityCache = {};
 
    const moduleArchetypeCache = {
      _ops: [],
 
      get(id) {
        if (moduleCache[id] && !moduleCache[id].invalid) {
          if (typeof moduleCache[id] === 'string') {
            moduleCache[id] = JSON.parse(moduleCache[id]);
          }
          return moduleCache[id];
        }
      },
 
      set(id, item) {
        moduleCache[id] = item;
        if (item) {
          this._ops.push(id);
        } else if (moduleCache[id]) {
          if (typeof moduleCache[id] === 'string') {
            moduleCache[id] = JSON.parse(moduleCache[id]);
          }
          moduleCache[id].invalid = true;
          moduleCache[id].invalidReason = 'overwritten';
 
          this._ops.push(id);
        }
      },
 
      operations() {
        const _this = this;
        const ops = this._ops.map(id => ({
          key: relateNormalModuleId(compiler, id),
          value: _this.get(id) || null,
        }));
        this._ops.length = 0;
        return ops;
      },
    };
 
    compilerHooks._hardSourceArchetypeRegister.call(
      'Module',
      moduleArchetypeCache,
    );
 
    let moduleCacheSerializer;
 
    compilerHooks._hardSourceCreateSerializer.tap(
      'HardSource - ModuleCache',
      (cacheSerializerFactory, cacheDirPath) => {
        moduleCacheSerializer = cacheSerializerFactory.create({
          name: 'module',
          type: 'data',
          cacheDirPath,
          autoParse: true,
        });
      },
    );
 
    compilerHooks._hardSourceResetCache.tap('HardSource - ModuleCache', () => {
      moduleCache = {};
    });
 
    compilerHooks._hardSourceReadCache.tapPromise(
      'HardSource - ModuleCache',
      ({ contextKeys, contextNormalModuleId, copyWithDeser }) =>
        moduleCacheSerializer
          .read()
          .then(_moduleCache => {
            Object.keys(_moduleCache).forEach(key => {
              if (key.startsWith('__hardSource_parityToken')) {
                parityCache[key] = _moduleCache[key];
                delete _moduleCache[key];
              }
            });
            return _moduleCache;
          })
          .then(contextKeys(compiler, contextNormalModuleId))
          .then(copyWithDeser.bind(null, moduleCache)),
    );
 
    compilerHooks._hardSourceParityCache.tap(
      'HardSource - ModuleCache',
      parityRoot => {
        parityCacheFromCache('Module', parityRoot, parityCache);
      },
    );
 
    compilerHooks.compilation.tap('HardSource - ModuleCache', compilation => {
      compilation.__hardSourceModuleCache = moduleCache;
    });
 
    compilerHooks._hardSourceWriteCache.tapPromise(
      'HardSource - ModuleCache',
      compilation => {
        const moduleOps = moduleArchetypeCache.operations();
 
        if (!compilation.compiler.parentCompilation) {
          // Add ops to remove no longer valid modules. If they were replaced with a
          // up to date module, they will already have replaced this item so we
          // won't accidentally delete up to date modules.
          Object.keys(moduleCache).forEach(key => {
            const cacheItem = moduleCache[key];
            if (cacheItem && cacheItem.invalid) {
              // console.log('invalid', cacheItem.invalidReason);
              moduleCache[key] = null;
              moduleOps.push({
                key,
                value: null,
              });
            }
          });
        }
 
        pushParityWriteOps(compilation, moduleOps);
 
        return moduleCacheSerializer.write(moduleOps);
      },
    );
  }
}
 
module.exports = ModuleCache;