编写自定义 webpack 解析器

2024-04-15

我计划使用一组更复杂的约定来将资源导入到我的 webpack 项目中。所以我正在尝试编写一个插件,该插件应该重写请求的模块定位器的部分,然后将其传递给解析器瀑布 https://webpack.js.org/development/how-to-write-a-plugin/#different-plugin-shapes.


假设我们只想

  • 检查请求的模块是否以#性格和
  • 如果是这样,请将其替换为./lib/。现在应该由默认解析器查找新的模块定位器。

这意味着当一个文件/var/www/source.js does require("#example"),然后它实际上应该得到/var/www/lib/example.js.


到目前为止我已经发现我显然应该使用the module事件挂钩 https://webpack.js.org/api/plugins/resolver/#module-request-request-async-waterfall以此目的。这也是选择的方式通过其他答案 https://stackoverflow.com/a/29859165/2048874不幸的是这并没有给我太大帮助。

这是我对自定义解析插件的看法,非常简单:

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

显然,这不是做事的方式。但由于我找不到太多关于这个问题的示例材料,所以我有点没有想法。


为了使重现更容易,我已将此精确配置放入 GitHub 存储库中。因此,如果您有兴趣提供帮助,您可以获取它:

git clone https://github.com/Loilo/webpack-custom-resolver.git

然后运行npm install and npm run webpack查看错误。


Update:请注意,webpack 4 中的插件架构发生了显着变化。下面的代码将不再适用于当前的 webpack 版本。

如果您对 webpack 4 兼容版本感兴趣,请发表评论,我会将其添加到此答案中。

我找到了解决方案,主要是通过读取小doResolve() line 在文档中 https://webpack.js.org/api/plugins/resolver.

该解决方案是一个多步骤过程:

1. 跑步callback()不足以继续瀑布。

为了将解决任务传递回 webpack,我需要替换

callback(null, modified)

with

this.doResolve(
  'resolve',
  modified,
  `Looking up ${modified.request}`,
  callback
)

(2.修复webpack文档)

文档缺少第三个参数(message) 的doResolve()方法,导致使用此处所示的代码时出错。这就是为什么我放弃了doResolve()当我在提出问题之前找到它时的方法。

我已经提出了拉取请求,文档应该很快就会修复。

3.不要使用Object.assign()

看来原来的请求对象(名为init在问题中)不得通过重复Object.assign()传递给解析器。

显然,它包含欺骗解析器查找错误路径的内部信息。

所以这一行

const modified = Object.assign({}, init, {
  request: './lib/' + init.request.slice(1)
})

需要替换为:

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

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编写自定义 webpack 解析器 的相关文章

