编写自定义webpackparsing器
我打算使用一些更复杂的约定来导入我的webpack项目中的资产。 所以我想写一个插件,应该重写所需的模块定位器的一部分,然后将其传递给parsing器瀑布 。
我们假设我们只是想
- 检查一个请求的模块是否以
#
字符开始 - 如果是这样,用
./lib/
replace。 现在应该由默认的parsing器查找新的模块定位器。
这意味着当一个文件/var/www/source.js
确实require("#example")
/var/www/source.js
require("#example")
,它实际上应该得到/var/www/lib/example.js
。
到目前为止,我已经想通了,我显然应该使用module
事件钩为此目的。 这也是其他答案所select的方式,但不幸的是我没有太多的帮助。
所以这是我的自定义解决插件,这是非常简单的:
function MyResolver () {} MyResolver.prototype.apply = function (compiler) { compiler.plugin('module', function (init, callback) { // Check if rewrite is necessary if (init.request.startsWith('#')) { // Create a new payload const modified = Object.assign({}, init, { request: './lib/' + init.request.slice(1) }) // Continue the waterfall with modified payload callback(null, modified) } else { // Continue the waterfall with original payload callback(null, init) } }) }
但是,使用这个(在resolve.plugins
)不起作用。 运行webpack,我得到以下错误:
ERROR in . Module build failed: Error: EISDIR: illegal operation on a directory, read @ ./source.js 1:0-30
显然,这不是做事情的方式。 但是因为在这个问题上我找不到太多的实例资料,所以我有些不了解。
为了使这更容易重现,我把这个确切的configuration到一个GitHub仓库。 所以如果你对帮助感兴趣,你可以取它:
git clone https://github.com/Loilo/webpack-custom-resolver.git
然后运行npm install
和npm run webpack
来查看错误。
我find了解决scheme,主要是通过阅读文档中的小doResolve()
行触发的。
解决scheme是一个多步骤的过程:
1.运行callback()
不足以继续瀑布。
为了将parsing任务返回到webpack,我需要更换
callback(null, modified)
同
this.doResolve( 'resolve', modified, `Looking up ${modified.request}`, callback )
(2.修复webpack文档)
该文档缺lessdoResolve()
方法的第三个参数( message
),导致使用代码时出现错误,如图所示。 这就是为什么我在把问题放在SO上之前就放弃了doResolve()
方法。
我已经提出了要求,文件应该很快修复。
3.不要使用Object.assign()
似乎原来的请求对象(在问题中命名为init
)不能通过Object.assign()
被复制到parsing器。
显然它包含内部信息,欺骗parsing器查找错误的path。
所以这一行
const modified = Object.assign({}, init, { request: './lib/' + init.request.slice(1) })
需要被这个replace:
const modified = { path: init.path, request: './lib/' + init.request.slice(1), query: init.query, directory: init.directory }
而已。 为了更清楚地看到,下面是从上面的整个MyResolver
插件工作与所提到的修改:
function MyResolver () {} MyResolver.prototype.apply = function (compiler) { compiler.plugin('module', function (init, callback) { // Check if rewrite is necessary if (init.request.startsWith('#')) { // Create a new payload const modified = { path: init.path, request: './lib/' + init.request.slice(1), query: init.query, directory: init.directory } // Continue the waterfall with modified payload this.doResolve( // "resolve" just re-runs the whole resolving of this module, // but this time with our modified request. 'resolve', modified, `Looking up ${modified.request}`, callback ) } else { this.doResolve( // Using "resolve" here would cause an infinite recursion, // use an array of the possibilities instead. [ 'module', 'file', 'directory' ], modified, `Looking up ${init.request}`, callback ) } }) }