美文网首页
26种source-map看花了眼?别急,理解这几个全弄懂

26种source-map看花了眼?别急,理解这几个全弄懂

作者: 一颗冰淇淋 | 来源:发表于2022-05-04 21:10 被阅读0次

    上一篇 webpack处理模块化源码 的文章中提到了 "source map",这一篇来详细说说。

    有什么作用

    source map 用于映射编译后的代码与源码,这样如果编译后的代码出错了,可以很快速的定位到源文件的位置。

    我们在 format.js 文件中打印一个不存在的 hello 变量, 当没有 source map 的时候,没有办法看到报错内容在源码的哪个位置。

    生产环境提示报错是在编译后的 bundle.js 文件,点击该文件后,只能看到压缩和丑化之后的代码。

    1_生产环境没有source-map.png

    开发环境中会告知报错文件路径在 src/utils/format.js 中,点击 bundle.js 文件看到的代码也是经过编译的,和源码仍有些出入。

    2_开发环境没有source-map.png

    当设置了 source map 之后,源代码的目录结构、报错内容在哪个源文件、哪一行、列都能够清晰的看到。

    3_devtool为source-map.png

    这样可以快速的定位问题并进行代码修复。

    如何使用

    在配置文件 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 仅在开发及测试中使用,因为在生产中暴露源码是非常不安全的。

    4_26种source-map的值.png

    但这26种 source map 是有规律可循的,弄懂几种类型就可以全部理解。

    source map 文件

    当 devtool 设置为 source-map 时,webpack 会生成一个 source map 文件,并在打包后的 bundle.js 文件最后添加一行注释,指向 source map 文件。

    5_devtool为source-map.png

    source map文件中有这些字段用于记录编译后代码与源码的映射关系

    • version:版本,第一个版本的 source map 文件大小是源文件的 10 倍左右,第二版减少了 50%,第三版又减少了 50%,现在是第三版。
    • file:编译后的文件名,用于浏览器加载的
    • mappings:用来保存和源文件的映射信息(比如行、列位置信息、变量等)
    • sources:转换前的源文件、打包所用webpack代码
    • sourceContent:转换前的具体代码信息(与sources是对应的关系)
    • names:转换前的变量和属性名称
    • sourceRoot:所有sources相对的根目录
    6_source-map文件.png

    以上是生成 source map 文件时的标准版本,除了某些不生成 source map 文件的配置,其它都是以类似这种方式来设置映射关系的。

    不生成 source map 文件

    也有可能存在不需要 source map 文件的情况,有两种方式来配置 devtool,使之不不生成 source map 文件。

    • false:不使用 source map
    • none:mode 为 production 的默认值(没有定义 devtool 时)

    这两种方式不会生成 bundle.js.map 文件,也不会在 bundle.js 引入 bundle.js.map 。

    内联 source-map

    除了直接生成 source map 文件,还可以将 source map 内容直接内联到编译后的 bundle.js 中,有三种方式来配置 devtool。

    • eval:development 模式下的默认值(没有定义 devtool 时),通过 eval 函数来执行文件内容,并在最后增加指向该内容所在的源文件地址
    • eval-source-map:生成的 source map 以 base64 编码的形式添加到 eval 函数中
    • inline-source-map:生成的 source map 以 base64 编码放置在打包后文件的最后面

    eval

    当 devtool 设置为 eval 时,在编译的 bundle.js 文件中,使用 eval 执行文件内容,并通过 //# sourceURL= 指向源文件地址。

    7_eval的source-map内容.png

    此时可以获取到报错的文件、行、列,但看到的代码与源码会有一点不同,增加了 webpack 处理的部分。

    8_eval的报错提示.png

    eval-source-map

    当 devtool 设置为 eval-source-map 时,文件内容通过 eval 函数执行,source map 通过base64编码后添加到了eval函数中。

    9_eval-source-map的source-map内容.png

    此时通过控制台可以看到具体源代码,报错提醒具体到行与列。

    10_eval-source-map的报错提示.png

    inline-source-map

    当 devtool 设置为 inline-source-map 时,source map 通过base64编码后添加到了文件最末尾处。

    11_inline-source-map的source-map内容.png

    此时通过控制台可以看到具体源代码,报错提醒也具体到行与列。

    12_inline-source-map报错提示.png

    因为 source map 会占据较大空间,将 source map 内联到 bundle.js 文件中,会使打包后文件体积变大。

    报错精确到行

    以上的报错信息都是精确到"列"的,提示具体哪个字段报错,而精确到"行"的话,只会告知这一行中有错误。

    13_精确到列与行的区别.png

    只精确到行,编译速度会稍快一点,有两种方式设置 devtool,这两种文件都会生成 source map 文件,也就是 bunlde.js.map。

    • cheap-source-map:只精确到行,对于有loader的情况,会不够准确。
    • cheap-module-source-map:只精确到行,可以很好的处理有loader的情况。

    为了方便演示,将普通函数改成箭头函数。

    可以看到,两者都是精确到"列"的,"cheap-source-map" 定位到的代码和实际的源码有些出入,并且行列顺序也有点不同,但"cheap-module-source-map" 就与源码完全一致。

    14_cheap-module-source-map.png

    不显示源码

    有没有方法既生成 sourcemap,又不会显示源代码呢?webpack 也提供了两种 devtool 的配置。

    • hidden-source-map:与 devtool 定义成 source-map 一样都会生成 source map 文件,只是在打包后文件 bundle.js 中,没有对 source-map 的引用,如果手动加入,也是会生效的。
    • nosources-source-map:会生成source map,但是生成的source map只有错误信息的提示,不会生成源代码文件, 会在控制台告诉错误的内容及文件,但是点击文件名的时候看不到源码

    hidden-source-map

    没有引入 source map,在报错信息处也就不会指向源码

    15_hidden-source-map.png

    nosources-source-map

    此时会生成 source map 文件,打包后的 bundle.js 也会引入map文件,也可以看到报错内容所在文件,但无法获取源码。

    16_nosources-source-map.png

    组合规则

    通过表格总结一下上面所提到的 source map

    17_总结.png

    理解这些 source map 之后,剩余的组合也可以推导出,比如

    • eval-cheap-module-source-map:不会生成 source map 文件,而是将 source map 以 base64 编码的形式添加到eval函数中,不会精确到列,只精确到列,且
      存在loader时,可准确定位源码
    • inline-nosources-source-map:不生成 source map 文件,将 source map 以base 64 编码的形式添加到编译后文件的底部,不会展示源码。

    但以上这些也不能随意的组合,要遵循以下规则

    • inline-|hidden-|eval:三个值时三选一,可不选
    • nosources:可选值
    • cheap可选值,并且可以跟随module的值

    总结起来如下
    [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

    在开发、测试、生产阶段,也有一些推荐

    • 开发阶段:source-map(vue脚手架默认值)或者 cheap-module-source-map(react脚手架默认值)
    • 测试阶段:source-map 或者 cheap-module-source-map,可快速定位问题
    • 发布阶段:false、none(即不写)

    source map 可以帮助我们在开发、测试阶段更好的定位问题,正确的使用能够提升效率。

    以上就是关于 source map 的详细介绍,更多有关webpack的内容可以参考我其它的博文,持续更新中~

    相关文章

      网友评论

          本文标题:26种source-map看花了眼?别急,理解这几个全弄懂

          本文链接:https://www.haomeiwen.com/subject/clcxyrtx.html