tft每日頭條

 > 生活

 > webpack環境設置

webpack環境設置

生活 更新时间:2024-07-28 22:24:58

webpack環境設置?用過 webpack 的都知道,webpack 的 sourcemap 配置是比較麻煩的,比如這兩個配置的區别:,我來為大家講解一下關于webpack環境設置?跟着小編一起來看一看吧!

webpack環境設置(徹底搞懂Webpack的)1

webpack環境設置

用過 webpack 的都知道,webpack 的 sourcemap 配置是比較麻煩的,比如這兩個配置的區别:

eval-nosources-cheap-module-source-map

hidden-module-source-map

是不是分不清楚?

其實它是有規律的。

你把配置寫錯的時候,webpack 會提示你一個正則:

^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$

這個就是配置的規律,是幾種基礎配置的組合。

搞懂了每一種基礎配置,比如 eval、nosources、cheap、module,按照規律組合起來,也就搞懂了整體的配置。

那這每一種配置都是什麼意思呢?

我們分别來看一下。

在講基礎配置之前,首先講下 sourcemap 是什麼:

sourcemap

sourcemap 是關聯編譯後的代碼和源碼的,通過一個個行列号的映射。

比如編譯後代碼的第 3 行第 4 列,對應着源碼裡的第 8 行第 5 列這種,這叫做一個 mapping。

sourcemap 的格式如下:

{

version : 3,

file: "out.js",

sourceRoot : "",

sources: ["foo.js", "bar.js"],

names: ["a", "b"],

mappings: "AAgBC,SAAQ,CAAEA;AAAEA",

sourcesContent: ['const a = 1; console.log(a)', 'const b = 2; console.log(b)']

}

version 是版本号,file 是文件名,sourceRoot 是源碼根目錄,names 是轉換前的變量名,sources 是源碼文件,sourcesContent 是每個 sources 對應的源碼的内容,mappings 就是一個個位置映射了。

為什麼 sources 可以有多個呢?

因為可能編譯産物是多個源文件合并的,比如打包,一個 bundle.js 就對應了 n 個 sources 源文件。

為什麼要把變量名單獨摘出來到 names 裡呢?

因為這樣就可以通過下标來索引了,mapping 裡面就不用保存變量名,隻保留 names 的索引就行。

重點是 mappings 部分:

mappings 部分是通過分号; 和逗号 , 分隔的:

mappings:"AAAAA,BBBBB;CCCCC"

一個分号就代表一行,這樣就免去了行的映射。

然後每一行可能有多個位置的映射,用 , 分隔。

那具體的每一個 mapping 都是啥呢?

比如 AAAAA 一共五位,分别有不同的含義:

第一位:轉換後代碼的第幾列(行數通過分号 ; 來确定)

第二位:對應轉換前的哪個源碼文件,保存在 sources 裡的,這裡通過下标索引

第三位:對應轉換前的源碼的第幾行

第四位:對應轉換前的源碼的第幾列

第五位:對應轉換前的源碼的哪個變量名,保存在 names 裡的,這裡通過下标索引

然後經過編碼之後,就成了 AAAAA 這種,這種編碼方式叫做 VLQ 編碼。

sourcemap 的格式還是很容易理解的,就是一一映射編譯後代碼的位置和源碼的位置。

各種調試工具一般都支持 sourcemap 的解析,隻要在文件末尾加上這樣一行:

//@ sourceMappingURL=/path/to/source.js.map

運行時就會關聯到源碼:

sourcemap 介紹完了,接下來一起來看下 webpack 的幾種 sourcemap 配置。

前面說過,webpack 的 sourcemap 配置是 eval、cheap、nosources、inline、source-map 等基礎配置的組合。

我們先分别來看下這幾種基礎配置:

eval

eval 的 api 是動态執行 JS 代碼的。比如:

但有個問題,eval 的代碼打不了斷點。

怎麼解決這個問題呢?

