背景:给一个巨石单体项目进行标准化模块拆分,封装出来的模块代码用 vite
进行构建,但模块启动后页面上的表现一直和 webpack
那版不一致
一步步 debug
后,发现问题出在下面这个判断条件
js
const GeneratorFunction = function* () {}.constructor;
function(func){
if (func instanceof GeneratorFunction){
// do something
} else {
// do something
}
}
问:当 func
是生成器函数时,判断条件输出 true
还是 false
答案:
vite:false
webpack:true
为什么
条件判断的本质是在判断 func.__proto__ 和 GeneratorFunction.prototype 两个值引用是否一致
在 vite
和 webpack
下输出看看:
js
console.log(func.__proto__) ==> ƒ GeneratorFunctionPrototype() { }
console.log(GeneratorFunction.prototype) ==> ƒ GeneratorFunctionPrototype() { }
两个值看起来一样,但进行引用比较
js
func.__proto__ === GeneratorFunction.prototype
会发现在 vite
输出 false
,在 webpack
输出 true
谁对谁错?
当我在控制台搜索 GeneratorFunctionPrototype
发现 vite
编译后的产物里但凡使用了生成器函数,这个模块里都会重复声明一次 GeneratorFunctionPrototype
而 webpack
的编译产物里只有这一个来源,所以引用是一致的
GeneratorFunctionPrototype
应该是全局标准的唯一引用,因此 webpack
的表现是正确的
怎么解决
很遗憾,在 vite
里现阶段还无法通过有效手段编译出唯一 GeneratorFunctionPrototype
(如果你有方法请留言评论哦,蟹蟹)
我只能把判断条件换一种写法:
js
function(func){
if (saga.constructor.name.startsWith('GeneratorFunction')){
// do something
} else {
// do something
}
}
注:vite dev
和 prod
都会出现这个问题