随笔|闲扯前端工程化④---sourceMap知多少

114 阅读7分钟

了解热更新机制的原理,能够熟练配置热更新功能,能够提升我们的开发效率。在实际的工作中,影响我们开发效率的问题有很多。

我们可能都遇到过这样的问题,项目在开发环境下每次构建感觉都非常慢,修改完代码,总是要等一会儿才能看到最新的效果,这是为什么?

这其实跟我们的 sourceMap 配置有关。

那么接下来的问题:什么是sourceMap?

在现代前端开发过程中,我们的代码会经过多重处理,编译、封装、压缩等,最后形成最终的文件。

造成的一个问题是,我们在浏览器中调试代码时,会发现代码跟我们写的源码完全不是一个同一个东西,于是,我们需要一种工具,能够将这个代码能够转化成我们原始的代码,sourceMap就是这个工具。

sourceMap的基本原理是在编译过程中,生成最终代码的同时会生成一个映射关系表,有了这个映射表之后,我们就可以通过浏览器控制台中的“enable javascript source map ”实现调试时定位源代码的功能。

同一个源文件,不同的目标可以生成不同效果的 source map 。构建速度、质量、方案、生成的文件大小也可能都不一样。

而在开发过程中,我们通常关注的是速度,不太关注文件大小。

而在生成环境中,我们更关注是否要开启source map,以及最终文件的大小是不是会对页面加载速度、性能造成影响,不太关注构建速度。

在webpack中,通过设置**devtool**来改变source map的预设风格,从而构建(build)和重新构建(rebuild)的速度造成影响

链接放到这里,有兴趣的可以点开看看webpack devtool

文档中提供了20多个配置,这个配置的关键词通常都是由eval,cheap,module,nosources,source-map等组合而成。

source map关键字设置:

  • false: 不开启source map
  • eval : 在编译器中使用evaldevtoolModulePlugin作为source map的处理插件
  • 前缀+source-map: 根据devtool中对应的是否有eval关键字来决定使用evaldevtoolModulePlugin还是sourceMapdevtoolPlugin作为source map的处理插件
  • inline关键字:决定是否传入插件的 filename参数,作用是决定单独生成source map文件还是在行内显示
  • hidden关键字:决定传入插件append的的赋值,用来判断是否添加source mapping url 的注视
  • module:为true 时传入插件的 module为 true ,作用是为加载器(Loaders)生成 source map
  • cheap :当 module 为 false 时,它决定插件 module 参数的最终取值,最终取值与 cheap 相反决定插件 columns参数的取值,作用是决定生成的source map中是否包含列信息,在不包含列信息的情况下,调试时只能定位到指定代码所在的行
  • nosource:决定插件中nosource的变量取值,决定生成的source map 是否包含源码信息,没有源码时只能显示调用栈信息

实际上,webpack是从三种不同的插件中根据不同配置选择不同的插件来处理source map

第一种是evaldevtoolModulePlugin,这个插件的作用是在模块代码后添加source url,比如:source URL = webpack://+模块儿引用路径,它不生成膜代码,是通过eval进行封装。

第二种是 evalsourcemapdevtoolplugin,它的作用是生成base64格式的source map 并附加在模块代码之后,source map后添加source URL = webpack://+模块儿引用路径,模块代码通过eval进行封装。

第三种就是sourcemapdevtoolplugin,它的作用就是生成单独的.map文件,模块代码并不通过eval进行封装。

三种插件接受的参数不同,那么对sourcemap的生成又回产生不同的效果

以下是文档中的配置项解释:

