3-7 sourceMap的配置

1. 簡(jiǎn)介

sourceMap,顧名思義,就是對(duì)源文件的映射。比如打包壓縮后的代碼對(duì)應(yīng)源文件中的哪一行代碼,這能夠極大地方便開發(fā)者的調(diào)試。

2. sourceMap的作用

我們用一個(gè)簡(jiǎn)單的示例,來看一下sourceMap的作用。如圖,先精簡(jiǎn)一下之前的項(xiàng)目文件。


image.png

將sidebar.js中的console,log故意攜程console.lo,修改webpack_config.js如下:

// webpack.config.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin');
var path = require('path');

module.exports = {
    entry: {
        index: "./src/index.js",
    },
    devtool: "none",
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "[name].js"
    },
    mode: 'development',
    plugins: [new HtmlWebpackPlugin({
        template: "./src/index.html"
    }), new CleanWebpackPlugin()]
};

打包后打開index.html,我們發(fā)現(xiàn)網(wǎng)頁(yè)上沒有sidebar。打開調(diào)試模式有報(bào)錯(cuò)。


image.png

點(diǎn)擊報(bào)錯(cuò)提示,我可以看到光標(biāo)直接在出問題的代碼處閃爍。但問題是,我們并不是直接修改打包后的文件來修復(fù)問題,而是去修改源文件來解決問題。所以,我們希望能夠直接定位到出錯(cuò)的源代碼。

3. source map

source map是用來記錄轉(zhuǎn)換后代碼和源代碼之間映射關(guān)系的代碼,當(dāng)客戶端瀏覽器在收到打包后的js文件時(shí),它根據(jù)指定的sourcmap文件把打包的的js代碼轉(zhuǎn)換成格式規(guī)范的js代碼。
也就是說,瀏覽器運(yùn)行轉(zhuǎn)換后的代碼出錯(cuò)時(shí)定位到源代碼位置的關(guān)鍵因素在于:
有記錄映射關(guān)系的source_map,并能告知瀏覽器如何讀取。
我們配置如下屬性:

devtool: "source-map"

運(yùn)行打包命令后,如下:


image.png

image.png

生成了一個(gè)單獨(dú)的source map文件用來記錄映射關(guān)系,同時(shí)在打包生成的代碼末尾注明了source map文件的地址。
點(diǎn)擊報(bào)錯(cuò)信息,如下,點(diǎn)擊后直接定位到了出錯(cuò)的源碼。


image.png

總結(jié):整個(gè) source map 作為一個(gè)單獨(dú)的文件生成。它為 bundle 添加了一個(gè)引用注釋,以便開發(fā)工具知道在哪里可以找到它??捎糜谏a(chǎn)環(huán)境和開發(fā)環(huán)境。對(duì)于生產(chǎn)環(huán)境,應(yīng)該將服務(wù)器配置為,不允許普通用戶訪問 source map 文件。
優(yōu)點(diǎn):能夠準(zhǔn)確映射到原始源代碼
缺點(diǎn):由于攜帶了最完整的映射信息,所以構(gòu)建和重構(gòu)速度很慢

我們目前使用的是生成一個(gè)完整的map文件的形式來記錄映射信息,那么還有沒有別的方法呢?

3.1 inine 關(guān)鍵字

顧名思義,內(nèi)聯(lián)。就是將.map文件作為DataURI嵌入,不單獨(dú)生成.map文件。他必須與其它關(guān)鍵字配合使用,如下:

devtool: "inline-source-map"

打包后如下:


image.png

可以看到?jīng)]有map文件了,底部的 sourceMappingURL 從文件地址變成了base64編碼。等于是將原來單獨(dú)的map文件編碼城base64內(nèi)嵌到了打包輸出的js文件中。
點(diǎn)擊報(bào)錯(cuò)信息后直接定位到了出錯(cuò)的源碼。
總結(jié): source map 轉(zhuǎn)換為 DataUrl 后添加到 bundle 中。僅用于開發(fā)環(huán)境
優(yōu)點(diǎn):能夠準(zhǔn)確映射到原始源代碼,相較source-map,可以少加載一個(gè)文件
缺點(diǎn):由于攜帶了最完整的映射信息,所以構(gòu)建和重構(gòu)速度很慢。相較source-map,打包后的index.js文件變大了。

3.2 hidden 關(guān)鍵字

隱藏源文件。僅有一種搭配:

devtool: "hidden-source-map"

打包后如下:


image.png

沒有引用地址注釋了,但仍然可以準(zhǔn)確定位到源文件信息。


image.png

總結(jié):與 source-map 相同,但不會(huì)為 bundle 添加引用注釋。如果你只想 source map 映射那些源自錯(cuò)誤報(bào)告的錯(cuò)誤堆棧跟蹤信息,但不想為瀏覽器開發(fā)工具暴露你的 source map,這個(gè)選項(xiàng)會(huì)很有用??捎糜陂_發(fā)環(huán)境和生產(chǎn)環(huán)境。生產(chǎn)環(huán)境中,不應(yīng)將 source map 文件部署到 web 服務(wù)器。而是只將其用于錯(cuò)誤報(bào)告工具。
ps:inline可以和大多數(shù)關(guān)鍵字配合使用,作用是將source map進(jìn)行內(nèi)聯(lián)。

3.3 eval 關(guān)鍵字

直接將每個(gè)模塊使用 eval 執(zhí)行。這里可以單獨(dú)使用,也可以搭配其他關(guān)鍵字使用。

3.3.1 eval

devtool: "eval"
image.png

image.png

