webpack5 高级配置

虽然在日常开发中,我们使用vuereact框架,它们的脚本架vue-clireact-react-app会帮我们配置最基本的webpack,但我们了解webpack的一些配置,会让我们在需要特定个性化配置时不至于手忙脚乱,能够做进一步优化操作等。

vue-cli中,要查看webpack的默认配置,可以在项目中使用vue inspect命令查看;
react-react-app 中,使用npm run eject将内建的webpack文件都暴露出来

这篇将进一步介绍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. 修改要输出的模板配置,一般有多少个入口,就会设多少个出口模板,注意要写上不同的filenamechunks是个数组,用来说明引入哪些chunk,如果不写,会默认引入所有入口文件
// webpack.common.js
  plugins: [
    require('autoprefixer'),
    new CleanWebpackPlugin(), // 清除之前的打包文件
    new htmlWebpackPlugin({
      // template: 'index.html',
      template: path.join(rootPath, 'index.html'),
      // 在这里还可以自定义参数,在模板中,使用ejs方式 <%= htmlWebpackPlugin.options %>获取自定义属性
      title: 'webpack multi demo1',
      filename: 'index.html',
      // 指明要引用哪些chunk,如不指定,会默认引用所有入口文件
      chunks: ['index'] // 只引用index.js
    }),
    new htmlWebpackPlugin({
      template: path.join(rootPath, 'other.html'),
      filename: 'other.html',
      title: 'webpack multi demo2',
      chunks: ['other'] // 指明引用other.js入口文件

    })
  ]
  1. 修改出口文件
    设置动态的[name],用于匹配入口文件设置的文件名
// webpack.prod.js
output: {
    // filename: 'bundle.[chunkhash].js', 
    filename: '[name].[chunckhash:8].js',  // 从写死改为以入口文件命名
    path: path.join(__dirname, '..', 'dist')  // 输出目录
  }

抽离并压缩css

  1. 抽离
    上一篇已经说明如何使用mini-css-extract-plugin来抽离css文件,抽离的好处是,当只改变js文件时,css文件因为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. 压缩
    单抽离是不够的,我们在生产环境中还需要对其进行压缩,并尽可能让打包的资源体积小,这也是加快速度的一种手段
    • 安装: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这两文件时,都要分别引入c文件,这操作不仅冗余,而且还浪费性能,当c文件很大时,这个问题就越加明显。

我们希望c文件只引入一次,就可以在多个文件中使用,这就是我们说的公共代码

第三方代码指代的,它一般是指我们安装引入的第三方库,引入了后基本就不会变了,所以要与我们的业务代码分离开来,这样,我们修改业务代码时,第三方代码的文件不会改变,从而可以命中缓存,加快加载速度。

抽离公共代码和第三方代码的配置,也比较简单,就是在optimization中添加splitChucks的配置,可以看到,在webpack5除了入口文件外,已经实现基本的按需引入,不需要我们在入口文件中再手动设置指定的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/,  // 设置命中目录规则
          priority: 1, // 优先级,数值越大,优先级越高
          minSize: 0, // 小于这个大小的文件,不分割
          minChunks: 1 // 最少复用几次,这里意思是只要用过一次就分割出来
        },
        // 公共模块
        common: {
          name: 'common',
          minChunks: 2,
          priority: 0,
          minSize: 0,
          minChunks: 2  // 只要引用过2次,就分割成公共代码
        }
      }
    }
  }

设置两个入口文件

// 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





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




懒加载

懒加载是webpack默认支持的,不需要我们额外配置,使用方式:import('xxxx')

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

// index.js
setTimeout(() => {
  // 直接使用import导入即可,这样加载的模块,相当于一个独立的chunk存在
  import('./common/dynamicData.js').then(res => {
    console.log(res.default.msg);
  })
}, 1000)

解析.jsx

  • 安装: npm i @babel/preset-react -D
  • 在根目录下创建.babelrc
{
  "presets": ["@babel/preset-react"]
}

解析.vue

  • 安装:npm i vue-loader -D
  • 配置:
// webpack.common.js
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: ['vue-loader'],
        include: srcPath
      }
    ]
  },

你可能感兴趣的:(webpack5 高级配置)