【问题标题】:How to access compiler/compilation/module from loader context in Webpack 4如何从 Webpack 4 中的加载器上下文访问编译器/编译/模块
【发布时间】:2019-10-14 14:45:43
【问题描述】:

我正在尝试编写自定义 webpack 加载器。

Webpack 文档提到不推荐访问加载程序上下文中的 _compiler_compilation_module 属性 (https://webpack.js.org/api/loaders/#this_compilation),应该避免。

是否有更新的 API 可以让我访问它们?

【问题讨论】:

    标签: webpack webpack-4


    【解决方案1】:

    对于任何试图弄清楚同样事情的人。我认为没有任何替代 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
    }
    
    

    【讨论】:

      【解决方案2】:

      加载完依赖后,就可以访问生成模块的源码了:

      // 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
      }
      

      【讨论】:

      • 我可能只是太累了,但我认为这不能回答我的问题。我需要访问编译器/编译/模块的实例。模块的代码可以通过加载器参数访问,而无需任何这些。此外,这似乎只是从这个答案 stackoverflow.com/questions/52320135/… 复制而来,这是完全不同的。
      猜你喜欢
      • 2019-01-07
      • 1970-01-01
      • 1970-01-01
      • 2013-07-10
      • 2020-02-23
      • 1970-01-01
      • 2015-07-20
      • 2017-07-16
      • 1970-01-01
      相关资源
      最近更新 更多