123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const NormalModule = require("../NormalModule");
- const LazySet = require("../util/LazySet");
- const LoaderDependency = require("./LoaderDependency");
- const LoaderImportDependency = require("./LoaderImportDependency");
- /** @typedef {import("../../declarations/LoaderContext").LoaderPluginLoaderContext} LoaderPluginLoaderContext */
- /** @typedef {import("../Compilation").DepConstructor} DepConstructor */
- /** @typedef {import("../Compilation").ExecuteModuleResult} ExecuteModuleResult */
- /** @typedef {import("../Compiler")} Compiler */
- /** @typedef {import("../Module")} Module */
- /** @typedef {import("../Module").BuildInfo} BuildInfo */
- /**
- * @callback ImportModuleCallback
- * @param {(Error | null)=} err error object
- * @param {any=} exports exports of the evaluated module
- */
- /**
- * @typedef {object} ImportModuleOptions
- * @property {string=} layer the target layer
- * @property {string=} publicPath the target public path
- * @property {string=} baseUri target base uri
- */
- class LoaderPlugin {
- /**
- * @param {object} options options
- */
- constructor(options = {}) {}
- /**
- * Apply the plugin
- * @param {Compiler} compiler the compiler instance
- * @returns {void}
- */
- apply(compiler) {
- compiler.hooks.compilation.tap(
- "LoaderPlugin",
- (compilation, { normalModuleFactory }) => {
- compilation.dependencyFactories.set(
- LoaderDependency,
- normalModuleFactory
- );
- compilation.dependencyFactories.set(
- LoaderImportDependency,
- normalModuleFactory
- );
- }
- );
- compiler.hooks.compilation.tap("LoaderPlugin", compilation => {
- const moduleGraph = compilation.moduleGraph;
- NormalModule.getCompilationHooks(compilation).loader.tap(
- "LoaderPlugin",
- loaderContext => {
- loaderContext.loadModule = (request, callback) => {
- const dep = new LoaderDependency(request);
- dep.loc = {
- name: request
- };
- const factory = compilation.dependencyFactories.get(
- /** @type {DepConstructor} */ (dep.constructor)
- );
- if (factory === undefined) {
- return callback(
- new Error(
- `No module factory available for dependency type: ${dep.constructor.name}`
- )
- );
- }
- const oldFactorizeQueueContext =
- compilation.factorizeQueue.getContext();
- compilation.factorizeQueue.setContext("load-module");
- const oldAddModuleQueueContext =
- compilation.addModuleQueue.getContext();
- compilation.addModuleQueue.setContext("load-module");
- compilation.buildQueue.increaseParallelism();
- compilation.handleModuleCreation(
- {
- factory,
- dependencies: [dep],
- originModule:
- /** @type {NormalModule} */
- (loaderContext._module),
- context: loaderContext.context,
- recursive: false
- },
- err => {
- compilation.factorizeQueue.setContext(oldFactorizeQueueContext);
- compilation.addModuleQueue.setContext(oldAddModuleQueueContext);
- compilation.buildQueue.decreaseParallelism();
- if (err) {
- return callback(err);
- }
- const referencedModule = moduleGraph.getModule(dep);
- if (!referencedModule) {
- return callback(new Error("Cannot load the module"));
- }
- if (referencedModule.getNumberOfErrors() > 0) {
- return callback(
- new Error("The loaded module contains errors")
- );
- }
- const moduleSource = referencedModule.originalSource();
- if (!moduleSource) {
- return callback(
- new Error(
- "The module created for a LoaderDependency must have an original source"
- )
- );
- }
- let map;
- let source;
- if (moduleSource.sourceAndMap) {
- const sourceAndMap = moduleSource.sourceAndMap();
- map = sourceAndMap.map;
- source = sourceAndMap.source;
- } else {
- map = moduleSource.map();
- source = moduleSource.source();
- }
- const fileDependencies = new LazySet();
- const contextDependencies = new LazySet();
- const missingDependencies = new LazySet();
- const buildDependencies = new LazySet();
- referencedModule.addCacheDependencies(
- fileDependencies,
- contextDependencies,
- missingDependencies,
- buildDependencies
- );
- for (const d of fileDependencies) {
- loaderContext.addDependency(d);
- }
- for (const d of contextDependencies) {
- loaderContext.addContextDependency(d);
- }
- for (const d of missingDependencies) {
- loaderContext.addMissingDependency(d);
- }
- for (const d of buildDependencies) {
- loaderContext.addBuildDependency(d);
- }
- return callback(
- null,
- source,
- /** @type {object | null} */ (map),
- referencedModule
- );
- }
- );
- };
- /**
- * @param {string} request the request string to load the module from
- * @param {ImportModuleOptions} options options
- * @param {ImportModuleCallback} callback callback returning the exports
- * @returns {void}
- */
- const importModule = (request, options, callback) => {
- const dep = new LoaderImportDependency(request);
- dep.loc = {
- name: request
- };
- const factory = compilation.dependencyFactories.get(
- /** @type {DepConstructor} */ (dep.constructor)
- );
- if (factory === undefined) {
- return callback(
- new Error(
- `No module factory available for dependency type: ${dep.constructor.name}`
- )
- );
- }
- const oldFactorizeQueueContext =
- compilation.factorizeQueue.getContext();
- compilation.factorizeQueue.setContext("import-module");
- const oldAddModuleQueueContext =
- compilation.addModuleQueue.getContext();
- compilation.addModuleQueue.setContext("import-module");
- compilation.buildQueue.increaseParallelism();
- compilation.handleModuleCreation(
- {
- factory,
- dependencies: [dep],
- originModule:
- /** @type {NormalModule} */
- (loaderContext._module),
- contextInfo: {
- issuerLayer: options.layer
- },
- context: loaderContext.context,
- connectOrigin: false,
- checkCycle: true
- },
- err => {
- compilation.factorizeQueue.setContext(oldFactorizeQueueContext);
- compilation.addModuleQueue.setContext(oldAddModuleQueueContext);
- compilation.buildQueue.decreaseParallelism();
- if (err) {
- return callback(err);
- }
- const referencedModule = moduleGraph.getModule(dep);
- if (!referencedModule) {
- return callback(new Error("Cannot load the module"));
- }
- compilation.buildQueue.increaseParallelism();
- compilation.executeModule(
- referencedModule,
- {
- entryOptions: {
- baseUri: options.baseUri,
- publicPath: options.publicPath
- }
- },
- (err, result) => {
- compilation.buildQueue.decreaseParallelism();
- if (err) return callback(err);
- const {
- fileDependencies,
- contextDependencies,
- missingDependencies,
- buildDependencies,
- cacheable,
- assets,
- exports
- } = /** @type {ExecuteModuleResult} */ (result);
- for (const d of fileDependencies) {
- loaderContext.addDependency(d);
- }
- for (const d of contextDependencies) {
- loaderContext.addContextDependency(d);
- }
- for (const d of missingDependencies) {
- loaderContext.addMissingDependency(d);
- }
- for (const d of buildDependencies) {
- loaderContext.addBuildDependency(d);
- }
- if (cacheable === false) loaderContext.cacheable(false);
- for (const [name, { source, info }] of assets) {
- const buildInfo =
- /** @type {BuildInfo} */
- (
- /** @type {NormalModule} */ (loaderContext._module)
- .buildInfo
- );
- if (!buildInfo.assets) {
- buildInfo.assets = Object.create(null);
- buildInfo.assetsInfo = new Map();
- }
- /** @type {NonNullable<BuildInfo["assets"]>} */
- (buildInfo.assets)[name] = source;
- /** @type {NonNullable<BuildInfo["assetsInfo"]>} */
- (buildInfo.assetsInfo).set(name, info);
- }
- callback(null, exports);
- }
- );
- }
- );
- };
- // eslint-disable-next-line no-warning-comments
- // @ts-ignore Overloading doesn't work
- loaderContext.importModule = (request, options, callback) => {
- if (!callback) {
- return new Promise((resolve, reject) => {
- importModule(request, options || {}, (err, result) => {
- if (err) reject(err);
- else resolve(result);
- });
- });
- }
- return importModule(request, options || {}, callback);
- };
- }
- );
- });
- }
- }
- module.exports = LoaderPlugin;
|