本文同步发布在我的 Github 个人博客
前言
前几天在优化项目时,发现next.config.js
的配置里,development 模式下的 sourcemap 为cheap-module-sourcemap
,仔细想了想,记忆中好像有个更推荐常用的开发模式 sourcemap 配置:cheap-module-eval-source-map
。
看了一下是三年前添加的代码,于是又回顾研究了下 webpack 的 sourcemap 配置,开个 PR。
什么是 Sourcemap
我们的项目在打包后,将开发环境中源代码经过压缩,去空格,babel 编译等工程化转换,最终的项目代码和源代码之间差异性很大,会造成无法 debug 的问题,在线上环境定位到的代码是压缩处理后的代码。
而 Sourcemap 就是是为了解决开发代码与实际运行代码不一致时帮助我们 debug 到原始开发代码的技术,解决上述代码定位的问题,是源代码和目标代码出错位置的映射。
Sourcemap 关键词
Sourcemap 的关键词组合眼花缭乱,我们不可能一个一个去记每种 sourcemap 用途,我们只需知道几个关键词的意思,便可推测它们组合的 sourcemap 类型。
eval
每一个模块都执行 eval() 过程,执行后不会生成.map
文件,而是在每一个模块后追加//@ sourceURL
来关联代码处理前后的对应关系。使用 eval 包裹模块代码,可以提高 rebuild 的速度。故一般 sourcemap 带有eval
的选项,rebuild
速度都快一些。
webpackJsonp([1],[
function(module,exports,__webpack_require__){
eval(
...
//# sourceURL=webpack:///./src/js/index.js?'
)
},
function(module,exports,__webpack_require__){
eval(
...
//# sourceURL=webpack:///./src/static/css/app.less?./~/.npminstall/css-loader/0.23.1/css-loader!./~/.npminstall/postcss-loader/1.1.1/postcss-loader!./~/.npminstall/less-loader/2.2.3/less-loader'
)
},
function(module,exports,__webpack_require__){
eval(
...
//# sourceURL=webpack:///./src/tmpl/appTemplate.tpl?"
)
},
...])
为什么 eval 模式 rebuild 的速度会快?
source-map
会为每一个打包后的模块生成独立的.map
文件,会在 bundle 文件末尾追加 sourceURI=指定.map文件路径
,会在浏览器开发者工具中看到webpack://
的文件夹
webpackJsonp([1],[
function(e,t,i){...},
function(e,t,i){...},
function(e,t,i){...},
function(e,t,i){...},
...
])//# sourceMappingURL=index.js.map
打包后的模块在模块后面会对应引用一个.map
文件,同时在打包好的目录下会针对每一个模块生成相应的.map
文件,在上例中会生成一个 index.js.map 文件,这个文件是一个典型的 sourcemap 文件,形式如下:
{
"version":3,
"sources":[
"webpack:///js/index.js","webpack:///./src/js/index.js",
"webpack:///./~/.npminstall/css-loader/0.23.1/css-loader/lib/css-base.js",
...
],
"names":["webpackJsonp","module","exports"...],
"mappings":"AAAAA,cAAc,IAER,SAASC...",
"file":"js/index.js",
"sourcesContent":[...],
"sourceRoot":""
}
cheap
不包含列信息也不包含 loader 的 sourcemap,会为每一个模块生成.map
文件,与source-map
的区别在于 cheap 生成的.map
文件会忽略原始代码中的列信息。
由于生成的 sourcemap 不会有列信息而只有行信息,编译计算量少,所以速度较快。
module
包含 loader 模块之间的 sourcemap(比如 jsx 语法代码经 loader 编译为原生 js 代码),这样可以看到 loader 处理前的原始代码
inline
正常的 sourcemap 的生成是在 dist 目录下创建一个.map
文件, inline 的含义就是不产生独立的 .map
文件,把 sourcemap 的内容以 DataURI 的方式追加到 bundle 件末尾,即将.map
作为 DataURI 嵌入。(一般使用该类型如造成体积过大,该类型比较少用)
webpackJsonp([1],[
function(e,t,i){...},
function(e,t,i){...},
function(e,t,i){...},
function(e,t,i){...},
...
])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9...
DataURL 使用于如下的场景
- 访问外部资源受限
- 图片体积小,占用一个 HTTP 会话资源浪费
hidden
bundle 里不包含 sourcemap 的引用地址,这样浏览器开发者工具里看不到原始代码
Sourcemap 类型
上述的关键词混一起搭配,又增加了好几种 sourcemap 类型
-
eval-source-map:每一个模块在执行 eval()过程之后,并且会为每一个模块生成
.map
文件,生成的 sourcemap 文件通过 DataURL 的方式添加(把 eval 的 sourceURL 换成了完整 sourcemap 信息的 DataURL) -
cheap-eval-source-map:跟 eval-source-map 相同,唯一不同的就是增加了"cheap","cheap"是指忽略了行信息。这个属性同时也不会生成不同 loader 模块之间的 sourcemap。
-
cheap-module-eval-source-map:与 cheap-eval-source-map 相同,但是包含了不同 loader 模块之间的 sourcemap
-
cheap-source-map: 不包含列信息,不包含 loader 的 sourcemap
-
inline-source-map: 为每一个文件添加 sourcemap 的 DataURL,注意这里的文件是打包前的每一个文件而不是最后打包出来的,同时这个 DataURL 是包含一个文件完整 sourcemap 信息的 base64 格式化后的字符串
-hidden-source-map:不在 bundle 文件结尾处追加 sourceURL 指定其 sourcemap 文件的位置,但是仍然会生成 sourcemap 文件。这样,浏览器开发者工具就无法应用 sourcemap, 目的是避免把 sourcemap 文件发布到生产环境,造成源码泄露。
不仅还有这几种,还可以继续组合,这里就列举这么多了
如何选择 Sourcemap
- 首先在源代码的列信息意义不大,因为只要有行信息就能完整的建立打包前后代码之间的依赖关系,够我们定位了。
- 其次,不管在生产环境还是开发环境,我们都需要定位 debug 到最最原始的资源,比如定位错误到 jsx 的原始代码处,而不是编译成 js 的代码处,因此,不能忽略 module 属性。
eval-source-map
使用 DataURL 本身包含完整 sourcemap 信息,并不需要像 sourceURL 那样,浏览器需要发送一个完整请求去获取 sourcemap 文件,这会略微提高点效率
开发环境中使用:cheap-module-eval-source-map(该配置值能保留 loader 处理前的原始代码信息,而打包速度也较快,是一个较佳的选择。)
生产环境中使用 sourcemap 会有泄露源代码的风险,但如果要保留定位线上的错误,应该禁止浏览器开发者工具看到源代码,而是用一些错误收集系统,将 sourcemap 文件传到系统上,通过系统 source map 分析出原始代码的错误堆栈,如使用hidden-source-map
。
当然,也有使用nosources-source-map
, source-map
的,依据你们需求场景选择。总之,最终结果是不能被人通过开发者工具看到源代码的。
结语
我们项目目前还是 Webpack4.x,如果你们项目已经用 Webpack5,sourcemap 名称有些不 同,具体请查阅 Webpack5 文档。
参考
Webpack 中的 sourcemap 以及如何在生产和开发环境中合理的设置 sourcemap 的类型
ps:
- 个人技术博文 Github 仓库
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!