項目中經常使用的webpack插件

本文原創:linqiumei、huoyinghuijavascript

不一樣項目,使用webpack版本不一樣,對應的插件也不一樣。css

如何查看項目中webpack的版本?

1.在package.json中的script腳本命令中,添加"webpack": "webpack --version",終端運行npm run webpackhtml

2.項目目錄的終端運行./node_modules/.bin/webpack –v前端

3.項目目錄的終端運行npx webpack -vvue

npx會自動查找當前依賴包中的可執行文件,找不到會在PATH中尋找,找不到,就會自動安裝。npm5.2起支持npxjava

webpack -v查詢的是全局環境中的webpack版本node

項目中webpack配置文件結構

1.webpack_config_node.png

webpack的重要屬性

entry: 定義入口文件jquery

output: 定義輸出文件webpack

module: 設置項目中不一樣類型模塊的處理方式es6

resolve: 設置模塊解析方式

plugins: 使用插件自定義webpack構建過程

webpack.base.js

2.base_entry_oputput.png

entry:
定義了webpack打包的入口文件
output:
-- path: 定義輸出文件存儲位置
-- publicPath: 用於配置異步加載/按需加載等線上資源的url前綴,默認爲空字符串,爲相對路徑;const publicPath = path.join('/account/')
-- filename: 定義打包資源輸出到path指定目錄位置的文件名
其中,[name]指代entry中鍵值對的鍵值,[hash]爲打包時會生成惟一的標誌符,指代打包過程,同一打包過程的文件hash是同樣的
-- chunkFilename: chunk是webpack進行模塊依賴分析時,代碼分割出來的代碼塊。用於配置沒有入口起點的代碼塊輸出的文件名
-- globalObject: 由於默認傳入的參數是window,可是umd書寫規範中,傳入的參數應該是this

3.base_module.png

module:
-- loader在module.rules中配置,如使用vue-loader加載vue文件,使用css-loader加載.css文件。

4.base_resolve.png

resolve:
-- extensions: 若是有多個文件有相同的名字,可是後綴名不一樣,webpack會按數組順序解析列在首位的文件,並跳過其餘後綴
-- alias: 別名,簡化模塊引入的代碼
-- symlinks: 是否將符號連接解析爲真實路徑,默認爲true

5.base_plugins.png

plugins
-- vueLoaderPlugin: 必須插件,將定義的其餘規則應用到.vue文件中相應語言塊。
-- HtmlWebpackPlugin: 簡化了HTML文件的建立
當使用webpack打包時,HtmlWebpackPlugin建立一個html文件,並把webpack打包後的靜態文件自動插入到html文件中。默認會在output.path目錄下建立一個index.html文件,並在文件中插入一個script標籤,src爲output.filename。css資源會包含在html頭部的link標記中。
6.base_htmlWebpackPlugin1.png

-- DllReferencePlugin: 配合DllPlugin使用,webpack.dll.js中生成manifest.json文件,DllReferencePlugin打包時,不會打包manifest.json中的文件,而是使用相應的全局函數處理,用於提升構建速度。如第三方庫vue、vue-loader等打包
-- DefinePlugin: 能夠在編譯時定義全局變量,打包的時候對這些變量進行替換

7.base_DefinPlugin.png

webpack.dll.js

將第三方庫依賴打包到一個單獨的dll文件目錄下,並生成manifest.json文件

8.dll.png

optimization
-- minimize: 是否壓縮
plugins
-- ProvidePlugin: 每當vue做爲自由變量時,模塊會自動用已加載vue的內容填充模塊
-- CleanWebpackPlugin: 用於npm run dll時,清除以前打包的文件
-- AssetsPlugin: 生成一個記錄版本號的文件
-- DllPlugin: 將第三方庫代碼分離,每次文件更改的時候,只打包項目自身的代碼。將vue、vue-router第三方庫單獨打包

webpack.dev.js

9.dev.png

plugins:
-- HotModuleReplacementPlugin: 熱加載模塊,不能用於生產環境,由於watch狀態消耗性能,生產環境中,代碼穩定,更新概率小

webpack.prod.js

10.prod.png

devtool:
控制是否生成以及如何生成source map,有助於定位代碼錯誤位置
performance:
展現性能提示,當加載影響性能的資源時,能夠輸出一個警告提醒。warning、error、 false
optimization:
-- minimizer: 用於壓縮js文件,不支持es6語法
-- uglifyjs-webpack-plugin: 用於壓縮js文件,不支持es6語法,可用terser-webpack-plugin替代
-- OptimizeCssAssetsPlugin: 用於優化css文件的輸出,擯棄重複樣式,去除樣式規則中的多餘參數,移除沒必要要的瀏覽器前綴等。autoprefixer是否去除瀏覽器前綴
plugins:
-- MiniCssExtractPlugin: 將css提取到單獨的文件中,並支持按需加載
-- DefinePlugin: 定義全局變量
-- hashedModuleIdsPlugin: 根據模塊的相對路徑,生成四位數的hash做爲模塊id,用於生產環境。
-- CleanWebpackPlugin: 清除打包內容:verbose: 是否將日誌輸出到控制檯,默認爲false;dry: 默認爲false,爲true的時候,模擬刪除,不會真的刪除文件;exclude: 忽略不用刪除的文件
-- CopyWebpackPlugin: 將單個文件或整個目錄複製到構建目錄中

