如何从 Webpack 4 中的加载器上下文访问 compiler/compilation/module
How to access compiler/compilation/module from loader context in Webpack 4
我正在尝试编写自定义 webpack 加载器。
Webpack 文档提到对加载程序上下文中的 _compiler
、_compilation
和 _module
属性的访问已被弃用 (https://webpack.js.org/api/loaders/#this_compilation),应该避免。
是否有更新的 API 允许我访问它们?
加载依赖项后,您可以访问生成的模块的源代码:
// Index the modules generated in the child compiler by raw request.
let byRawRequest = new Map
for (let asset of compilation.modules)
byRawRequest.set(asset.rawRequest, asset)
// Replace the template requests with the result from modules generated in
// the child compiler.
for (let {node, request} of this._getAssetRequests()) {
if (!byRawRequest.has(request))
continue
const ASSET = byRawRequest.get(request)
const SOURCE = ASSET.originalSource().source()
const NEW_REQUEST = execAssetModule(SOURCE)
setResourceRequest(node, NEW_REQUEST)
log(`Changed: ${prettyFormat({from: request, to: NEW_REQUEST})}`)
}
And execute the module's source with a VM:
function execAssetModule(code, path) {
let script = new Script(code)
let exports = {}
let sandbox = {
__webpack_public_path__: '',
module: {exports},
exports,
}
script.runInNewContext(sandbox)
return sandbox.module.exports
}
对于任何想弄清楚同样事情的人。我不认为有任何替代品 API。这个想法可能是加载程序不应该真正需要访问这些对象,如果你确实需要它们,你应该使用插件代替(或另外)。
如果将来属性会被删除,您可以通过以下方式使用插件“将它们添加回来”:
// custom-plugin.js
const NormalModule = require('webpack/lib/NormalModule')
class CustomPlugin {
apply (compiler) {
compiler.hooks.compilation.tap('CustomPlugin', (compilation) => {
NormalModule.getCompilationHooks(compilation).loader.tap('CustomPlugin', (loader, module) => {
loader._customPlugin = {
module: module,
compiler: compiler,
compilation: compilation,
}
})
});
}
}
module.exports = CustomPlugin
// custom-loader.js
module.exports = function (source) {
console.log({
module: this._customPlugin.module === this._module, // true
compiler: this._customPlugin.compiler === this._compiler, // true
compilation: this._customPlugin.compilation === this._compilation, // true
});
return source
}
我正在尝试编写自定义 webpack 加载器。
Webpack 文档提到对加载程序上下文中的 _compiler
、_compilation
和 _module
属性的访问已被弃用 (https://webpack.js.org/api/loaders/#this_compilation),应该避免。
是否有更新的 API 允许我访问它们?
加载依赖项后,您可以访问生成的模块的源代码:
// Index the modules generated in the child compiler by raw request.
let byRawRequest = new Map
for (let asset of compilation.modules)
byRawRequest.set(asset.rawRequest, asset)
// Replace the template requests with the result from modules generated in
// the child compiler.
for (let {node, request} of this._getAssetRequests()) {
if (!byRawRequest.has(request))
continue
const ASSET = byRawRequest.get(request)
const SOURCE = ASSET.originalSource().source()
const NEW_REQUEST = execAssetModule(SOURCE)
setResourceRequest(node, NEW_REQUEST)
log(`Changed: ${prettyFormat({from: request, to: NEW_REQUEST})}`)
}
And execute the module's source with a VM:
function execAssetModule(code, path) {
let script = new Script(code)
let exports = {}
let sandbox = {
__webpack_public_path__: '',
module: {exports},
exports,
}
script.runInNewContext(sandbox)
return sandbox.module.exports
}
对于任何想弄清楚同样事情的人。我不认为有任何替代品 API。这个想法可能是加载程序不应该真正需要访问这些对象,如果你确实需要它们,你应该使用插件代替(或另外)。
如果将来属性会被删除,您可以通过以下方式使用插件“将它们添加回来”:
// custom-plugin.js
const NormalModule = require('webpack/lib/NormalModule')
class CustomPlugin {
apply (compiler) {
compiler.hooks.compilation.tap('CustomPlugin', (compilation) => {
NormalModule.getCompilationHooks(compilation).loader.tap('CustomPlugin', (loader, module) => {
loader._customPlugin = {
module: module,
compiler: compiler,
compilation: compilation,
}
})
});
}
}
module.exports = CustomPlugin
// custom-loader.js
module.exports = function (source) {
console.log({
module: this._customPlugin.module === this._module, // true
compiler: this._customPlugin.compiler === this._compiler, // true
compilation: this._customPlugin.compilation === this._compilation, // true
});
return source
}