總結(jié):每個(gè)模塊都使用 eval() 執(zhí)行,并且都有 //@ sourceURL。僅用于開發(fā)環(huán)境。
優(yōu)點(diǎn):此選項(xiàng)會(huì)非??斓貥?gòu)建。
缺點(diǎn):由于會(huì)映射到轉(zhuǎn)換后的代碼,而不是映射到原始代碼(沒有從 loader 中獲取 source map),所以不能正確地顯示行數(shù)。

3.3.2 eval-source-map

devtool: "eval-source-map"
image.png

image.png

總結(jié):每個(gè)模塊使用 eval() 執(zhí)行,并且 source map 轉(zhuǎn)換為 DataUrl 后添加到 eval() 中。僅用于開發(fā)環(huán)境。
優(yōu)點(diǎn):重新構(gòu)建時(shí)有比較快的速度,并且生成實(shí)際的文件。行數(shù)能夠正確映射,因?yàn)闀?huì)映射到原始代碼中。它會(huì)生成用于開發(fā)環(huán)境的最佳品質(zhì)的 source map。
缺點(diǎn):初始化 source map 時(shí)比較慢

3.3.3 搭配其他關(guān)鍵字

eval 還可以搭配其他關(guān)鍵字,下面會(huì)講到。但不管搭配什么,它的作用都是,將每個(gè)模塊都使用 eval() 執(zhí)行。

4. source map詳細(xì)程度

目前為止,我們都是拿到了所有模塊的完整映射信息。但是,十幾條是的時(shí)候我們并不需要這么晚完整的映射信息。那么有什么辦法來減少不必要的映射信息,加快構(gòu)建速度呢?

4.1 cheap 關(guān)鍵字

作用: 顧名思義,低配的。不包含列信息,也不包含loader的sourcemap??纱钆浯蟛糠制渌P(guān)鍵字使用。比如:

devtool: "cheap-source-map"

sourceMap文件默認(rèn)會(huì)保存打包代碼和源代碼之間的行與列的映射信息,文件內(nèi)容較復(fù)雜時(shí),報(bào)錯(cuò)會(huì)攜帶列信息。但如果指明了cheap,就不需要映射列信息,出錯(cuò)時(shí)只會(huì)攜帶行信息。另外,不包含loader的 sourcemap(例如 babel 的 sourcemap)。


image.png

image.png

如圖,僅定位到了錯(cuò)誤的行。
總結(jié):沒有列映射(column mapping)的 source map,忽略 loader source map。映射的是轉(zhuǎn)換過的代碼(僅限行)??捎糜陂_發(fā)環(huán)境和生產(chǎn)環(huán)境。
優(yōu)點(diǎn):構(gòu)建速度較快。
缺點(diǎn):映射信息品質(zhì)降低。

4.2 module 關(guān)鍵字

module關(guān)鍵字僅在 cheap 關(guān)鍵字存在的情況下使用。用來提升映射信息品質(zhì),輸出模塊映射的行信息。

devtool: "cheap-module-source-map"
image.png

image.png

總結(jié):沒有列映射(column mapping)的 source map,將 loader source map 簡(jiǎn)化為每行一個(gè)映射(mapping)??捎糜陂_發(fā)環(huán)境和生產(chǎn)環(huán)境。
優(yōu)點(diǎn):提升了映射信息品質(zhì),映射到原始源代碼(僅限行)。
缺點(diǎn):品質(zhì)和速度都是中等,并無(wú)突出的地方。

5. 最佳模式

以上關(guān)鍵字,都擁有自己的行為,搭配起來,就是將不同的行為進(jìn)行組合。

  1. source-map 生成映射信息文件
  2. inline 將映射信息內(nèi)聯(lián)
  3. eval 將模塊用eval包裹執(zhí)行。含有這個(gè)關(guān)鍵字就不能用于生產(chǎn)環(huán)境。
  4. cheap 降低映射信息品質(zhì),沒有列信息,沒有l(wèi)oader的映射信息
  5. module 必須與cheap搭配,仍然沒有列信息,但是會(huì)映射loader的行信息
    基于以上特征,我們?cè)谏a(chǎn)和開發(fā)中的最佳搭配模式如下:
    開發(fā):cheap-module-eval-source-map
    生產(chǎn):cheap-module-source-map

補(bǔ)充

原理后續(xù)研究一下。

參考

https://www.webpackjs.com/configuration/devtool/
https://webpack.js.org/configuration/devtool/
Webpack中的sourcemap
MDN - 使用 source map
解決Failed to parse SourceMap: http:xxx 問題
淺談webpack devtool里的7種SourceMap模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • publicPath指定了一個(gè)在瀏覽器中被引用的URL地址。 對(duì)于使用 和 加載器,當(dāng)文件路徑不同于他們的本地磁盤...
    飛呀飛哥閱讀 1,759評(píng)論 0 0
  • 開始準(zhǔn)備 為了從JavaScript模塊中import一個(gè)CSS文件,需要安裝并添加style-loader和cs...
    皮皮坤666閱讀 43,972評(píng)論 1 18
  • source maps Webpack打包生成的.map后綴文件,使得我們的開發(fā)調(diào)試更加方便,它能幫助我們鏈接到斷...
    zhangivon閱讀 14,713評(píng)論 5 3
  • section-2.1 什么是loader loader 用于對(duì)模塊的源代碼進(jìn)行轉(zhuǎn)換。loader 可以使你在 i...
    羽晞yose閱讀 679評(píng)論 0 0
  • 近日,在2019MWC期間的OPPO創(chuàng)新大會(huì)上,OPPO公布了其最新的智能手機(jī)三攝配置方案。開創(chuàng)性顛覆傳統(tǒng)"黑白+...
    aonbs從安閱讀 447評(píng)論 0 0

友情鏈接更多精彩內(nèi)容