You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
比如通过fetch or ajax获取到可执行的js字符串之后,通过new Function()()来执行可以执行的js字符串,即可达到动态执行字符串的目的,伪代码如下
constcode=awaitfetch('xxxx')newFunction(code)();
注意点:new Function()的作用域是全局作用域,不存在当前作用域的情况;所以推荐使用new Function来替换eval的原因就是,eval如果是直接调用的场景,那么js引擎在执行eval内代码的时候需要判断变量是当前最用域内的变量还是全局变量,所以相对new Function 只有全局作用域会慢;
目录
动态执行js字符串方式
动态执行js字符串的能力,有利于我们去做一些热更新,劫持子应用js并渲染子应用js等,常用的动态执行js字符串有三种方式
内联script
比如通过fetch or ajax获取到可执行的js字符串之后,通过创建一个script标签,然后将内容设置到script标签,最后在append到dom中,即可达到动态执行字符串的目的,伪代码如下所示
注意这种执行方式,js的作用域是全局作用域
eval
比如通过fetch or ajax获取到可执行的js字符串之后,通过eval来执行可以执行的js字符串,即可达到动态执行字符串的目的,伪代码如下
注意点: eval执行的作用域为当前作用域,而间接执行的eval作用域为全局作用域
所以我们需要根据场景来决定怎么使用eval
new Function
比如通过fetch or ajax获取到可执行的js字符串之后,通过new Function()()来执行可以执行的js字符串,即可达到动态执行字符串的目的,伪代码如下
注意点:new Function()的作用域是全局作用域,不存在当前作用域的情况;所以推荐使用new Function来替换eval的原因就是,eval如果是直接调用的场景,那么js引擎在执行eval内代码的时候需要判断变量是当前最用域内的变量还是全局变量,所以相对new Function 只有全局作用域会慢;
soure map
为什么需要source map?
便于调试压缩后的代码及还原压缩后代码真实的源码报错信息
source map会不会影响性能?
不会,只有开启了浏览器的devtool的时候浏览器才会去根据js文件内是否有souceMapUrl的标识去加载对应的source map文件
source map有没有标准?
有,目前的版本是3,标准包含了source map应该包含的信息,及怎么去设置source map,具体内容请查看sourcemaps spec
webpack为什么有那么多种source-map格式?
因为webpack基于安全、大小(性能)生成了不同方式的source map,但是本质上包含的内容都是标准规定的内容,只是做了部分增减
webpack source map
webpack生成的source map虽然有很多类型,但是归根结底就是几个场景的组合,具体场景如下所示
具体组合规则如下所示
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
下面以如下源码为例
source-map
eval
相对于source-map,eval 不生成source-map,仅添加sourceURL,用于提示错误文件来源
inline-source-map
相对于source-map、inline-source-map将单独的source map文件,通过base64的方式添加到源文件内
nosources-source-map
相对于source-map、nosources-source-map生成的map文件缺少了源代码,只能用于定位错误的文件及行列号,无法查看源码信息
hidden-source-map
相对于source-map、hidden-source-map不在源码中添加顶级注释//# sourceMappingURL
cheap-source-map
source-map 完整的行列信息,点击错误信息的时候光标会直接定位到错误行列
cheap-source-map 完整的行信息,点击错误信息的时候光标会直接定位到错误行
cheap-source-map 相对于source-map少了列信息,少了loader转化的source-map,也就是定位的文件是loader转化后的代码,而不是源文件
cheap-module-source-map
cheap-module-source-map 相对于source-map少了列信息,定位的文件是源文件
注意点
webpack mode production 开启压缩的场景下,devtoo仅支持source-map,inline-source-map,hidden-source-map 和 nosources-source-map,其它模式不会按照预期生成source map,具体可以查看note-about-source-maps
总结
其实webpack的source map的生成,主要围绕的是安全、大小(也就是速度)两个维度来生成不同种类的source map
首先是最完整的source-map
然后从安全角度看
从大小(速度)角度看
所以只要理解了source map这么多种类的目的,那么我们就可以结合实际场景做出最适合当前项目的source map
内联script、eval、new Function错误定位
在微前端或者一些动态执行脚本的场景需要先fetch js代码,然后在通过内联script or eval or new Function的方式来执行js,这时候怎么去快速定位错误及记录错误来源是很重要与关键的能力,那么分别看下这三种场景下的错误应该怎么处理才是最佳
在看内联script、eval、new Function三种执行js代码报错之前,我们先看下通过script src脚本执行报错,有source map与无source map的场景是怎么样的
script src
无source map
可以看出js出错的文件名,不能直接映射到源文件
有source map
可以看出js出错的源文件名,能直接映射到源文件
内联script
无source map
内联脚本名是anonymous, 不能够看出是哪个js文件的报错,不能映射到原文件
有source map
内联脚本名是anonymous,能看到报错源文件名, 能映射到原文件,但是在微前端场景,不能够知道报错的这段js来自于哪个子应用
有sourceURL
内联脚本名是anonymous,能看到报错源文件名, 不能映射到源文件,但是在微前端场景,能够知道报错的这段js来自于哪个子应用
eval
无source map
会看到代码是eval执行, 不能够看出是哪个js文件的报错,不能映射到源文件
有source map
会看到代码是通过eval执行, 能够看出是哪个js文件的报错,能映射到源文件,但是在微前端场景,不能够知道报错的这段js来自于哪个子应用
有source url
会看到代码是通过eval执行, 能够看出是哪个js文件的报错,不能映射到源文件,但是在微前端场景,能够知道报错的这段js来自于哪个子应用
new Function
无source map
会看到代码是eval执行, 不能够看出是哪个js文件的报错,不能映射到源文件
有source map
会看到代码是通过eval执行, 不能够看出是哪个js文件的报错,不能映射到源文件
有source url
会看到代码是通过eval执行, 能够看出是哪个js文件的报错,不能映射到源文件,但是在微前端场景,能够知道报错的这段js来自于哪个子应用
错误监听
在微前端的场景下,比如micrpApp是通过new Function or 内联script来执行子应用js代码,那么怎么区分错误来源是哪个子应用,有两种三种思路
最终选择添加sourceURL方式,原因是Object.defineProperty + Proxy的方式改写Error类,只能影响到代码内主动throw 的Error,对于语法错误等js引擎执行过程中抛出的错误是影响不到的;而使用try catch的方式改动量更大,且更容易出bug下,相对来说选择sourceURL方式成本更低,改动更小
无sourceURL
addEventlisten error no sourceURL
filename来自url,不知道错误来源于哪个js文件,及哪个子应用
有sourceURL
addEventlisten error sourceURL
filename来自原本的js文件,准备知道错误来源于哪个js文件,及哪个子应用
总结
在微前端场景,通过添加sourceURL可以区分错误来源是哪个子应用,通过添加sourceMappingURL便于排查错误
参考链接
eval
note-about-source-maps
chrome-development-tool-vm-file-from-javascript
Support //# sourceURL= and //# sourceMappingURL= in v8's parser
Introduction to JavaScript Source Maps
Source Map Revision 3 Proposal
Source map for a dynamically created function
Bug: Source maps don't work with hot reload
Webpack devtool source map
Source Maps
The text was updated successfully, but these errors were encountered: