分类
前端工具链

使用 webpack-rpc-inline-plugin 打包内联函数体

使用 Puppeteer 的时候,我们常常要使用 page.evaluate() 或者 page.evaluateHandle() 函数到目标页面的环境里执行一段代码。

如果是简单的代码,比如返回页面标题、改变某个节点的属性,那么直接写在 .evaluate() 里面就行了;但实际生产中,尤其是前厂的 Showman 产品里,要执行的函数往往非常复杂,经常需要组合多个函数:

page.evaluate(() => {
  function func1() {}
  function func2() {}
  // ...
  function funcN() {}

  func1();
  func2();
  // ...
  funcN();
});

这种场景下,我们必须用上面这种写法,而不是下面这种我们更熟悉的写法:

import func1 from './func1';
import func2 from './func2';
// ...
import funcN from './funcN';

page.evaluate(() => {
  func1();
  func2();
  // ...
  funcN();
});

因为被执行的函数会被转换成字符串,传输到目标环境,然后重新实例化成函数,再执行。所以上面这种写法,引擎会在全局环境下查找需要的函数,而那些函数都没传递过去,就会找不到。

如果开发时按照方案一组织代码,会遇到几个问题:

  1. 子函数放在主函数体内部,不方便独立开发、调试、测试
  2. 每个主函数内部都需要写死子函数,不方便共享复用

所以我就想从工具链入手,写一个专用工具,可以继续用方案二的形式组织代码,但是编译打包之后,就恢复到方案一的状态。

我选择了 webpack 插件,原因有二:

  1. 我比较熟悉 webpack
  2. 这种情况不能用 loader

最后我选择在 compilation.afterProcessAssets 钩子处理 JS。此时 JS 已经打包了所有资源,并且经过 terser 压缩。所以我会先将 bundle 解开(直接用 string.substring),然后 return webpack 对象,从中找到目标函数替换。

具体的代码在 GitHub 仓库里,我就不详细解释了(困了),感兴趣的同学可以看看。

欢迎需要在 rpc 环境下执行 JS 的同学使用,欢迎反馈需求和问题。

meathill

爱编程,爱旅游,爱吐槽。
今年的目标是完成并运营至少一个 Side Project。
《Electron + Vue 实战开发》龟速创作中……

欢迎吐槽,共同进步

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据