2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
8 const NormalModule = require("../NormalModule");
9 const LazySet = require("../util/LazySet");
10 const LoaderDependency = require("./LoaderDependency");
11 const LoaderImportDependency = require("./LoaderImportDependency");
13 /** @typedef {import("../Compilation").DepConstructor} DepConstructor */
14 /** @typedef {import("../Compiler")} Compiler */
15 /** @typedef {import("../Module")} Module */
18 * @callback LoadModuleCallback
19 * @param {(Error | null)=} err error object
20 * @param {string | Buffer=} source source code
21 * @param {object=} map source map
22 * @param {Module=} module loaded module if successful
26 * @callback ImportModuleCallback
27 * @param {(Error | null)=} err error object
28 * @param {any=} exports exports of the evaluated module
32 * @typedef {Object} ImportModuleOptions
33 * @property {string=} layer the target layer
34 * @property {string=} publicPath the target public path
35 * @property {string=} baseUri target base uri
40 * @param {Object} options options
42 constructor(options = {}) {}
46 * @param {Compiler} compiler the compiler instance
50 compiler.hooks.compilation.tap(
52 (compilation, { normalModuleFactory }) => {
53 compilation.dependencyFactories.set(
57 compilation.dependencyFactories.set(
58 LoaderImportDependency,
64 compiler.hooks.compilation.tap("LoaderPlugin", compilation => {
65 const moduleGraph = compilation.moduleGraph;
66 NormalModule.getCompilationHooks(compilation).loader.tap(
70 * @param {string} request the request string to load the module from
71 * @param {LoadModuleCallback} callback callback returning the loaded module or error
74 loaderContext.loadModule = (request, callback) => {
75 const dep = new LoaderDependency(request);
79 const factory = compilation.dependencyFactories.get(
80 /** @type {DepConstructor} */ (dep.constructor)
82 if (factory === undefined) {
85 `No module factory available for dependency type: ${dep.constructor.name}`
89 compilation.buildQueue.increaseParallelism();
90 compilation.handleModuleCreation(
94 originModule: loaderContext._module,
95 context: loaderContext.context,
99 compilation.buildQueue.decreaseParallelism();
101 return callback(err);
103 const referencedModule = moduleGraph.getModule(dep);
104 if (!referencedModule) {
105 return callback(new Error("Cannot load the module"));
107 if (referencedModule.getNumberOfErrors() > 0) {
109 new Error("The loaded module contains errors")
112 const moduleSource = referencedModule.originalSource();
116 "The module created for a LoaderDependency must have an original source"
121 if (moduleSource.sourceAndMap) {
122 const sourceAndMap = moduleSource.sourceAndMap();
123 map = sourceAndMap.map;
124 source = sourceAndMap.source;
126 map = moduleSource.map();
127 source = moduleSource.source();
129 const fileDependencies = new LazySet();
130 const contextDependencies = new LazySet();
131 const missingDependencies = new LazySet();
132 const buildDependencies = new LazySet();
133 referencedModule.addCacheDependencies(
140 for (const d of fileDependencies) {
141 loaderContext.addDependency(d);
143 for (const d of contextDependencies) {
144 loaderContext.addContextDependency(d);
146 for (const d of missingDependencies) {
147 loaderContext.addMissingDependency(d);
149 for (const d of buildDependencies) {
150 loaderContext.addBuildDependency(d);
152 return callback(null, source, map, referencedModule);
158 * @param {string} request the request string to load the module from
159 * @param {ImportModuleOptions=} options options
160 * @param {ImportModuleCallback=} callback callback returning the exports
163 const importModule = (request, options, callback) => {
164 const dep = new LoaderImportDependency(request);
168 const factory = compilation.dependencyFactories.get(
169 /** @type {DepConstructor} */ (dep.constructor)
171 if (factory === undefined) {
174 `No module factory available for dependency type: ${dep.constructor.name}`
178 compilation.buildQueue.increaseParallelism();
179 compilation.handleModuleCreation(
183 originModule: loaderContext._module,
185 issuerLayer: options.layer
187 context: loaderContext.context,
191 compilation.buildQueue.decreaseParallelism();
193 return callback(err);
195 const referencedModule = moduleGraph.getModule(dep);
196 if (!referencedModule) {
197 return callback(new Error("Cannot load the module"));
199 compilation.executeModule(
203 baseUri: options.baseUri,
204 publicPath: options.publicPath
208 if (err) return callback(err);
209 for (const d of result.fileDependencies) {
210 loaderContext.addDependency(d);
212 for (const d of result.contextDependencies) {
213 loaderContext.addContextDependency(d);
215 for (const d of result.missingDependencies) {
216 loaderContext.addMissingDependency(d);
218 for (const d of result.buildDependencies) {
219 loaderContext.addBuildDependency(d);
221 if (result.cacheable === false)
222 loaderContext.cacheable(false);
223 for (const [name, { source, info }] of result.assets) {
224 const { buildInfo } = loaderContext._module;
225 if (!buildInfo.assets) {
226 buildInfo.assets = Object.create(null);
227 buildInfo.assetsInfo = new Map();
229 buildInfo.assets[name] = source;
230 buildInfo.assetsInfo.set(name, info);
232 callback(null, result.exports);
240 * @param {string} request the request string to load the module from
241 * @param {ImportModuleOptions} options options
242 * @param {ImportModuleCallback=} callback callback returning the exports
243 * @returns {Promise<any> | void} exports
245 loaderContext.importModule = (request, options, callback) => {
247 return new Promise((resolve, reject) => {
248 importModule(request, options || {}, (err, result) => {
249 if (err) reject(err);
250 else resolve(result);
254 return importModule(request, options || {}, callback);
261 module.exports = LoaderPlugin;