webpack之source map
前言
通过构建编译之类的操作,我们可以将开发阶段的源代码,转换为能够在生产环境中运行的代码,这是一种进步,但这种进步的同时也意味着我们在实际生产环境中运行的代码与我们在开发环境编写的代码之间会有很大的差异,这种情况下如果我们需要去调试应用,又或是我们在运行应用时出现了意料之外的错误,我们将无法定位错误信息。因为无论是调试还是调试还是报错都是基于转换过后的代码来进行的,source-map就是解决这类问题最好的一个办法。
一、什么是source map
source map 翻译过来就是源代码地图,它是用来映射我们转换后的代码与源代码之间的关系,转换后的代码我们通过转换过程中生成的source-map文件就可以逆向得到源代码。
一般打包生成后的bundle.js中会通过一段注释来引用source-map文件。
二、在webpack中启用source map
我们可以通过配置文件webpack.config.js中的devtool来配置source map。
// webpack.config.js
module.exports = {
..., // 其他的配置这里就不废话了
devtool:"source-map"
}
执行打包yarn webpack
,我们的dist目录中会多出一个bundle.js.map文件
在bundle.js最后一行,通过注释引入了source map文件。
这里我故意写个个错误的代码
会提示错误行数,点击可以直接跳转到错误位置。
三、关于source map的各种模式
在webpack中,source map有十二种模式,不同模式下生成的source map效果会有一定差别,并且打包速度以及webpack-dev-server重新构建的速度也不一样,我这里只是进行了一些关键词的解释,有兴趣的读者可以去官网查看详细解析。
const allModes = [
'eval',// 带有eval的,表示以使用eval执行模块代码
'eval-source-map',
'eval-cheap-source-map',// cheap表示包含行信息
'eval-cheap-module-source-map', // 有module的模式下,source map中的代码是没经过loader加工过的,也就是我们手写的代码
'cheap-source-map',
'cheap-module-source-map',
'inline-source-map',// 和普通的soure map效果基本一样,只不过sourcemap模式下,它的sourcemap文件是以物理文件的方式存在,inline-source-map是将sourcemap以DataUrl的方式嵌入到代码中(和eval有些类似),这会导致代码体积大很多
'inline-cheap-source-map',
'inline-cheap-module-source-map',
'source-map',
'hidden-source-map',// 这个模式下,我们在开发工具中是看不到效果的,但是它确实生成了sourcemap文件,这和jquery一样,生成了sourcemap文件但并没有在代码中注释引入,这个模式一般是我们在开发一些第三方包的时候可能会用到
'nosources-source-map'// 这个模式下我们能看到错误出现的位置,但是我们点击错误信息进去是看不到源代码的,nosources指的就是没有源代码,但还是提供了行列信息,我们可以结合源代码找到错误代码
]
推荐:
开发环境建议使用eval-cheap-module-source-map,我们的代码每行一般不会太长,经过loader转换后可能有较大差异,这种模式重写打包相对较快。
生产环境使用none,即不使用sourcemap,因为sourcemap会暴露源代码,如果实在担心自己写的代码出问题,可以用nosources-source-map,这样不会有被别人窃取源代码的危险,又能自己根据行列信息找到错误代码。
有兴趣的读者还可以尝试使用每种模式打包一次,看看效果。
// 使用这段代码记得安装babel-babel,yarn add babel-loader @babel/core @babel/preset-env --dev
// 使用babel-loader编译转换后更容易区分,带有module的模式与不带module模式的区别
const allModes = [
'eval',// 带有eval的,表示以使用eval执行模块代码
'eval-source-map',
'eval-cheap-source-map',// cheap表示包含行信息
'eval-cheap-module-source-map', // 有module的模式下,source map中的代码是没经过loader加工过的,也就是我们手写的代码
'cheap-source-map',
'cheap-module-source-map',
'inline-source-map',// 和普通的soure map效果基本一样,只不过sourcemap模式下,它的sourcemap文件是以物理文件的方式存在,inline-source-map是将sourcemap以DataUrl的方式嵌入到代码中(和eval有些类似),这会导致代码体积大很多
'inline-cheap-source-map',
'inline-cheap-module-source-map',
'source-map',
'hidden-source-map',// 这个模式下,我们在开发工具中是看不到效果的,但是它确实生成了sourcemap文件,这和jquery一样,生成了sourcemap文件但并没有在代码中注释引入,这个模式一般是我们在开发一些第三方包的时候可能会用到
'nosources-source-map'// 这个模式下我们能看到错误出现的位置,但是我们点击错误信息进去是看不到源代码的,nosources指的就是没有源代码,但还是提供了行列信息,我们可以结合源代码找到错误代码
]
module.exports = allModes.map( item => {
return {
devtool:item,
mode:"none",
entry:"./src/main.js",
output:{
filename:`js/${item}.js`
},
module:{
rules:[
{
test:/\.js$/,
use:{
loader:"babel-loader",
options:{
presets:['@babel/preset-env']
}
}
}
]
}
}
})