随机推荐

  • 如何打乱数组? [复制]

    这个问题在这里已经有答案了 我想在 JavaScript 中打乱数组元素 如下所示 0 3 3 gt 3 0 3 9 3 6 0 6 gt 0 3 6 9 6 3 3 6 0 6 gt 0 3 6 3 6 Use Fisher Yates
  • onUpgrade数据库Android版本号不增加

    我正在尝试更新 Android 应用程序中的数据库 当我更新版本号时 会调用onUpgrade 但版本号不会增加 因此每次访问数据库时 都会调用onUpgrade 这是我的代码 private final static int DB VER
  • 如何在 iPhone 上将 NSMutableData 转换为 NSString?

    我从服务器收到 NSMutableData 现在我想将其转换为 NSString 关于如何做到这一点有什么想法吗 您可以使用initWithData 初始化器 NSString alloc initWithData data encodin
  • Python - 类似于 VLOOKUP (Excel) 的函数

    我正在尝试连接两个数据框 但无法理解 Python 提供的可能性 第一个数据框 ID MODEL REQUESTS ORDERS 1 Golf 123 4 2 Passat 34 5 3 Model 3 500 8 4 M3 5 0 第二个
  • 如何使用python分离两条高斯曲线?

    I measured the fluorescence intensity of thousands of particles and made the histogram which showed two adjacent gaussia
  • Google Map API 3 从 API 2 的代码中为标记创建不同的颜色

    我在 API 2 中使用了此代码 但找不到 API 3 的等效代码 我想根据严重性为标记创建不同的颜色 因此它们不是静态值 我有如何创建的问题GICON G DEFAULT ICON GSize 和 addOverlay 如果有人告诉我如何
  • Scala:将 Map 应用于元组列表

    非常简单的问题 我想做这样的事情 var arr1 Array Double var arr2 Array Double var arr3 Array Double Double arr1 zip arr2 arr3 foreach x g
  • 检查(从书签)页面是否已加载?

    我正在写一个书签 javascript 这里的问题是用户可以在某些页面完成加载之前和之后调用它 我想确保脚本仅在页面加载完成后运行 怎么做 检查文档是否已加载的一种方法是检查文档就绪状态 http www w3 org TR html5 d
  • Python C-API 访问字符串常量

    我想使用 python 的 C API 在 C 语言中实现我为 python 编写的库 在 python 中 我可以通过声明以下内容在我的模块中声明 常量 RED red Not really a constant I know BLUE
  • 如何使用 stargazer 或 xtable 省略交互?

    是否可以使用omit选项 通常我会将变量名称写入omit c varname 但在互动的情况下我不知道该写什么 有什么提示吗 在其他包中如何解决这个问题 例如xtable documentclass article begin docume
  • Firebase 更改 Android 中子数据信息的布局

    这是我的 firebase 数据结构 当在我的应用程序中打印出来时 它是这样的 我该如何改变这个 所以它不显示逗号 但改为新行 在 Android 中 我只有一段代码可以从子 成分 中检索所有值 那是因为您已将成分存储在数组中 Fireba
  • 想要在激活 iOS 键盘时调整浏览器视口的大小

    在 iOS 网络浏览器 Safari Chrome 等 中 当您单击输入字段并显示键盘时 它会保持视口大小相同 但将其部分向上滑动到视图之外 这使得创建类似应用程序的网站非常困难 因为我正在编写一个聊天应用程序 当键盘显示时 我希望将对话完
  • SQL Server:如何将固定值绑定到列?

    假设我定义了一个 char 列类型 我想严格限制它的值 例如 黑 白 红 蓝 我怎样才能做到这一点 据我所知 这在 Access 中很容易 P 如果只有几个允许的值 那么您可以使用CHECK约束 http msdn microsoft co
  • 使用 Docker Jenkins 容器管道构建 docker 映像时找不到 Docker

    我有一个 Jenkins 作为 docker 容器运行 现在我想使用管道构建 Docker 映像 但 Jenkins 容器总是告诉 Docker 未找到 simple tdd pipeline Running shell script do
  • 射线聚类算法

    我知道显然有点的聚类算法 但我有不同的场景 我有许多光线 它们的起点都在 3D 球体上 并且其方向矢量向内指向球体 一些光线指向 A 点 其他光线指向 B 点等 并带有一些噪声 即光线彼此不完全相交 是否有一种聚类算法可以让我根据光线指向的
  • 将 ReadonlySpan 转换为 int 的最快方法?

    我有一个带有字符串的文件 40070 我读它并将其转换为ReadonlySpan
  • 如何在 Rails 4 中使用关注点

    默认的 Rails 4 项目生成器现在会在控制器和模型下创建目录 concerns 我找到了一些有关如何使用路由问题的解释 但没有找到有关控制器或模型的解释 我很确定这与社区当前的 DCI 趋势 有关 并且愿意尝试一下 问题是 我应该如何使
  • 在探索 Angular2 之前是否有必要先学习 TypeScript? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 在尝试学习 AngularJS 2 之前是否有必要先学习 TypeScript 没有必要学习 TypeScript 但我绝对建议您学习
  • C# 中防止子进程显示 shell 窗口

    我正在使用 ffmpeg 编译视频 我想防止它在执行操作时显示控制台 这是我启动 ffmpeg 的方法 ProcessStartInfo si new ProcessStartInfo si Arguments string Format
  • 编写自定义 webpack 解析器

    我计划使用一组更复杂的约定来将资源导入到我的 webpack 项目中 所以我正在尝试编写一个插件 该插件应该重写请求的模块定位器的部分 然后将其传递给解析器瀑布 https webpack js org development how to