Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webpack——可选依赖打包实践 #7

Open
HexMox opened this issue Jun 8, 2020 · 0 comments
Open

webpack——可选依赖打包实践 #7

HexMox opened this issue Jun 8, 2020 · 0 comments

Comments

@HexMox
Copy link
Owner

HexMox commented Jun 8, 2020

近期在维护一个Web侧的SDK,遇到一个可选依赖打包的场景颇为头疼,仅在此记录下探索过程。

前言

在Node中,我们常常会包一层try catch写出这样的代码来实现降级逻辑:

try {
  const a = require('a');
} catch(e) {
  // 模块a不存在的降级逻辑
}

但在前端存在webpack打包的场景中,也有几种方案可以实现类似效果

try-catch

将Node的代码原封不动的使用webpack打包也是可以实现这个效果的。不过会出现Warnings:

WARNING in ./src/pages/xxx/index.js
Module not found: Error: Can't resolve 'a' in '/workspace/projects/xx/src/pages/xxx'
 @ ./src/pages/xxx/index.js

当然如果你不包裹一层try-catch就会导致构建失败了,这一层try-catch的语义分析,webpack做到了什么程度呢?

假如现在有源码

[
  () => require('a'), 
  () => require('b')
].some(fn => {
  try {
    this.reportor = fn();
    return true;
  } catch (e) {}
});

那么webpack的语义分析就没用了...
如果需要尝试依赖超过3次的降级包,那为了避免嵌套地狱,try-catch包裹就只能这么写了:

function tryGet(x = 0) {
  try {
    switch(x) {
    case 0:
      return require('a');
    case 1:
      return require('b');
    case 2:
      return require('c');
    }
  } catch(e) {
    return x >= 2 ? null : tryGet(x + 1);
  }
}

require.resolveWeak

webpack提供了require.resolveWeak的API来实现弱依赖打包。

[
  // 兼容webpack,需要业务先行引入上报库
  () => __webpack_modules__[require.resolveWeak('a')],
  () => __webpack_modules__[require.resolveWeak('b')],
  // 兼容fis3
  () => jsRequire('a'),
  () => jsRequire('b'),
].some((fn, i) => {
  try {
    this.x = fn();
    return !!this.x;
  } catch (e) {
    console.warn('xxx');
  }
});

这种方式的缺陷就是业务代码中必须将模块ab先依赖进来,如果仅仅是node_modules中存在模块,则__webpack_modules__中不会有打包的模块,是一种相对较弱的optional require。

__non_webpack_require__

按照官方文档的说法,实际上会将源码:

__non_webpack_require__('a')

生成:

require('a')

以交由其他模块加载器处理,也有很大的局限性。

小结

以上是基于不动构建配置的前提下,实现可选依赖打包的实践,请多多指教!

如果不基于这个前提当然也有很多种实现,比如可以自行判断package.json的dependecies再结合externals配置来做、自行实现__webpack_require__的模板等等。

参考链接:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant