webpack5 高級配置

雖然在日常開發(fā)中,我們使用vuereact框架,它們的腳本架vue-clireact-react-app會幫我們配置最基本的webpack,但我們了解webpack的一些配置,會讓我們在需要特定個(gè)性化配置時(shí)不至于手忙腳亂,能夠做進(jìn)一步優(yōu)化操作等。

vue-cli中,要查看webpack的默認(rèn)配置,可以在項(xiàng)目中使用vue inspect命令查看;
react-react-app 中,使用npm run eject將內(nèi)建的webpack文件都暴露出來

這篇將進(jìn)一步介紹webpack5一些高級配置:

  1. 多入口文件配置:entry + output + html-webpack-plugin
  2. css文件抽離和壓縮:
    • 抽離:mini-css-extract-plugin
    • 壓縮:terser-webpack-plugin + optimize-css-assets-webpack-plugin
  3. 抽離公共代碼和第三方代碼:splitChunks
  4. 懶加載:import('xxx.js').then(res => {...})
  5. 識別.jsx@babel/preset-react
  6. 識別.vuevue-loader

多入口文件配置

  1. 修改入口文件,改為對象形式
// webpack.common.js
// entry: path.join(srcPath, 'index'),
  entry: {
    index: path.join(srcPath, 'index.js'),
    other: path.join(srcPath, 'other.js') 
  },
  1. 修改要輸出的模板配置,一般有多少個(gè)入口,就會設(shè)多少個(gè)出口模板,注意要寫上不同的filename,chunks是個(gè)數(shù)組,用來說明引入哪些chunk,如果不寫,會默認(rèn)引入所有入口文件
// webpack.common.js
  plugins: [
    require('autoprefixer'),
    new CleanWebpackPlugin(), // 清除之前的打包文件
    new htmlWebpackPlugin({
      // template: 'index.html',
      template: path.join(rootPath, 'index.html'),
      // 在這里還可以自定義參數(shù),在模板中,使用ejs方式 <%= htmlWebpackPlugin.options %>獲取自定義屬性
      title: 'webpack multi demo1',
      filename: 'index.html',
      // 指明要引用哪些chunk,如不指定,會默認(rèn)引用所有入口文件
      chunks: ['index'] // 只引用index.js
    }),
    new htmlWebpackPlugin({
      template: path.join(rootPath, 'other.html'),
      filename: 'other.html',
      title: 'webpack multi demo2',
      chunks: ['other'] // 指明引用other.js入口文件

    })
  ]
  1. 修改出口文件
    設(shè)置動(dòng)態(tài)的[name],用于匹配入口文件設(shè)置的文件名
// webpack.prod.js
output: {
    // filename: 'bundle.[chunkhash].js', 
    filename: '[name].[chunckhash:8].js',  // 從寫死改為以入口文件命名
    path: path.join(__dirname, '..', 'dist')  // 輸出目錄
  }

抽離并壓縮css

  1. 抽離
    上一篇已經(jīng)說明如何使用mini-css-extract-plugin來抽離css文件,抽離的好處是,當(dāng)只改變js文件時(shí),css文件因?yàn)?code>hash沒變,所以可以使用緩存,而不需要重新加載,訪問速度會快一些
// webpack.prod.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader']
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name]-[contenthash].css'
    })
  ]

打包出來的css文件如下:

body {
  background-color: yellow;
  opacity: 0.7;
  /* transform: rotate(45deg); */
  /* background: url('../imgs/img002.jpg'); */
}
.test {
  font-size: 18px;
  font-weight: bold;
}
  1. 壓縮
    單抽離是不夠的,我們在生產(chǎn)環(huán)境中還需要對其進(jìn)行壓縮,并盡可能讓打包的資源體積小,這也是加快速度的一種手段
    • 安裝:npm i terser-webpack-plugin optimize-css-assets-webpack-plugin -D
    • 配置
// webpack.prod.js
const TerserWebpackPlugin = require('terser-webpack-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const prodConfig = {
  // ...
  optimization: {
    minimizer: [new TerserWebpackPlugin({}), new OptimizeCssAssetsWebpackPlugin()]
  }
}

打包后,可以看到css文件被壓縮了,且注釋被去掉了

body{background-color:#ff0;opacity:.7}.test{font-size:18px;font-weight:700}

抽離公共代碼和第三方代碼

a文件引入了c文件,b也引入了c文件,那么在打包這a和b這兩文件時(shí),都要分別引入c文件,這操作不僅冗余,而且還浪費(fèi)性能,當(dāng)c文件很大時(shí),這個(gè)問題就越加明顯。

我們希望c文件只引入一次,就可以在多個(gè)文件中使用,這就是我們說的公共代碼

第三方代碼指代的,它一般是指我們安裝引入的第三方庫,引入了后基本就不會變了,所以要與我們的業(yè)務(wù)代碼分離開來,這樣,我們修改業(yè)務(wù)代碼時(shí),第三方代碼的文件不會改變,從而可以命中緩存,加快加載速度。

抽離公共代碼和第三方代碼的配置,也比較簡單,就是在optimization中添加splitChucks的配置,可以看到,在webpack5除了入口文件外,已經(jīng)實(shí)現(xiàn)基本的按需引入,不需要我們在入口文件中再手動(dòng)設(shè)置指定的chunks

// webpack.prod.js
  optimization: {
    minimizer: [new TerserWebpackPlugin({}), new OptimizeCssAssetsWebpackPlugin()],
    splitChunks: {
      chunks: 'all', // 表示要分割的chunk類型:initial只處理同步的; async只處理異步的;all都處理
      // 緩存分組
      cacheGroups: {
        // 第三方模塊
        verdors: {
          name: 'verdor', // chunk名稱
          test: /node_modules/,  // 設(shè)置命中目錄規(guī)則
          priority: 1, // 優(yōu)先級,數(shù)值越大,優(yōu)先級越高
          minSize: 0, // 小于這個(gè)大小的文件,不分割
          minChunks: 1 // 最少復(fù)用幾次,這里意思是只要用過一次就分割出來
        },
        // 公共模塊
        common: {
          name: 'common',
          minChunks: 2,
          priority: 0,
          minSize: 0,
          minChunks: 2  // 只要引用過2次,就分割成公共代碼
        }
      }
    }
  }

設(shè)置兩個(gè)入口文件

// index.js
import _ from 'lodash'
import { sum } from './common/math'
console.log(sum(1,2))
console.log(_.each)

// other.js
import { sum } from './common/math'
console.log(sum(3,4))
  plugins: [
    new htmlWebpackPlugin({
      template: path.join(rootPath, 'index.html'),
      title: 'webpack multi demo1',
      filename: 'index.html',
      chunks: ['index'] // 引入index.js
    }),
    new htmlWebpackPlugin({
      template: path.join(rootPath, 'other.html'),
      filename: 'other.html',
      title: 'webpack multi demo2',
      chunks: ['other'] // 指明引用other.js入口文件
    })
  ]

打包后,輸出模板中:
index.html引入了verdor,common,index

<!-- index.html -->
<script defer="defer" src="verdor.ab38c0e4.js"></script>
<script defer="defer" src="common.1be3f0b4.js"></script>
<script defer="defer" src="index.632b90fb.js"></script>

other.html中引入了common.jsother.js

<!-- other.html -->
<script defer="defer" src="common.1be3f0b4.js"></script>
<script defer="defer" src="other.cea083a6.js"></script>

懶加載

懶加載是webpack默認(rèn)支持的,不需要我們額外配置,使用方式:import('xxxx')

// common/dynamicData.js
export default {
  msg: 'dynamic data'
}

// index.js
setTimeout(() => {
  // 直接使用import導(dǎo)入即可,這樣加載的模塊,相當(dāng)于一個(gè)獨(dú)立的chunk存在
  import('./common/dynamicData.js').then(res => {
    console.log(res.default.msg);
  })
}, 1000)

解析.jsx

  • 安裝: npm i @babel/preset-react -D
  • 在根目錄下創(chuàng)建.babelrc
{
  "presets": ["@babel/preset-react"]
}

解析.vue

  • 安裝:npm i vue-loader -D
  • 配置:
// webpack.common.js
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: ['vue-loader'],
        include: srcPath
      }
    ]
  },
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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