const fs = require('graceful-fs');
|
const path = require('path');
|
|
const cachePrefix = require('./util').cachePrefix;
|
const pluginCompat = require('./util/plugin-compat');
|
const relateContext = require('./util/relate-context');
|
|
let NS;
|
|
NS = path.dirname(fs.realpathSync(__dirname));
|
|
class NormalModuleFactoryPlugin {
|
apply(compiler) {
|
const compilerHooks = pluginCompat.hooks(compiler);
|
|
let fetch;
|
|
compilerHooks._hardSourceMethods.tap(
|
'HardSource - TransformNormalModuleFactoryPlugin',
|
methods => {
|
fetch = methods.fetch;
|
},
|
);
|
|
compilerHooks.compilation.tap(
|
'HardSource - TransformNormalModuleFactoryPlugin',
|
(compilation, { normalModuleFactory, contextModuleFactory }) => {
|
// if (!active) {return;}
|
|
// compilation.fileTimestamps = fileTimestamps;
|
// compilation.contextTimestamps = contextTimestamps;
|
|
// compilation.__hardSourceFileMd5s = fileMd5s;
|
// compilation.__hardSourceCachedMd5s = cachedMd5s;
|
|
const compilationHooks = pluginCompat.hooks(compilation);
|
compilationHooks.buildModule.tap(
|
'HardSource - TransformNormalModuleFactoryPlugin',
|
module => {
|
if (module.constructor.name === 'NormalModule') {
|
module.__originalCreateLoaderContext =
|
module.__originalCreateLoaderContext ||
|
module.createLoaderContext;
|
module.__hardSource_resolved = {};
|
module.createLoaderContext = (...args) => {
|
const loaderContext = module.__originalCreateLoaderContext(
|
...args,
|
);
|
const _resolve = loaderContext.resolve;
|
loaderContext.resolve = (context, request, callback) => {
|
_resolve.call(
|
loaderContext,
|
context,
|
request,
|
(err, result) => {
|
if (err) {
|
callback(err, result);
|
} else {
|
module.__hardSource_resolved[
|
JSON.stringify({ context, request })
|
] = {
|
resource: result,
|
resolveOptions: module.resolveOptions,
|
};
|
callback(err, result);
|
}
|
},
|
);
|
};
|
return loaderContext;
|
};
|
}
|
},
|
);
|
|
const normalModuleFactoryHooks = pluginCompat.hooks(
|
normalModuleFactory,
|
);
|
|
// Webpack 2 can use different parsers based on config rule sets.
|
normalModuleFactoryHooks.parser
|
.for('javascript/auto')
|
.tap(
|
'HardSource - TransformNormalModuleFactoryPlugin',
|
(parser, options) => {
|
// Store the options somewhere that can not conflict with another plugin
|
// on the parser so we can look it up and store those options with a
|
// cached module resolution.
|
parser[`${NS}/parser-options`] = options;
|
},
|
);
|
|
normalModuleFactoryHooks.resolver.tap(
|
'HardSource - TransformNormalModuleFactoryPlugin',
|
fn => (request, cb) => {
|
const identifierPrefix = cachePrefix(compilation);
|
if (identifierPrefix === null) {
|
return fn.call(null, request, cb);
|
}
|
|
const cacheId = JSON.stringify([
|
identifierPrefix,
|
request.context,
|
request.request,
|
]);
|
const absCacheId = JSON.stringify([
|
identifierPrefix,
|
request.context,
|
relateContext.relateAbsoluteRequest(
|
request.context,
|
request.request,
|
),
|
]);
|
|
request.contextInfo.resolveOptions = request.resolveOptions;
|
|
const next = () => {
|
const originalRequest = request;
|
return fn.call(null, request, function(err, request) {
|
if (err) {
|
return cb(err);
|
}
|
if (!request.source) {
|
compilation.__hardSourceModuleResolveCacheChange.push(
|
cacheId,
|
);
|
compilation.__hardSourceModuleResolveCache[
|
cacheId
|
] = Object.assign({}, request, {
|
parser: null,
|
generator: null,
|
parserOptions: request.parser[`${NS}/parser-options`],
|
type: request.settings && request.settings.type,
|
settings: request.settings,
|
resourceResolveData: request.resourceResolveData,
|
dependencies: null,
|
});
|
}
|
cb(...arguments);
|
});
|
};
|
|
const fromCache = () => {
|
const result = Object.assign(
|
{},
|
compilation.__hardSourceModuleResolveCache[cacheId] ||
|
compilation.__hardSourceModuleResolveCache[absCacheId],
|
);
|
result.dependencies = request.dependencies;
|
|
if (!result.parser || !result.parser.parse) {
|
result.parser = result.settings
|
? normalModuleFactory.getParser(
|
result.type,
|
result.settings.parser,
|
)
|
: normalModuleFactory.getParser(result.parserOptions);
|
}
|
if (!result.generator && normalModuleFactory.getGenerator) {
|
result.generator = normalModuleFactory.getGenerator(
|
result.type,
|
result.settings.generator,
|
);
|
}
|
|
result.loaders = result.loaders.map(loader => {
|
if (typeof loader === 'object' && loader.ident) {
|
const ruleSet = normalModuleFactory.ruleSet;
|
return {
|
loader: loader.loader,
|
ident: loader.ident,
|
options: ruleSet.references[loader.ident],
|
};
|
}
|
return loader;
|
});
|
|
return cb(null, result);
|
};
|
|
if (
|
(compilation.__hardSourceModuleResolveCache[cacheId] &&
|
!compilation.__hardSourceModuleResolveCache[cacheId].invalid) ||
|
(compilation.__hardSourceModuleResolveCache[absCacheId] &&
|
!compilation.__hardSourceModuleResolveCache[absCacheId].invalid)
|
) {
|
return fromCache();
|
}
|
|
next();
|
},
|
);
|
|
normalModuleFactoryHooks.createModule.tap(
|
'HardSourceWebpackPlugin',
|
({ request }) => {
|
if (
|
compilation.cache &&
|
compilation.cache[`m${request}`] &&
|
compilation.cache[`m${request}`].cacheItem &&
|
!compilation.cache[`m${request}`].cacheItem.invalid
|
) {
|
return compilation.cache[`m${request}`];
|
}
|
|
const identifierPrefix = cachePrefix(compilation);
|
if (identifierPrefix === null) {
|
return;
|
}
|
|
const identifier = identifierPrefix + request;
|
|
const module = fetch('Module', identifier, {
|
compilation,
|
normalModuleFactory: normalModuleFactory,
|
contextModuleFactory: contextModuleFactory,
|
});
|
|
if (module) {
|
return module;
|
}
|
},
|
);
|
},
|
);
|
}
|
}
|
|
module.exports = NormalModuleFactoryPlugin;
|