webpack5


首先能夠看一下當前webpack5的開發進度

picture1.png

相較於webpack4,webpack5有了很大的變化,先簡單列舉一下新舊版本的幾個不一樣點:

  1. webpack5清除webpack4標記即將過時的功能
  2. 經過持久緩存提升構建性能cache
  3. 肯定性chunkId和moduleId,優化長期緩存
  4. 更好的Tree Shaking
  5. 支持生成es6/es2015的代碼
  6. SplitChunk配置優化

清除webpack4標記即將過時的功能點就先掠過,其他幾點下面咱們一一介紹。

經過持久緩存提升構建性能

首先說明cache在構建中的做用,cache在首次打包構建項目時,會將編譯結構緩存起來,二次構建時,會根據緩存判斷當前哪些已經構建過而且沒有改動,這些文件就不會被從新編譯,從而減小項目構建時間。

在webpack4中,cache是這樣設置的:

cache: true // 或false
複製代碼

經過cache-loader將編譯結構寫入硬盤緩存或者採用babel-loader並配置option.cacheDirectory將編譯結果寫入磁盤

而在webpack5中對cache作了升級,緩存默認是開啓狀態,緩存的文件存於內存中,咱們也能夠配置緩存的類型及存儲的位置:

cache: {
    type: 'filesystem’, cacheDirectory: path, cacheLocation: path + name, buildDependencies: { config: [__filename], }, } 複製代碼

以上幾個屬性的含義能夠簡單理解爲:

type: 緩存類型,值爲 'memory'或‘filesystem’,分別表明基於內存的臨時緩存,以及基於文件系統的持久化緩存。

cacheDirectory: 緩存目錄,默認目錄爲 node_modules/.cache/webpack,也能夠自定義設置

name: 緩存名稱,同時也是 cacheDirectory 中的子目錄命名,默認值爲 Webpack配置中 的 c o n f i g . n a m e {config.name}- {config.mode}

cacheLocation: 緩存真正的存放地址, path.resolve(cache.cacheDirectory, cache.name), 該屬性在賦值狀況下將忽略 cacheDirectory 和 name 屬性

優化長期緩存

咱們都知道,webpack基本配置會有入口文件,相似的設置以下:

entry:{
    app: './index.js'// 入口
},
output:{
    filename:'./bundle.js'// 出口
}
複製代碼

可是有不少文件是不會配置entry的,這些未從entry打包的chunk文件,都會以0,1,2,3…加chunkhash的文件命名方式輸出。這樣就引起了一些問題,舉個例子:

假設咱們打包了page0.js、page1.js、page2.js,打包後的文件名暫時稱爲1.js、2.js、3.js,這樣使用是不會有任何問題的,但如今若是咱們刪除或者暫時不使用1.js後,原來的2.js會變爲1.js,3.js會變爲2.js,此時再引用2.js就不對了,這就是出現了緩存失效問題。

出現的這種問題,目前有解決方案,就是使用import(/* webpackChunkName: 「home」 */ ‘./home’)這種魔術式註釋來給打包文件命名,雖然命名問題解決了,但是打開文件內容會發現,chunkId仍然發生了變化。

page1.js第一次打包時的chuankId:

14.page_chunkId_1.png

page1.js第二次打包後的chunkId:

15.page_chunkId_2.png

那麼webpack5是怎麼解決的呢

在webpack5中,有肯定的 chunkId、moduleId 以及導出名稱,生產模式下,默認是啓用chunkIds、 moduleIds的,具體是以肯定性的方式爲模塊和分塊分配短的(3 或 5 位)數字 ID,使得生成的緩存失效頻率下降,配置能夠這樣寫:

optimization: {
	  chunkIds: "deterministic", // 顧名思義,deterministic爲肯定性的
    moduleIds: "deterministic"
}
複製代碼

固然,chunkIds和moduleIds還有其餘的配置選項

moduleId:

optimization 選項值
false 告訴webpack不該使用任何內置算法, 經過插件提供自定義算法
natural 按使用順序的數字ID,沿用v4數值命名
named 方便調試的高可讀性id,文件命名
deterministic 根據**模塊路徑**生成簡短的hash值
size 根據模塊大小生成的數字id,沿用v4

chunkId:

optimization 選項值
false 告訴webpack不該使用任何內置算法, 經過插件提供自定義算法
natural 按使用順序的數字ID,沿用v4數值命名
named 方便調試的高可讀性id,文件命名
deterministic 根據代碼**塊內容**決定,注意與moduleId的此選項區分
totalSize 根據請求到的解析資源size計算的id

減少Bundle體積

  1. 分析導入導出模塊之間的依賴關係

webpack能夠經過優化配置選項中的innerGraph啓用模塊依賴,具體以下:

optimization: {
		innerGraph: true
}
複製代碼

依賴圖的好處是能夠理清各個模塊之間從export到import是怎樣的引用關係,webpack對模塊中的符號進行分析以找出從export到import的依賴關係,舉個🌰:(內部依賴圖能夠記錄到當前文件引用了something模塊)

import {something} from './something'
function usingSomething() {
    return something;
}
export function test() {
     return usingSomething();
}
複製代碼
  1. 嵌套tree-shaking

Tree-shaking,翻譯過來就是樹搖,一個文件就是一棵樹,會有主幹和分支,也會有葉子,若是樹被晃動,就會有葉子落下。tree-shaking就是將文件中不須要的代碼刪除掉,用來減少文件的體積,在webpack5中,不只能夠作到搖無用代碼,還能夠嵌套查詢是否有無用代碼從而進行刪除。

首先作這樣的配置:

optimization: {
    sideEffects: false,
    usedExports: true
}
複製代碼
// inner.js
export const a = 1;
export const b = 2;

// module.js
import * as inner from './inner'
export {inner}

// user.js
import * as module from './module';
console.log(module.inner.a);
複製代碼

經過內部模塊依賴圖,檢測到inner.js中的常量 b 沒有被使用,就會將其刪除掉,是否是很膩害:happy:

注意!tree-shaking雖然在減少文件體積方面作的很到位,但使用需謹慎,要保證被刪除的代碼沒有反作用才行,由於只要是沒有使用到的文件,都會被搖掉,那若是有些文件不使用也不想被優化呢,好比須要寫一個組件,但在庫裏沒有使用它,這就有可能在打包時被優化掉了。

SplitChunk配置優化

splitChunk是webpack優化配置中的一個配置項,能夠將Node Modules中代碼單獨打包成一個chunk最終輸出,配置成功的話,能夠自動分析多入口chunk中,有沒有公共的文件,若是有,就會打包成一個單獨的chunk。

先在index文件裏引入jquery庫,簡單寫兩行代碼:

import $ from 'jquery'

function sum(...args) {
  return args.reduce((a, b) => a + b, 0)
}
console.log(sum(1,2,3,4))
複製代碼

看一下不配置splitChunk的打包狀況:

17.splitchunk_2.png

18.splitchunk_3.png

看第一張圖,index.js中只寫了幾行代碼,但體積卻有852KiB,從第二張圖能夠獲得答案,就是webpack將jquery和index中的代碼打包到了一個文件裏。

接下來配置一下splitchunk:

optimization: {
  splitChunks: {
    chunks: 'all',
    minSize: {// webpack5以前只能夠設置 minSize: size
      javaScript: 2000,
      style: 10000
    }
  }
}
複製代碼

splitchunk不是webpack5纔有的屬性,但minSize的細化配置是webpack5升級的,能夠在其中配置單獨打包文件知足的條件,好比javaScript: 2000,若是文件體積小於2000,是不會單獨抽離出來打包的。

再來看下一樣代碼的打包狀況:

20.splitchunk_5.png

能夠看到,第三方組件庫被單獨打包了,雖然一個文件引用了jquery庫,表現的做用不明顯,但若是多個文件都引用了這個庫,做用就很明顯了,一個是每一個文件中都會打包jquery,一個是jquery只打包一份。

webpack使用遇到的問題


1.本地綁定localhost.jd.com域名,而後經過綁定域名訪問項目,可是頁面會報Invalid Host header,以下圖所示

21.problem_one.png

問題緣由:新版的webpack-dev-server增長了安全驗證,默認檢查hostname,若是hostname不是配置內的,將中斷訪問。

解決方法:在webapck配置中找到devServer配置項,添加{disableHostCheck: true},而後重啓項目便可,如圖

solutionOne.png

2.debug模式啓動項目報找不到localhost

問題緣由: 本地代理時,沒有指定本地host

解決方案:在host配置中添加上本地迴環地址127.0.0.1 localhost的映射,例如: 127.0.0.1 localhost.test.com

3.設置div超出兩行顯示省略號,但由於css樣式中有瀏覽器前綴,線上打包會將前綴去掉致使樣式失效。

問題緣由:webpack.prod.js文件配置壓縮時,引入了OptimizeCSSAssetsPlugin插件,這個插件默認會將瀏覽器前綴去掉

解決方案:爲該插件設置參數autoprefixer爲false


歡迎計算機前端相關領域小夥伴加入咱們,具體的招聘信息可進入公衆號查看,歡迎關注。

關注咱們吧.jpg

相關文章
相關標籤/搜索