浏覽器支持了這樣一種特性,隻要在 eval 代碼的最後加上 //# sourceURL=xxx,那就會以 xxx 為名字把這段代碼加到 sources 裡。那不就可以打斷點了麼?

比如這樣:

執行以後,你會發現 sources 多了光.js的文件:

它是可以打斷點的,比如在 add 裡打個斷點,然後再執行 eval。

你會發現它斷住了!

除了指定 source 文件外,還可以進一步指定 sourcemap 來映射到源碼:

這樣,動态 eval 的代碼也能關聯到源碼,并且能打斷點了!

webpack 就利用了 eval 這個特性來優化的 sourcemap 生成的性能,比如你可以指定 devtool 為 eval:

生成的代碼就是每個模塊都被 eval 包裹的,并且有 sourceUrl 來指定文件名:

這樣有啥好處呢?

快呀,因為隻要指定個文件名就行,不用生成 sourcemap。sourcemap 的生成還是很慢的,要一個個 mapping 的處理,做編碼之類的。

每個模塊的代碼都被 eval 包裹,那麼執行的時候就會在 sources 裡生成對應的文件,這樣就可以打斷點了:

不過這樣隻是把每個模塊的代碼分了出去,并沒有做源碼的關聯,如果相關聯源碼,可以再開啟 sourcemap:

你會發現生成的代碼也是用 eval 包裹的,但除了 sourceUrl 外,還有 sourceMappingUrl:

再運行的時候除了 eval 的代碼會生成文件放在 sources 外,還會做 sourcemap 的映射:

webpack 的 sourcemap 的配置就利用了浏覽器對 eval 代碼的調試支持。

所以為什麼這個配置項不叫 sourcemap 而叫 devtool 呢?

因為不隻是 sourcemap 呀,eval 的方式也行。

再來看下一個基礎配置:

source-map

source-map 的配置是生成獨立的 sourcemap 文件:

可以關聯,也可以不關聯,比如加上 hidden,就是生成 sourcemap 但是不關聯:

生産環境就不需要關聯 sourcemap,但是可能要生成 sourcemap 文件,把它上傳到錯誤管理平台之類的,用來映射線上代碼報錯位置到對應的源碼。

此外,還可以配置成 inline 的:

這個就是通過 dataUrl 的方式内聯在打包後的文件裡:

這幾個配置還是很好懂的,我們來看下一個基礎配置:

cheap

sourcemap 慢主要是處理映射比較慢,很多情況下我們不需要映射到源碼的行和列,隻要精确到行就行,這時候就可以用 cheap。

不精确到列能提升 souremap 生成速度,但是會犧牲一些精準度:

我們再來看下一個基礎配置:

module

webpack 中對一個模塊會進行多次處理,比如經過 loader A 做一次轉換,再用 laoder B 做一次轉換,之後打包到一起。

每次轉換都會生成 sourcemap,那也就是有多個 sourcemap:

默認 sourcemap 隻是能從 bundle 關聯到模塊的代碼,也就是隻關聯了最後那個 sourcemap。

那如果你想調試最初的源碼怎麼辦呢?

那就把每一次的 loader 的 sourcemap 也關聯起來,這就是 module 配置的作用。

比如我們想調試 React 最初的源碼,那就要先生成有 sourcemap 的代碼:

怎麼生成有 sourcemap 的 React 代碼可以看我前面一篇文章。

有了 sourcemap 之後,要配置下 sourcemap-loader:

它的作用就是讀取源碼的 sourcemap,傳遞給後面的 loader。

之後配置 devtool,加上 module:

再次運行,你就會發現 react 代碼能映射到最初的源碼了:

之前隻能從 bundle.js 映射到編譯後的模塊代碼,也就是這一步:

devtool 配置加上 module,就支持了 loader 的 sourcemap 映射,然後再加上 sourmap-loader 來讀取源碼的 sourcemap,這樣就能一次性映射回最初的源碼:

當你想調試最初的源碼的時候,module 的配置就很有用了。

接下來還有最後一個基礎配置:

nosources

sourcemap 裡是有 sourceContent 部分的,也就是直接把源碼貼在這裡,這樣的好處是根據文件路徑查不到文件也可以映射,但這樣會增加 sourcemap 的體積。

如果你确定根據文件路徑能查找到源文件,那不生成 sourceContent 也行。

比如 devtool 配置為 source-map,生成的 sourcemap 是這樣的:

當你加上 nosources 之後,生成的 sourcemap 就沒有 sourceContent 部分了:

sourcemap 文件大小會小很多。

基礎配置講完了,接下來就是各種組合了,這個就比較簡單了,就算組合錯了,webpack 也會提示你應該按照什麼順序來組合。

它是按照這個正則來校驗的:^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$

接下來,我們讨論下最佳實踐:

線上的時候當然要啟用 hidden,不關聯 sourcemap,但要生成 sourcemap,不大需要 module 來映射回最初的源碼,所以可能是 hidden-source-map 這種。

開發的時候可以用 eval 的方式,這樣是每個模塊單獨做映射,不用從 bundle.js 開始映射,然後 cheap 也可以開啟,隻映射到源碼的某一行,提升生成速度,一般需要 module 來映射回最初的源碼,所以可能是 eval-cheap-module-source-map 這種。

當然,具體怎麼配置是按照需求來的,我們理解了每個基礎配置,知道怎麼組合就可以了。

不知道有沒有同學會覺得這樣寫比較麻煩,能不能每個基礎配置用 true、false 的方式配置呢?

确實可以,有這樣一個插件:SourceMapDevToolPlugin

它有很多 option,比如 module、columns、noSources 等:

相當于是 devtool 的另一種配置方式,啟用它需要把 devtool 設置為 false。

而且它可以控制更多東西,比如修改 sourcemap 的 url 和文件名等:

當你需要做更多的 sourcemap 生成方式的控制的時候,可以使用這個 webpack 插件。

總結

webpack 的 sourcemap 配置比較麻煩,但其實也是有規律的。

它是對一些基礎配置按照一定順序的組合,理解了每個基礎配置,知道了怎麼組合就理解了各種 devtool 配置。

eval:浏覽器 devtool 支持通過 sourceUrl 來把 eval 的内容單獨生成文件,還可以進一步通過 sourceMappingUrl 來映射回源碼,webpack 利用這個特性來簡化了 sourcemap 的處理,可以直接從模塊開始映射,不用從 bundle 級别。

cheap:隻映射到源代碼的某一行,不精确到列,可以提升 sourcemap 生成速度

source-map:生成 sourcemap 文件,可以配置 inline,會以 dataURL 的方式内聯,可以配置 hidden,隻生成 sourcemap,不和生成的文件關聯

nosources:不生成 sourceContent 内容,可以減小 sourcemap 文件的大小

module:sourcemap 生成時會關聯每一步 loader 生成的 sourcemap,配合 sourcemap-loader 可以映射回最初的源碼

理解了這些基礎配置項,根據 ^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$ 的規律來進行組合,就可以實現各種需求下的 sourcemap 配置。

當然,這種 sourcemap 配置還不夠細緻,比如 sourcemap 的 url 怎麼生成,文件名是什麼。如果想對這些做配置,可以關掉 devtool,啟用 SourceMapDevToolPlugin 來配置。

雖然 webapck 的 sourcemap 配置方式比較多,但最底層也就是浏覽器支持的文件級别的 sourcemap 還有 eval 代碼的 source 映射和 sourcemap 這兩種機制。其餘的方式都是基于這兩種機制的封裝。

理解了浏覽器 devtool的機制,webpack 封裝出的基礎配置,知道了組合規則,就可以應對各種需求的 sourcemap 配置。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved