Webpack中sourcemap的配置

sourcemap是为了解决开发代码与实际运行代码不一致时帮助我们debug到原始开发代码的技术。尤其是如今前端开发中大部分的代码都经过编译,打包等工程化转换。比如开发环境下用scss写样式, 想在浏览器中在线编辑css那样编辑scss就不是那么容易了。从我自己看过的资料中, sourcemap的概念最早出现在12年, jquer1.9是较早支持sourcemap的库。这篇博客比较有代表性:Introduction to JavaScript Source Maps,阮一峰的文章JavaScript Source Map 详解也大量参考该博客。关于sourcemap的原理及作用,基本在这两篇文章中讲清楚了。回到webpack中的sourcemap,就我这几天的琢磨, 这方面资料相对比较零散,但凡搜索Webpack中sourcemap的配置, 总是能得到千篇一律的如下信息:
Sourcemap type Quality Notes

eval: 生成代码 每个模块都被eval执行,并且存在@sourceURL

cheap-eval-source-map: 转换代码(行内) 每个模块被eval执行,并且sourcemap作为eval的一个dataurl

cheap-module-eval-source-map: 原始代码(只有行内) 同样道理,但是更高的质量和更低的性能

eval-source-map: 原始代码 同样道理,但是最高的质量和最低的性能

cheap-source-map: 转换代码(行内) 生成的sourcemap没有列映射,从loaders生成的sourcemap没有被使用

cheap-module-source-map: 原始代码(只有行内) 与上面一样除了每行特点的从loader中进行映射

source-map: 原始代码 最好的sourcemap质量有完整的结果,但是会很慢

webpack中devtool的配置的官方文档在这 :webpack-devtool

疑问

反正我看完这些说明是云里雾里, 就我自己而言, 有3个疑问:

  1. eval和sourcemap有什么关系,eval模式是sourcemap吗?

  2. 包含cheap关键字的配置中只有行内是什么意思?

  3. 这几种不同的配置有什么区别?

解答

看似配置项很多, 其实只是五个关键字evalsource-mapcheapmoduleinline的任意组合。这五个关键字每一项都代表一个特性, 这四种特性可以任意组合。它们分别代表以下五种特性(单独看特性说明有点不明所以,别急,往下看):

  • eval: 使用eval包裹模块代码

  • source-map: 产生.map文件

  • cheap: 不包含列信息(关于列信息的解释下面会有详细介绍)也不包含loader的sourcemap

  • module: 包含loader的sourcemap(比如jsx to js ,babel的sourcemap)

  • inline: 将.map作为DataURI嵌入,不单独生成.map文件(这个配置项比较少见)

了解了以上各种不同特性, 再来逐一解答以上问题。

eval和sourcemap有什么关系,eval模式是sourcemap吗?

evalsource-map都是webpack中devtool的配置选项, eval模式是使用eval将webpack中每个模块包裹,然后在模块末尾添加模块来源//# souceURL, 依靠souceURL找到原始代码的位置。包含eval关键字的配置项并不单独产生.map文件(eval模式有点特殊, 它和其他模式不一样的地方是它依靠sourceURL来定位原始代码, 而其他所有选项都使用.map文件的方式来定位)。包含source-map关键字的配置项都会产生一个.map文件,该文件保存有原始代码与运行代码的映射关系, 浏览器可以通过它找到原始代码的位置。(注:包含inline关键字的配置项也会产生.map文件,但是这个map文件是经过base64编码作为DataURI嵌入),举个栗子:eval-source-mapevalsource-map的组合,可知使用eavl语句包括模块,也产生了.map文件。webpack将.map文件作为DataURI替换eval模式中末尾的//# souceURL。按照我自己的理解, eval.map文件都是sourcemap实现的不同方式,虽然大部分sourcemap的实现是通过产生.map文件, 但并不表示只能通过.map文件实现。下面是eval模式后产生的模块代码:

包含cheap关键字的配置中只有行内是什么意思?

这里的列信息指的是代码的不包含原始代码的列信息。 官方文档对于包含cheap的解释是这样的:

> cheap-source-map - A SourceMap without **column-mappings**. SourceMaps
> from loaders are not used.

这句话翻译过来就是“在cheap-source-map模式下sourcemap不包含列信息,也不包含loaders的sourcemap”这里的“column-mappings”就是代码列数的意思,是否包含loaders的sourcemap有什么区别将在之后提到。debug的时候大部分人都只在意代码的行数, 很少关注列数, 列数就是该行代码从第一个字符开始到定位字符的位置(包括空白字符)包含cheap关键字的模式不包含列信息,体现在webpack中就是:如果包含cheap关键字,则产生的.map文件不包含列信息。也就是说当你在浏览器中点击该代码的位置时, 光标只定位到行数,不定位到具体字符位置。而不包含cheap关键字时, 点击控制台log将会定位到字符位置。

包含列信息后点击原始代码的定位,注意光标位置:

不包含列信息的光标位置:

这篇博客:Go to a line number at a specific column直观地展示了列数的概念。如果深入到webpack中的细节中体会该配置项,可以看这篇博客:SurviveJS:Source Maps ,该文章对比了webpack中所有配置项中.map文件的代码,这里截取eval-source-mapcheap-source-map的模式产生的.map文件代码中的mappings字段对比:

devtool: 'eval-source-map'

"mappings": "AAAAA,QAAQC,GAAR,CAAY,aAAZ",

devtool: 'cheap-source-map'

"mappings": "AAAA",

注:这里使用了VLQ编码,(关于VLQ编码还可参考这里:前端构建:Source Maps详解) 在VLQ编码中,逗号,表示字符列分割,分号;表示行分割。包含cheap关键字的配置项不包含列信息,也就没有逗号。关于VLQ编码, 本文最初的阮一峰的文章中有所解释。而不包含loader的sourcemap指的是不包含loader的sourcemap,不包含它时候如果你使用了诸如babel等代码编译工具时, 定位到的原始代码将是经过编译后的代码位置,而非原始代码。

比如当我用babel编译JS的时候,如果包含不包含loaders的sourcemap,此时debug到的将是编译后的代码, 而非原始代码,如图(这是使用cheap-source-map模式未包含loaders的sourcemap情况下的截图, debug的位置与之前的对比截图是同一个地方):

这几种不同的配置有什么区别?

通过以上两个问题的解释, webpack中的sourcemap各个配置项异同应该有了一定认识,乍看之下各个配置项很难记忆, 但其实从每个关键字所代表的特性入手, 就能体会到他们的异同。他们在webpack中的主要区别一个体现在重构的性能上, 总的来说eval性能最好,source-map性能最低,但就我自身的实践来看大多用的是最完整的source-map,该模式对于不管是js还是css,scss等都能很好的覆盖, 相反其他模式都不完整, 在开发环境下重构性能似乎比不上功能的完善。 
另外需要补充的是module关键字, 当加上module关键字webpack将会添加loader的sourcemap。

Webpack中的sourcemap的更多相关文章

  1. Webpack中的sourcemap以及如何在生产和开发环境中合理的设置

    一 . 从Sourcemap和Data URL说起 (1)什么是Sourcemap? 我们在打包中,将开发环境中源代码经过压缩,去空格,babel编译转化,最终可以得到适用于生产环境的项目代码,这样处 ...

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

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

  3. webpack中使用typescript

    概述 这是我学习webpack中使用typescript的记录,供以后开发时参考,相信对其他人也有用. 学习typescript建议直接看中文文档或英文文档,休闲之余可以看这篇TypeScript 总 ...

  4. 在Vue的webpack中结合runder函数

    在Vue的webpack中结合runder函数 1.引入: <h1>下面是vue的内容:</h1> <div id="app"> <log ...

  5. 使用pug(jade),以及在vue+webpack中使用pug(jade)

    一:在HTML中使用pug 在css中有预处理器less和scss来使我们的样式表更加的简介,那么在HTML中有没有这样的格式呢,答案是有的,那就是pug(前身是jade),效果如下: 转译以后 好, ...

  6. webpack中Development和Production模式的区分打包

    当我们在开发一个项目的时候,我们一般用development这个环境进行项目的开发,在这个环境下,webpack使用dev-server,帮我们启用一个服务器,然后这个服务器里面还集成了一些,比如hm ...

  7. 理解webpack中的devTool的配置项

    2.1. eval  eval 会将每一个module模块,执行eval,执行后不会生成sourcemap文件,仅仅是在每一个模块后,增加sourceURL来关联模块处理前后对应的关系.在webpac ...

  8. 发现Webpack中泄露的api

    发现Webpack中泄露的api 目录 发现Webpack中泄露的api 1 - 安装 reverse-sourcemap 2 - 寻找xxx.js.map 3 - 下载xxx.js.map并获取所有 ...

  9. Webpack中hash与chunkhash的区别,以及js与css的hash指纹解耦方案

    文件的hash指纹通常作为前端静态资源实现增量更新的方案之一,Webpack是目前最流行的开源编译工具之一,其强大的功能也带来很多坑(当然,大部分麻烦其实都可以在官方文档中找到答案). 比如,在Web ...

随机推荐

  1. CentOS(学习笔记一)

    菜鸟记录 一.配置网络.防火墙等 setup命令 二.查看网络 ifconfig 重启网络 /ect/init.d/network restart 或者ifup ethx(,,)等 查看网络配置文件 ...

  2. 算法笔记_109:第四届蓝桥杯软件类省赛真题(JAVA软件开发本科B组部分习题)试题解答

    目录 1 马虎的算式 2 黄金连分数 3 有理数类 4 幸运数 5 连号区间数   前言:以下试题解答代码部分仅供参考,若有不当之处,还请路过的同学提醒一下~ 1 马虎的算式 标题: 马虎的算式 小明 ...

  3. java程序员认证考试题库

    第一部分 基础知识练习 目标 本章对应于<学生指南>各章的内容分别提供了练习题集,包括: ●  第一章Java入门 ●  第二章数据类型和运算符 ●  第三章流程控制与数组 ●  第四章封 ...

  4. servlet常用操作

      servlet常用操作 CreateTime--2017年9月7日09:36:43 Author:Marydon 1.获取当前应用程序对象 需要导入: import javax.servlet.S ...

  5. 自定义网站的icon和收藏夹图标

    定制网站收藏夹图标的方法有两种: 第一种方法: 第一步,当然是准备一个能体现您的主页的风格和个性的图标.比较简便的办法除了下载,就是将您的网站的logo做成一个图标. 第二步,将这个图标文件命名为:f ...

  6. Linux对包管理阐述

    Centos/Redhat/Fedora的软件包,都是rpm后缀的文件.包管理器rpm(Redhat packages manager)  linux的哲学思想是简单命令解决复杂任务,因此每个软件的功 ...

  7. 封装UIlabel 辨别用户名 ,话题 ,链接,电话,高亮文字等

    概述 对UIlabel进行封装 用于辨别用户名 ,话题 ,链接,电话,高亮文字等,链接跳转网页,电话点击拨打电话,完美封装UIlabel,适合绝大多数需求 详细 代码下载:http://www.dem ...

  8. 机器学习的敲门砖:手把手教你TensorFlow初级入门

    摘要: 在开始使用机器学习算法之前,我们应该首先熟悉如何使用它们. 而本文就是通过对TensorFlow的一些基本特点的介绍,让你了解它是机器学习类库中的一个不错的选择. 本文由北邮@爱可可-爱生活  ...

  9. Oracle EBS WMS功能介绍(二)

    Oracle EBS WMS功能介绍(二) (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处.否则请与本人联系,违者必究) 出货物流逻辑主要包括 1.      打包.能够进 ...

  10. HDUOJ----2647Reward

    Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...