sourcemap的作用
在生产环境和开发环境下,经过webpack打包的代码在运行发生错误时,控制台报出的错误信息让人很难定位。如下:
如果我们引入sourcemap
,在webpack
的配置文件中导出配置添加devtool
如下所示:
webpack.config.js
module.exports = {
mode:'production',
devtool:'source-map', // 添加devtool配置
//..以下配置省略
}
则同样的代码以及同样的抛出错误,控制台报出的信息会更详细。如下:
为什么运行的是已经打包压缩后的代码,然而在输出报错时可以精准定位到开发代码。其中是借助sourcemap
实现的,sourcemap
作用在于映射转换过后的代码与源代码之间的关系。
sourcemap的原理
这里简单说一下sourcemap
的原理,当经过启用了sourcemap
的webpack打包时,会对每个打包压缩后的文件生成对应的map
代码。我们拿jquery1.10.2
的map
代码作例子,其结构如下:
{
"version": 3, // SourceMap的版本,目前为3
"file": "jquery.min.js", // 转换后的文件名称
"sources": ["jquery.js"], // 转换前的文件名称的集合,因为转换后的文件可能是多个文件打包合并的,所以此属性的值是数组类型
"names":[ // 源代码使用的成员名称,压缩代码时会通过把变量名替换成简短的形式以减少体积。故此值用于记录原始对应的名称
"global",
"factory",
...
],
"mappings":";;;CAaA,SAAWA,EAAQC,GAOnB,..." // BASE64-VLQ编码的字符串,记录转换后的代码和源代码之间的映射关系
// "sourcesContent": "", 转换后的代码,jquery的map不存在此项
// "sourceRoot" : "" 转换前的文件所在的目录。如果与转换前的文件在同一目录,该项为空,jquery的map不存在此项
}
拓展: 至于里面的mappings
是怎么映射的,可以看:阮一峰 JavaScript Source Map 详解
不同的sourcemap
会对该map
代码的放置方式不同。
- 以
inline-*
和eval-*
命名的sourcemap会把map
代码内联到对应的打包后的原文件中, - 而其他的会把
map
代码放置到与对应的打包压缩后的原文件同名的以.map
为后缀的新的文件中。
devtool的分类
为什么不直接说sourcemap
的不同模式?因为devtool
中除了可以设置"sourcemap"
模式还可以设置"eval"
模式。这里先介绍"eval"
和"sourcemap"
,后再介绍"sourcemap"
的不同模式。
以下的构建和重构分别指webpack
初次构建和在监视模式下文件变化时的重新构建。
eval
效果: 该模式下,每个模块都使用 eval()
执行,并且都有 //@ sourceURL
。但其错误定位在经过webpack
打包生成的独立模块的代码上。如下:
使用场景: 此模式下,webpack
无论是初次构建还是重新构建的速度都快。主要缺点是,由于会映射到转换后的独立模块代码,而不是映射到源代码(没有从 loader
中获取 sourcemap
),所以不能正确的显示行数。主要在简单的项目中的开发模式下可以使用。
source-map
效果: 每个打包后的生成的文件都会生成一个对应的map
文件作为转换代码和源代码之间的映射。对比于上述的eval
模式,source-map
模式的定位精准度高很多,可以定位到列位置。
使用场景: 虽然精准度高,然而构建速度和重构速度非常的慢,因此用于对错误代码定位要求高的生产环境中。
在如今前端框架普遍使用的时代,用eval
模式定位错误非常鸡肋,然而用source-map
模式时webpack
的构建速度和重构又非常慢。针对此,source-map
模式下又分了好几种模式,以对其构建过程进行一些调整从而达到加快webpack
的构建和重构速度。
我们可以引用webpack
对devtool
的校验规则去了解sourcemap
的分类
inline-*
效果: 该模式下会把生成的map
文件转换为DataUrl
后以//# sourceMappingURL=DataUrl
添加到转换后的文件中中。如下所示:
使用场景: 这种模式下生成的map
文件体积较大,所以一般在开发模式和生产模式都不会被使用。他们是一些特定场景下需要的,例如,针对一些第三方工具。
hidden-*
效果: 该模式下会生成map
文件,但不会为打包后的代码添加引用注释。因此报错时控制台的输出错误效果会和没设置生成sourcemap
的一样。
使用场景: 该模式适用于生产环境,尤其是用于开发第三方包,开发者想生成map
文件而达到映射那些源自错误报告的错误堆栈跟踪信息,但不想在打包代码中引用。
当使用第三方包的开发者想引用map
文件时,可以手动通过注入//# sourceMappingURL=(map文件名称)
把这个包引用回来。目前jquery
就是用这种模式。
eval-*
效果: 该模式下打包生成的每个模块使用eval()
执行,并且map
文件会转换为DataUrl
后添加到eval()
中。如下所示:
使用场景: 第一次构建map
文件时比较慢,但在重新构建时速度较快。eval-cheap-source-map
,eval-cheap-module-source-map
以及eval-source-map
都适用于开发环境。
nosources-*
效果: 该模式下,当抛出错误时,输出的错误栈会详细列出错误来源,但当点击错误栈查看源码时,源码为空或无法加载。
使用场景: 可以在生产环境下使用,在错误抛出时找到错误来源的同时,可以保护源代码不会被暴露。
cheap-*
效果: 使用该模式下,map
文件没有生成列映射(column mapping),只是映射行数。下面可以对一下cheap-source-map
和source-map
使用cheap-source-map
:
使用source-map
:
使用场景: 可以看出使用cheap-*
会让错误信息只定位到行,较source-map
的定位到列会显得稍微不太精准。但其好处就是低开销,构建与重构速度快。无论哪种环境都可以用该模式以准确性为代价提高构建速度。
cheap-module-*
效果: 使用该模式下,错误栈定位的代码是loader加工转换前的,否则,定位的代码是loader加工转换后的。下面详细说明以下:
假设下面是开发时的源代码:
/src/index.js
const fn=()=>{
console.log1('hello')
}
fn()
在webpack.config.js中的module.rules这么设置:
module:{
rules:[
{
test:/\.js$/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env']
}
}
}
]
},
此时 /src/index.js中的箭头函数在打包过程中经过babel-loader
的转换会被替换成普通函数。
现在再对比一下cheap-source-map
和cheap-module-source-map
cheap-source-map:
cheap-module-source-map:
对比得知,cheap-module-source-map定位的是loader转换前的代码,cheap-source-map定位的是loader转换后的代码。其错误定位是到源代码行的,因为cheap-module-* 模式是在cheap-* 模式下进一步调整的。
使用场景: 不分环境,能提高定位的精准度,但会降低初次构建map
文件的速度。
如何选择适合的sourcemap
同上面不同的sourcemap
模式的特性可知,有些适合在开发环境使用,有些适合生产环境使用,有些适合特殊环境下使用。
下面来总结一下不同环境下适用的sourcemap
:
开发模式
以下选项非常适合开发环境:
devtool | 构建速度 | 重构速度 | 定位精准度 | eval-source-map | slowest | ok | 源代码 | eval-cheap-source-map | ok | fast | loader转换后的代码 | eval-cheap-module-source-map | slow | fast | 源代码行 |
---|
生产环境
这些选项通常用于生产环境中:
devtool | 构建速度 | 重构速度 | 定位精准度 | (none) | fastest | fastest | 生成且打包后的代码 | source-map | slowest | slowest | 源代码 | hidden-source-map | slowest | slowest | 源代码 | nosources-source-map | slowest | slowest | 源代码 |
---|
个人认为:一般不允许普通用户访问sourcemap
文件,因此,不能把sourcemap
文件部署到线上(RC)环境。
特殊环境
以下选项对于开发环境和生产环境并不理想。他们是一些特定场景下需要的,例如,针对一些第三方工具。
devtool | 构建速度 | 重构速度 | 定位精准度 | inline-source-map | slowest | slowest | 源代码 | cheap-source-map | ok | slow | loader转换后的代码 | inline-cheap-source-map | ok | slow | loader转换后的代码 | cheap-module-source-map | slow | slow | 源代码行 | inline-cheap-module-source-map | slow | slow | 源代码行 |
---|
其余更详细的sourcemap
请查看webpack devtool:
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!