上一篇 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 是有规律可循的,弄懂几种类型就可以全部理解。

source map 文件

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

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

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

以上是生成 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= 指向源文件地址。

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

eval-source-map

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

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

inline-source-map

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

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

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

报错精确到行

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

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

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

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

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

不显示源码

有没有方法既生成 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,在报错信息处也就不会指向源码

nosources-source-map

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

组合规则

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

理解这些 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看花了眼?别急,理解这几个全弄懂的更多相关文章

  1. source map 的原理探究

    线上产品代码一般是编译过的,前端的编译处理过程包括不限于 转译器/Transpilers (Babel, Traceur) 编译器/Compilers (Closure Compiler, TypeS ...

  2. 源映射(Source Map)详解

    一.什么是源映射 为了提高性能,很多站点都会先压缩 JavaScript 代码然后上线, 但如果代码运行时出现错误,浏览器只会显示在已压缩的代码中的位置,很难确定真正的源码错误位置. 这时源映射就登场 ...

  3. JavaScript Source Map 详解

    源码地址: http://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html 上周,jQuery 1.9发布. 这是2.0版之前的最后 ...

  4. javascript source map 的使用

    之前发现VS.NET会为压缩的js文添加一个与文件名同名的.map文件,一直没有搞懂他是用来做什么的,直接删除掉运行时浏览器又会报错,后来google了一直才真正搞懂了这个小小的map文件背后的巨大意 ...

  5. 【转】webpack中关于source map的配置

    Webpack中sourcemap的配置 sourcemap是为了解决开发代码与实际运行代码不一致时帮助我们debug到原始开发代码的技术.尤其是如今前端开发中大部分的代码都经过编译,打包等工程化转换 ...

  6. Javascript 如何生成Less和Js的Source map

    为什么有Source map CSS和JS脚本正变得越来越复杂,为了解决网络瓶颈,大部分源代码都需要经过编译.合并.压缩才能运用到实际环境中.为了减少网络资源占用,源码一般都会经过以下方式处理: 使用 ...

  7. Fundebug微信小程序BUG监控服务支持Source Map

    摘要: 自动还原真实出错位置,快速修复BUG. Source Map功能 微信小程序的Source Map功能目前只在 iOS 6.7.2 及以上版本支持. 微信小程序在打包时,会将所有 js 代码打 ...

  8. Source Map调试压缩后代码

    在前端开发过程中,无论是样式还是脚本,运行时的文件可能是压缩后的,那这个时候调试起来就很麻烦. 这个时候,可以使用Source Map文件来优化调试,Source Map是一个信息文件,里面储存着原代 ...

  9. java source map

    Chrome 更新后出现了 jquery.min.map 404  (Not Found) 的信息 这个到底是什么东西?查询了一下,得到了以下资料 JQuery 官方解释 摘录一下內容 从 jQuer ...

  10. Source Map入门教程

    部署前端之前,开发者通常会对代码进行打包压缩,这样可以减少代码大小,从而有效提高访问速度.然而,压缩代码的报错信息是很难Debug的,因为它的行号和列号已经失真.这时就需要Source Map来还原真 ...

随机推荐

  1. 苦苦搞了半个通宵才搞定的直接使用Sliverlight将文件PUT到阿里云OSS

    为了公司的项目,小的我各种折腾啊,不过高兴的是实现了Silverlight直接提交至阿里云OSS的文件上传,文件上传再也不用通过服务器中转了. 研究SDK发现还有个Node-oss.js,但还没进行测 ...

  2. TextArea设置MaxLength的代码(未测试在不同浏览器下的兼容性)

    function SetTextAreaMaxLength(controlId,length) { // JScript File for TextArea // Keep user from ent ...

  3. Golang for循环遍历小坑

    一.for循环 循环:让程序多次执行相同的代码块for循环是Go语言中唯一一个循环结构for循环经典语法先执行表达式1执行表达式2判断是否成立,如果成立执行循环体循环体执行完成后,执行表达式3再次执行 ...

  4. selenium文件上传和弹框处理

    文件上传 input 标签可以直接使用send_keys(文件地址)上传文件 用法: el = driver.find_element_by_id('上传按钮id') el.send_keys(&qu ...

  5. proto中service 作用的理解

    转载请注明出处: 在 proto 文件中,service 用于定义一组 RPC 方法,在服务端实现这些方法,并在客户端调用这些方法进行远程过程调用. service 的定义方式如下: service ...

  6. flutter apk启动闪退问题

    今发布一个flutter apk 安装后启动时老是闪退,经过一遍又一遍查找,发现是指定了so的问题 看多次点击启动 一.比对打包后的apk 在出现该问题后也搜索了不少资料,参考过 https://bl ...

  7. pycham2022最新破解

    pycharm破解方式常见有2种: 1 .破解插件+激活码,一般激活到2099年或者2089年! 2 .破解插件.该破解插件可以无限重置30天,也就是pycharm永远有30天的试用期,永不到期!   ...

  8. 【RocketMQ】NameServer总结

    NameServer是一个注册中心,提供服务注册和服务发现的功能.NameServer可以集群部署,集群中每个节点都是对等的关系(没有像ZooKeeper那样在集群中选举出一个Master节点),节点 ...

  9. 在R中子集化数据框的5种方法

    由于微信不允许外部链接,你需要点击文章尾部左下角的 "阅读原文",才能访问文中链接. 通常,我们在使用大型数据集时,只会对其中的一小部分感兴趣,用以进行特定分析. 那么,我们应该如 ...

  10. python3使用pjsua进行呼叫测试

    环境:CentOS 7.6_x64    Python版本 :3.9.12 pjsip版本:2.13   之前写过一篇CentOS7环境编译python3.9版本pjsua的文章: https://w ...