devtool表现:构建表现:重建production质量评论
(none)构建:最快 重建:最快推荐选择具有最高性能的生产版本。
eval构建:快速 重建:最快生成推荐选择具有最高性能的开发版本。
eval - cheap - source - map构建:确定 重建:快速转型开发构建的权衡选择。
eval - cheap - module - source - map建造:慢 重建:快原始线路开发构建的权衡选择。
eval - source - map构建:最慢 重建:确定原来的建议选择具有高质量SourceMaps的开发版本。
cheap - source - map构建:成功 重建:缓慢转型
cheap - module - source - map建造:缓慢 重建:缓慢原始线路
source - map建造:最慢 重建:最慢原来的建议选择具有高质量SourceMaps的生产版本。
inline - cheap - source - map构建:成功 重建:缓慢转型
inline - cheap - module - source - map建造:缓慢 重建:缓慢原始线路
inline - source - map构建:最慢 重建:最慢原来的发布单个文件时可能的选择
eval - nosources - cheap - source - map构建:确定 重建:快速转型不包括源代码
eval - nosources - cheap - module - source - map建造:慢 重建:快原始线路不包括源代码
eval - nosources - source - map构建:最慢 重建:确定原来的不包括源代码
inline - nosources - cheap - source - map构建:成功 重建:缓慢转型不包括源代码
inline - nosources - cheap - module - source - map建造:缓慢 重建:缓慢原始线路不包括源代码
inline - nosources - source - map构建:最慢 重建:最慢原来的不包括源代码
nosources - cheap - source - map构建:成功 重建:缓慢转型不包括源代码
nosources - cheap - module - source - map建造:缓慢 重建:缓慢原始线路不包括源代码
nosources - source - map构建:最慢 重建:最慢原来的不包括源代码
hidden - nosources - cheap - source - map构建:成功 重建:缓慢转型无参考,不包含源代码
hidden - nosources - cheap - module - source - map建造:缓慢 重建:缓慢原始线路无参考,不包含源代码
hidden - nosources - source - map构建:最慢 重建:最慢原来的无参考,不包含源代码
hidden - cheap - source - map构建:成功 重建:缓慢转型没有参考
hidden - cheap - module - source - map建造:缓慢 重建:缓慢原始线路没有参考
hidden - source - map建造:最慢 重建:最慢原来的无参考。仅将SourceMap用于错误报告目的时可能的选择。

不同的配置类型,会在几个方面产生不同的影响:

代码质量方面。可以分为5个级别,调试的便利性会依次降低:

源代码->缺少列信息的源代码->loader转化后的代码->生成的产物代码->不显示代码

对应的关键字:

source-map=eval-source-map->cheap-module->cheap->eval=none->nosource-map

构建速度上。rebuild 的速度通常都快于build。不同环境关注点也不一样,开发环境汇总,因为我们一直开启本地服务,所以rebuild的速度对我们的开发效率有影响。

eval对应的evalsourcemapdevtoolplugin整体要快于不带eval的插件,在生产环境中,我们通常不需要进行rebuild,所以build的速度对我们来说比较重要,如果我们build的时间超过15分钟,那么是不是需要考虑进行优化呢?

其实,了解了devtool的相关预设值我们就可以在不同的场景下选择不同的策略。

比如:开发环境下选择哪种配置,取决于sourcemap对我们的作用大小,如果我们对源码非常熟悉,那么我们甚至可以直接关闭devtool,或者直接使用eval来提高构建速度

而在调试的时候,通常需要通过source map 来快速定位到问题,所以我们可以优先考虑用eval-cheap-modulesource-map ,它的质量和构建速度都属于次优先级,牺牲了定位到列的功能换取更快的构建速度。

其他情况下,我们可以根据质量要求更高,或者是速度要求更高来进行设置。如果质量要求高,那么就可能选eval-source-map , 如果速度要求高,则可能选eval-cheap-source-map。

最后,说一下EvalSourceMapDevToolPlugin的使用方法

EvalSourceMapDevToolPlugin接受的参数有:

  • 预设相关的filename、append、module、columns
  • 影响注释内容的moduleFilenameTemplate 和 protocol
  • 影响处理范围的 test、include、exclude

如果我们能将和业务无关的第三方代码排除出去,则会提高我们的构建速度。

实例:

// webpack.config.js

// devtool:'eval-source-map',
plugins:[
  new webpack.EvalSourceMapDevToolPlugin({
  exclude:/node_modules/,
  module:true,
  columns:false
  })
]

source map的知识暂时就这么多...

(完)

没有关注公众号的朋友,觉得文章对您有启发的话,记得点赞、关注、评论、转发一下。