123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- const nodeObjectHash = require('node-object-hash');
- const parseJson = require('parse-json');
- const serial = require('./util/serial');
- const pluginCompat = require('./util/plugin-compat');
- const relateContext = require('./util/relate-context');
- const { parityCacheFromCache, pushParityWriteOps } = require('./util/parity');
- const serialJsonKey = {
- freeze(arg, value, extra) {
- return JSON.parse(arg);
- },
- thaw(arg, frozen, extra) {
- return JSON.stringify(arg);
- },
- };
- const serialJson = {
- freeze(arg, value, extra) {
- return JSON.stringify(arg);
- },
- thaw(arg, frozen, extra) {
- return JSON.parse(arg);
- },
- };
- const serialObjectAssign = serial.objectAssign;
- const serialResolveOptionsKey = serialObjectAssign({
- context: serial.path,
- userRequest: serial.request,
- options: serialObjectAssign({
- request: serial.request,
- }),
- });
- const serialResolveKey = serialObjectAssign({
- context: serial.path,
- request: serial.request,
- });
- const serialNormalModuleResolveKey = serial.pipe(
- serialJsonKey,
- {
- freeze(arg, key, extra) {
- if (Array.isArray(arg)) {
- return [
- arg[0],
- serial.path.freeze(arg[1], arg[1], extra),
- serial.request.freeze(arg[2], arg[2], extra),
- ];
- } else if (!arg.request) {
- return serialResolveOptionsKey.freeze(arg, arg, extra);
- } else {
- return serialResolveKey.freeze(arg, arg, extra);
- }
- },
- thaw(arg, frozen, extra) {
- if (Array.isArray(arg)) {
- return [
- arg[0],
- serial.path.thaw(arg[1], arg[1], extra),
- serial.request.thaw(arg[2], arg[2], extra),
- ];
- } else if (!arg.request) {
- return serialResolveOptionsKey.thaw(arg, arg, extra);
- } else {
- return serialResolveKey.thaw(arg, arg, extra);
- }
- },
- },
- serialJson,
- );
- const serialNormalModuleId = {
- freeze(arg, module, extra) {
- return (
- id.substring(0, 24) + serial.request.freeze(id.substring(24), id, extra)
- );
- },
- thaw(arg, frozen, extra) {
- return (
- id.substring(0, 24) + serial.request.thaw(id.substring(24), id, extra)
- );
- },
- };
- const serialResolveContext = serialObjectAssign({
- identifier: serialNormalModuleId,
- resource: serialNormalModuleId,
- });
- const serialResolveNormal = serialObjectAssign({
- context: serial.path,
- request: serial.request,
- userRequest: serial.request,
- rawRequest: serial.request,
- resource: serial.request,
- loaders: serial.loaders,
- resourceResolveData: serial.objectAssign({
- context: serial.created({
- issuer: serial.request,
- resolveOptions: serial.identity,
- }),
- path: serial.path,
- request: serial.request,
- descriptionFilePath: serial.path,
- descriptionFileRoot: serial.path,
- }),
- });
- const serialResolve = {
- freeze(arg, module, extra) {
- if (arg.type === 'context') {
- return serialResolveContext.freeze(arg, arg, extra);
- }
- return serialResolveNormal.freeze(arg, arg, extra);
- },
- thaw(arg, frozen, extra) {
- if (arg.type === 'context') {
- return serialResolveContext.thaw(arg, arg, extra);
- }
- return serialResolveNormal.thaw(arg, arg, extra);
- },
- };
- class ModuleResolverCache {
- apply(compiler) {
- let moduleResolveCache = {};
- let parityCache = {};
- let moduleResolveCacheChange = [];
- let moduleResolveCacheSerializer;
- const compilerHooks = pluginCompat.hooks(compiler);
- compilerHooks._hardSourceCreateSerializer.tap(
- 'HardSource - ModuleResolverCache',
- (cacheSerializerFactory, cacheDirPath) => {
- moduleResolveCacheSerializer = cacheSerializerFactory.create({
- name: 'module-resolve',
- type: 'data',
- autoParse: true,
- cacheDirPath,
- });
- },
- );
- compilerHooks._hardSourceResetCache.tap(
- 'HardSource - ModuleResolverCache',
- () => {
- moduleResolveCache = {};
- parityCache = {};
- },
- );
- compilerHooks._hardSourceReadCache.tapPromise(
- 'HardSource - ModuleResolverCache',
- ({
- contextKeys,
- contextValues,
- contextNormalPath,
- contextNormalRequest,
- contextNormalModuleId,
- copyWithDeser,
- }) => {
- function contextNormalModuleResolveKey(compiler, key) {
- if (key.startsWith('__hardSource_parityToken')) {
- return key;
- }
- const parsed = parseJson(key);
- if (Array.isArray(parsed)) {
- return JSON.stringify([
- parsed[0],
- contextNormalPath(compiler, parsed[1]),
- parsed[2],
- ]);
- } else {
- return JSON.stringify(
- Object.assign({}, parsed, {
- context: contextNormalPath(compiler, parsed.context),
- }),
- );
- }
- }
- function contextNormalModuleResolve(compiler, resolved, key) {
- if (key.startsWith('__hardSource_parityToken')) {
- parityCache[key] = resolved;
- return;
- }
- if (typeof resolved === 'string') {
- resolved = parseJson(resolved);
- }
- if (resolved.type === 'context') {
- return Object.assign({}, resolved, {
- identifier: contextNormalModuleId(compiler, resolved.identifier),
- resource: contextNormalRequest(compiler, resolved.resource),
- });
- }
- return serialResolveNormal.thaw(resolved, resolved, {
- compiler,
- });
- }
- return moduleResolveCacheSerializer
- .read()
- .then(contextKeys(compiler, contextNormalModuleResolveKey))
- .then(contextValues(compiler, contextNormalModuleResolve))
- .then(copyWithDeser.bind(null, moduleResolveCache));
- },
- );
- compilerHooks._hardSourceParityCache.tap(
- 'HardSource - ModuleResolverCache',
- parityRoot => {
- parityCacheFromCache('ModuleResolver', parityRoot, parityCache);
- },
- );
- compilerHooks._hardSourceVerifyCache.tapPromise(
- 'HardSource - ModuleResolverCache',
- () =>
- compiler.__hardSource_missingVerify.then(() => {
- const missingCache = compiler.__hardSource_missingCache;
- // Invalidate resolve cache items.
- Object.keys(moduleResolveCache).forEach(key => {
- const resolveKey = parseJson(key);
- const resolveItem = moduleResolveCache[key];
- let normalId = 'normal';
- if (resolveItem.resolveOptions) {
- normalId = `normal-${new nodeObjectHash({ sort: false }).hash(
- resolveItem.resolveOptions,
- )}`;
- }
- if (resolveItem.type === 'context') {
- const contextMissing =
- missingCache.context[
- JSON.stringify([
- resolveKey.context,
- resolveItem.resource.split('?')[0],
- ])
- ];
- if (!contextMissing || contextMissing.invalid) {
- resolveItem.invalid = true;
- resolveItem.invalidReason = 'resolved context invalid';
- }
- } else {
- const normalMissing =
- missingCache[normalId] &&
- missingCache[normalId][
- JSON.stringify([
- resolveKey[1],
- resolveItem.resource.split('?')[0],
- ])
- ];
- if (!normalMissing || normalMissing.invalid) {
- resolveItem.invalid = true;
- resolveItem.invalidReason = `resolved normal invalid${
- normalMissing
- ? ` ${normalMissing.invalidReason}`
- : ': resolve entry not in cache'
- }`;
- }
- resolveItem.loaders.forEach(loader => {
- if (typeof loader === 'object') {
- if (loader.loader != null) {
- loader = loader.loader;
- } else {
- // Convert { "0": "b", "1": "a", "2": "r" } into "bar"
- loader = Object.assign([], loader).join('');
- }
- }
- // Loaders specified in a dependency are searched for from the
- // context of the module containing that dependency.
- let loaderMissing =
- missingCache.loader[
- JSON.stringify([resolveKey[1], loader.split('?')[0]])
- ];
- if (!loaderMissing) {
- // webpack searches for rule based loaders from the project
- // context.
- loaderMissing =
- missingCache.loader[
- JSON.stringify([
- // compiler may be a Watching instance, which refers to the
- // compiler
- (compiler.options || compiler.compiler.options).context,
- loader.split('?')[0],
- ])
- ];
- }
- if (!loaderMissing || loaderMissing.invalid) {
- resolveItem.invalid = true;
- resolveItem.invalidReason = 'resolved loader invalid';
- }
- });
- }
- });
- }),
- );
- compilerHooks.compilation.tap(
- 'HardSource - ModuleResolverCache',
- compilation => {
- compilation.__hardSourceModuleResolveCache = moduleResolveCache;
- compilation.__hardSourceModuleResolveCacheChange = moduleResolveCacheChange;
- },
- );
- compilerHooks._hardSourceWriteCache.tapPromise(
- 'HardSource - ModuleResolverCache',
- (
- compilation,
- { relateNormalPath, relateNormalModuleId, relateNormalRequest },
- ) => {
- if (compilation.compiler.parentCompilation) {
- const moduleResolveOps = [];
- pushParityWriteOps(compilation, moduleResolveOps);
- return moduleResolveCacheSerializer.write(moduleResolveOps);
- }
- const moduleResolveOps = [];
- function relateNormalModuleResolveKey(compiler, key) {
- const parsed = parseJson(key);
- if (Array.isArray(parsed)) {
- return JSON.stringify([
- parsed[0],
- relateNormalPath(compiler, parsed[1]),
- relateContext.relateAbsoluteRequest(parsed[1], parsed[2]),
- ]);
- } else {
- if (!parsed.request) {
- return JSON.stringify(
- Object.assign({}, parsed, {
- context: relateNormalPath(compiler, parsed.context),
- userRequest: relateContext.relateAbsoluteRequest(
- parsed.context,
- parsed.userRequest,
- ),
- options: Object.assign({}, parsed.options, {
- request: relateContext.relateAbsoluteRequest(
- parsed.context,
- parsed.options.request,
- ),
- }),
- }),
- );
- } else {
- return JSON.stringify(
- Object.assign({}, parsed, {
- context: relateNormalPath(compiler, parsed.context),
- request: relateContext.relateAbsoluteRequest(
- parsed.context,
- parsed.request,
- ),
- }),
- );
- }
- }
- }
- function relateNormalModuleResolve(compiler, resolved) {
- if (resolved.type === 'context') {
- return Object.assign({}, resolved, {
- identifier: relateNormalModuleId(compiler, resolved.identifier),
- resource: relateNormalRequest(compiler, resolved.resource),
- });
- }
- return serialResolveNormal.freeze(resolved, resolved, {
- compiler,
- });
- }
- moduleResolveCacheChange
- .reduce((carry, value) => {
- if (!carry.includes(value)) {
- carry.push(value);
- }
- return carry;
- }, [])
- .forEach(key => {
- // console.log(key, moduleResolveCache[key]);
- // moduleResolveCache[key] && console.log(relateNormalModuleResolveKey(compiler, key));
- // moduleResolveCache[key] && console.log(relateNormalModuleResolve(compiler, moduleResolveCache[key]));
- moduleResolveOps.push({
- key: relateNormalModuleResolveKey(compiler, key),
- value: moduleResolveCache[key]
- ? relateNormalModuleResolve(compiler, moduleResolveCache[key])
- : null,
- });
- });
- moduleResolveCacheChange = [];
- pushParityWriteOps(compilation, moduleResolveOps);
- return moduleResolveCacheSerializer.write(moduleResolveOps);
- },
- );
- }
- }
- module.exports = ModuleResolverCache;
|