上一篇 webpack处理模块化源码 的文章中提到了 “source map”,这一篇来详细说说。
source map 用于映射编译后的代码与源码,这样如果编译后的代码出错了,可以很快速的定位到源文件的位置。
我们在 format.js 文件中打印一个不存在的 hello 变量, 当没有 source map 的时候,没有办法看到报错内容在源码的哪个位置。
生产环境提示报错是在编译后的 bundle.js 文件,点击该文件后,只能看到压缩和丑化之后的代码。
开发环境中会告知报错文件路径在 src/utils/format.js 中,点击 bundle.js 文件看到的代码也是经过编译的,和源码仍有些出入。
当设置了 source map 之后,源代码的目录结构、报错内容在哪个源文件、哪一行、列都能够清晰的看到。
这样可以快速的定位问题并进行代码修复。
在配置文件 webpack.config.js 中,mode 字段用于定义模式,默认生产模式 “production”,这里设置为开发模式便于调试,“dev-tool” 用于设置 source map,为了能看到 source map 定位到行与列的区别,增加 babel-loader。
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: "./src/index.js",
mode: "development",
devtool: "inline-source-map",
output: {
filename: "./bundle.js",
path: path.resolve(__dirname, "./dist"),
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
],
},
],
},
};
source map 有26种值可以设置,performance 表示构建速度,production 表示是否建议在"生产环境"使用,建议 source map 仅在开发及测试中使用,因为在生产中暴露源码是非常不安全的。
但这26种 source map 是有规律可循的,弄懂几种类型就可以全部理解。
当 devtool 设置为 source-map 时,webpack 会生成一个 source map 文件,并在打包后的 bundle.js 文件最后添加一行注释,指向 source map 文件。
source map文件中有这些字段用于记录编译后代码与源码的映射关系
以上是生成 source map 文件时的标准版本,除了某些不生成 source map 文件的配置,其它都是以类似这种方式来设置映射关系的。
也有可能存在不需要 source map 文件的情况,有两种方式来配置 devtool,使之不不生成 source map 文件。
这两种方式不会生成 bundle.js.map 文件,也不会在 bundle.js 引入 bundle.js.map 。
除了直接生成 source map 文件,还可以将 source map 内容直接内联到编译后的 bundle.js 中,有三种方式来配置 devtool。
当 devtool 设置为 eval 时,在编译的 bundle.js 文件中,使用 eval 执行文件内容,并通过 //# sourceURL= 指向源文件地址。
此时可以获取到报错的文件、行、列,但看到的代码与源码会有一点不同,增加了 webpack 处理的部分。
当 devtool 设置为 eval-source-map 时,文件内容通过 eval 函数执行,source map 通过base64编码后添加到了eval函数中。
此时通过控制台可以看到具体源代码,报错提醒具体到行与列。
当 devtool 设置为 inline-source-map 时,source map 通过base64编码后添加到了文件最末尾处。
此时通过控制台可以看到具体源代码,报错提醒也具体到行与列。
因为 source map 会占据较大空间,将 source map 内联到 bundle.js 文件中,会使打包后文件体积变大。
以上的报错信息都是精确到"列"的,提示具体哪个字段报错,而精确到"行"的话,只会告知这一行中有错误。
只精确到行,编译速度会稍快一点,有两种方式设置 devtool,这两种文件都会生成 source map 文件,也就是 bunlde.js.map。
为了方便演示,将普通函数改成箭头函数。
可以看到,两者都是精确到"列"的,“cheap-source-map” 定位到的代码和实际的源码有些出入,并且行列顺序也有点不同,但"cheap-module-source-map" 就与源码完全一致。
有没有方法既生成 sourcemap,又不会显示源代码呢?webpack 也提供了两种 devtool 的配置。
没有引入 source map,在报错信息处也就不会指向源码
此时会生成 source map 文件,打包后的 bundle.js 也会引入map文件,也可以看到报错内容所在文件,但无法获取源码。
通过表格总结一下上面所提到的 source map
理解这些 source map 之后,剩余的组合也可以推导出,比如
但以上这些也不能随意的组合,要遵循以下规则
总结起来如下
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
在开发、测试、生产阶段,也有一些推荐
source map 可以帮助我们在开发、测试阶段更好的定位问题,正确的使用能够提升效率。
以上就是关于 source map 的详细介绍,更多有关webpack的内容可以参考我其它的博文,持续更新中~