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

<!-- 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默认支持的,不需要我们额外配置,使用方式: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
      }
    ]
  },
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容