小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
What
SourceMap,即源代码地图,
前端工程模块化,代码需要进行打包操作,原始源代码经过编译、压缩等的“洗礼”,早就已经“面目全非”
其作用:映射转换后的代码与源代码之间的关系,是一份源码和转换后代码的映射文件
Why
思考:为什么需要SourceMap?
已知:开发时编写的代码,与实际运行的代码是存在差异的
开发后构建运行,此时出现了代码错误(注意:基于构建后的代码进行的)
如果没有SourceMap,根据编译后的代码报错,无法定位到错误位置
故答案:SourceMap利于调试、处理报错
How
原理
SourceMap如何完成原始代码到编译后代码的映射,可详见 # 传送门
Webpack中配置:devtool
此选项控制是否生成,以及如何生成 source map
默认值:string = 'eval'(开发模式) false(生产模式)
根据官网文档梳理,可得下图:
加上source-map,共27种模式
品质
-
打包后的代码:将所有生成的代码视为一大块代码,模块相互不分离
-
生成后代码:每个模块相互分离,并用模块名称进行注释,可看到 webpack 生成的代码
-
转换过的代码:每个模块相互分离,并用模块名称进行注释,可看到 webpack 转换前、loader 转译后的代码
-
原始源代码:每个模块相互分离,并用模块名称进行注释。可看到转译之前(编写时)的代码,取决于 loader 支持。
-
行/行&列:只有行映射/ 行、列映射都有
模式名称
-
inline-*:映射以base64格式编译,而不是创建单独的map文件 -
hidden-*:未添加对SourceMap的引用 -
eval-*:通过eval为每个模块生成SourceMap,建议用于开发 -
nosources-*:映射不包含源代码。适用于需要引用原始文件时 -
cheap-*: 因为只提供行映射,不显示列映射 -
moudule-*: 解析出来的源代码不经过Loader加工,会增加对loader SourceMap的映射注意:不带module的模式,解析出来的源代码是会经过Loader加工后的结果
示例
单看理论雾里看花,挑选部分不同模式名称,上demo:
// src/demo.js
console.log('Source Map');
console.lg('Webpack Devtool');
对应webpack配置:
devtool: 'source-map', // 后续修改
entry: "./src/demo.js",
source-map
打包:会生成map文件
运行
eval-source-map
打包:可见模块均使用 eval() 执行,不生成map文件
运行:同inline-source-map,采用了base64格式编码
cheap-source-map
打包:生成的map文件 略小于 source-map模式
运行:同source-map
inline-source-map
打包:不生成map文件(不以物理文件存在),而是以 base64 格式 编码映射文件,体积最大(base64会导致体积变大)
运行:同source-map
hidden-source-map
打包:会生成map文件
运行:在开发者工具中,虽然生成了map文件,但是看不到SourceMap的效果(即未添加对SourceMap的引用)
nosources-source-map
打包:会生成map文件,仅约600KB
运行:在开发者工具中,无法查看源代码(不暴露源代码)
推荐
简言之,Webpack的SourceMap模式多种多样,需要根据需求灵活选择,官方列举了以下推荐:
开发环境
对于开发环境,通常希望更快速的SourceMap,需要添加到 bundle 中以增加体积为代价
eval-source-map(用于开发环境的最佳品质的SourceMa,利于调试)- eval
- eval-cheap-source-map
- eval-cheap-module-source-map
生产环境
对于生产环境,则希望更精准的SourceMap,需要从 bundle 中分离并独立存在
不设置(不生成 SourceMap,不错的选择)- source-map
- hidden-source-map
- nosources-source-map (保护源代码)
链接传送门
# 如何配置 Webpack SourceMap 的最佳实践
Last but not least
如有不妥,请多指教呀~