-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
近期在维护一个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');
}
});这种方式的缺陷就是业务代码中必须将模块a或b先依赖进来,如果仅仅是node_modules中存在模块,则__webpack_modules__中不会有打包的模块,是一种相对较弱的optional require。
__non_webpack_require__
按照官方文档的说法,实际上会将源码:
__non_webpack_require__('a')生成:
require('a')以交由其他模块加载器处理,也有很大的局限性。
小结
以上是基于不动构建配置的前提下,实现可选依赖打包的实践,请多多指教!
如果不基于这个前提当然也有很多种实现,比如可以自行判断package.json的dependecies再结合externals配置来做、自行实现__webpack_require__的模板等等。
参考链接:
Metadata
Metadata
Assignees
Labels
No labels