webpack優化的一些基本方法

構建優化

一、 noParse(無需解析內部依賴的包)

對於咱們引入的一些第三方包,好比jQuery,在這些包內部是確定不會依賴別的包,因此根本不須要webpack去解析它內部的依賴關係,能夠在webpack配置文件中的module屬性下加上noParse屬性,它的值是一個正則表達式,用來匹配無需解析的模塊,這樣能夠節約webpack的打包時間,提升打包效率。css

module:{
    noParse:/jquery/
}
複製代碼

須要注意的是必須確保添加的包中沒有依賴別的包,不然會報依賴錯誤。 vue

二、DllPlugin(動態連接庫)

項目中依賴的一些第三方包好比reactvue通常狀況下包的內容不會發生改變,而每一次打包都要對它們進行構建顯然是不合理的,這會很浪費性能。正確的作法應該是將這些第三方包只打包一次,以後直接引用就能夠,直到第三方包須要更新版本時再從新進行構建。這樣咱們在打包的時候只須要構建咱們的業務代碼便可。react

Dllplugin插件能夠幫助咱們把這些不作修改的包抽取爲動態連接庫,而且會生成一個名爲manifest.json的文件,這個文件是用來讓DLLReferencePlugin映射到相關的依賴上去的。jquery

React爲例抽取Dllwebpack

  1. 首先建立一個將React抽取爲Dll的webpack配置文件webpack.react.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
  mode: 'development',
  // 入口文件:將要配置成Dll的庫放進來
  entry: {
    react: [
      'react'
    ]
  },
  // 輸出文件
  output: {
    // 輸出文件名
    filename: '[name]_dll.js',
    // 輸出文件路徑
    path: path.resolve(__dirname, '../dist'),
    // 將打包好的結果暴露在全局
    library: '[name]_dll'
  },
  plugins: [
    new webpack.DllPlugin({
      // dll文件名
      name: '[name]_dll',
      // 清單文件路徑
      path: path.resolve(__dirname, '../dist/mainfest.json')
    })
  ]
}
複製代碼
  1. 配置DllReferencePlugin

這個插件通常是在webpack的主配置文件中配置,在plugins配置下添加以下配置,manifest文件會將對dll文件的應用映射到模塊的id上,而後在須要的時候來引用Dll文件。web

new webpack.DllReferencePlugin({
  // (絕對路徑) manifest (或者是內容屬性)中請求的上下文
  context: __dirname,
  // 清單文件路徑
  manifest: path.resolve(__dirname, '../dist/manifest.json')
})
複製代碼
  1. 構建 而後運行webpack.react.js配置文件,通常狀況下能夠在package.json中添加運行腳本命令
scripts:{
    "build:react": "webpack --config ./build/webpack.react.js"
}
複製代碼

在命令行中運行該命令,這會在dist目錄下生成reactDll文件,還會生成一個mainfest.json文件,這個文件包含了importrequirerequest到模塊id的映射。DLLReferencePlugin也會引用這個文件。而後再進行打包,就不會對react重複打包,而是直接引用生成的react_dll文件。正則表達式

代碼優化

代碼優化的最終目的是爲了用戶體驗的優化,各類壓縮、拆分操做都應該圍繞最終目標展開。shell

一、webpack自帶優化

webpackmode設置爲production,進行生產模式打包的時候webapck會自動進行如下優化npm

  • tree shaking

webpack會在打包時移除引入了可是未引用的代碼,可是隻有經過ES6模塊系統中import語法引入的纔會適用tree shaking,減少生產環境下文件的體積,自動實現最基本的優化json

  • scope hoisting

分析模塊之間的依賴關係,會盡量的將打散的模塊合併到一個函數中去。須要注意的是這種優化方式也是隻有經過ES6模塊系統中import語法引入的模塊才適用,而且只有那些只被引用的一次的模塊纔有可能被合併。

  • 代碼壓縮

全部代碼自動使用UglifyJsPlugin進行壓縮。

二、CSS優化

  • 將CSS拆分爲獨立文件

mini-css-extract-plugin能夠將CSS拆分爲單獨的文件,使CSS文件能夠被異步加載,加快頁面加載呈現的速度。

使用方法:

  1. 安裝插件
$ npm i mini-css-extract-plugin -D
複製代碼
  1. 修改主配置文件,使用該插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
    ...,
    module: {
        rules: [
            ...,
            {
                test: /\.css$/,
                // 將原來多有使用style-loader來處理的地方替換爲使用MiniCssExtractPlugin.loader
                // use: ['style-loader', 'css-loader'],
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            }
        ]
    },
    plugins: [
        ...,
        new MiniCssExtractPlugin({
            // 生成的文件名
            filename: '[name].css'
        })
    ]
}
複製代碼
  • 壓縮CSS

optimize-css-assets-webpack-plugin插件能夠用來壓縮CSS文件,但使用該插件會致使webpack默認的js壓縮配置沒法生效,因此還須要手動對js代碼進行壓縮,js壓縮使用官方推薦的terser-webpack-plugin

使用方法:

  1. 安裝插件
$ npm i optimize-css-assets-webpack-plugin terser-webpack-plugin -D
複製代碼
  1. 修改主配置文件,使用該插件
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
    ...,
    optimization: {
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
    }
}
複製代碼

三、 JS優化

  • 拆分公共代碼

使用方法:只需在主配置文件中添加以下配置便可

Optimization: {
    splitChunks: {
        Chunks: 'all'
    }
}
複製代碼
  • IgnorePlugin(忽略插件)

有不少的第三方包內部會作國際化處理,包含不少的語言包,而這些語言包對咱們來講時沒有多大用處的,只會增大包的體積,咱們徹底能夠忽略掉這些語言包,從而提升構建效率,減少包的體積。

以moment爲例,首先找到moment中語言包所在的文件夾,而後在webpack配置文件中添加插件

// 該方法的兩個參數都是正則,第一個參數表示要忽略的路徑,第二個表示該資源所在目錄,在該文件夾下引入的語言包都會被忽略
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
複製代碼

這時候moment使用默認語言英語,若是要使用別的語言,能夠手動引入須要使用的語言包。

import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-CN')
複製代碼
  • 懶加載

在頁面中有一些代碼塊可能並非在頁面初始化的時候就須要使用的,須要用戶的某些操做出發纔會使用,若是用戶不觸發這個操做那這個代碼塊可能永遠不會被使用。咱們能夠將這些某個操做觸發纔會使用的代碼塊按需加載進來,而不是在頁面建立的時候直接加載,這樣能夠加快初始頁面的加載速度。

// 假設在頁面中有一個id爲btn的按鈕,當點擊這個按鈕的時候須要對時間進行操做
const btn = document.querySelector('#btn')
btn.onclick = e => import(/* webpackChunkName: "moment" */ 'moment').then(module => {
    var moment = module.default;
    moment().format('YYYY-MM-DD')
})
複製代碼

可是使用懶加載會影響用戶體驗,因此在懶加載的同時可使用魔法註釋:Prefetching,能夠在首頁資源加載完畢後,空閒時間時,將動態導入的資源加載進來,這樣便可以提升頁面加載速度又保證了用戶體驗。

const btn = document.querySelector('#btn')
btn.onclick = e => import(/* webpackChunkName: "moment" *//* webpackPrefetch: true */ 'moment').then(module => {
    var moment = module.default;
    moment().format('YYYY-MM-DD')
})
複製代碼

保持更新版本

webpack每次版本更新都會在性能上有很大提高,官方也推薦保持版本的更新。

相關文章
相關標籤/搜索