Webpack 中的 SourceMap 及优秀实践SourceMap 是为了解决开发代码与实际运行代码不一致时,帮助我们调试到原始开发代码的技术。在浏览器运行编译后的代码时,可以对应到编译前的代码,这对调试非常有帮助。
SourceMap 类型SourceMap 有多种类型,这些类型是通过五个关键字(eval、source-map、cheap、module、inline)的任意组合来定义的。
- eval:使用 eval 包裹模块代码。
- source-map:产生 .map 文件。
- cheap:不包含列信息,也不包含 loader 的 SourceMap。
- module:包含 loader 的 SourceMap(比如 JSX 到 JS,Babel 的 SourceMap),否则无法定义源文件。
- inline:将 .map 作为 DataURI 嵌入,不单独生成 .map 文件。
具体类型如下:
- source-map:原始代码,最好的 SourceMap 质量,有完整的结果,但会很慢。
- eval-source-map:原始代码,最高的质量和最低的性能。
- cheap-module-eval-source-map:原始代码(只有行内),更高的质量和更低的性能。
- cheap-eval-source-map:转换代码(行内),每个模块被 eval 执行,并且 SourceMap 作为 eval 的一个 dataurl,无法看到真正的源码。
- eval:生成代码,每个模块都被 eval 执行,并且存在 @sourceURL,带 eval 的构建模式能 cache SourceMap。
- cheap-source-map:转换代码(行内),生成的 SourceMap 没有列映射,从 loaders 生成的 SourceMap 没有被使用。
- cheap-module-source-map:原始代码(只有行内),与上面一样,除了每行特点的从 loader 中进行映射。
组合规则- source-map:单独在外部生成完整的 SourceMap 文件,并且在目标文件里建立关联,能提示错误代码的准确原始位置。
- inline-source-map:以 base64 格式内联在打包后的文件中,内联构建速度更快,也能提示错误代码的准确原始位置。
- hidden-source-map:会在外部生成 SourceMap 文件,但是在目标文件里没有建立关联,不能提示错误代码的准确原始位置。
- eval-source-map:会为每一个模块生成一个单独的 SourceMap 文件进行内联,并使用 eval 执行。
- nosources-source-map:也会在外部生成 SourceMap 文件,能找到源始代码位置,但源代码内容为空。
- cheap-source-map:外部生成 SourceMap 文件,不包含列和 loader 的 map。
- cheap-module-source-map:外部生成 SourceMap 文件,不包含列的信息但包含 loader 的 map。
最佳实践- 列信息:源代码的列信息是没有意义的,只要有行信息就能完整地建立打包前后代码之间的依赖关系。因此,不管是开发还是生产环境,都会增加 cheap 属性来忽略模块打包后的列信息关联。
- module 属性:不管是生产环境还是开发环境,我们都需要定位 debug 到最原始的资源,比如定位错误到 JSX、TS 的原始代码,而不是经编译后的 JS 代码。所以不可以忽略掉 module 属性。
- source-map 属性:需要生成 .map 文件,所以得有 source-map 属性。
总结:
- 开发环境:使用 cheap-module-eval-source-map。
- 测试环境:使用 cheap-module-eval-source-map。
- 生产环境:使用 cheap-module-source-map 或 hidden-source-map。
开发环境在开发环境对 SourceMap 的要求是:速度快,调试更友好。
- 速度快:推荐 eval-cheap-source-map。
- 调试更友好:cheap-module-source-map。
- 折中选择:eval-source-map。
生产环境在生产环境,首先排除内联,因为一方面要隐藏源代码,另一方面要减少文件体积。
- 调试友好:source-map > cheap-source-map/cheap-module-source-map > hidden-source-map/nosources-source-map。
- 速度快:优先选择 cheap。
- 折中选择:hidden-source-map。
可以使用 source-map-dev-tool-plugin 实现对 SourceMap 生成进行更细粒度的控制。
- filename:定义生成的 SourceMap 的名称(如果没有值将会变成 inlined)。
- append:在原始资源后追加给定值,通常是 #sourceMappingURL 注释。[url] 被替换成 SourceMap 文件的 URL。
市面上流行两种形式的文件指定,分别是以 @ 和 # 符号开头的,@ 开头的已经被废弃。
生产环境调试webpack 打包仍然生成 SourceMap,但是将 map 文件挑出放到本地服务器,将不含有 map 文件的部署到服务器。
通过以上配置和最佳实践,可以更有效地利用 SourceMap 进行开发和调试,提高开发效率和代码质量。