工程化-webpack篇

194 阅读1分钟

webpack中文文档:webpack.docschina.org/configurati…

1. 多入口配置?

webpack.common.js:

const srcPath = path.join(__dirname, '..', 'src')
const distPath = path.join(__dirname, '..', 'dist')

entry: {
  index: path.join(srcPath, 'index.js'),
  main: path.join(srcPath, 'main.js')
},
plugins: [
  new HtmlWebpackPlugin({
    template: path.join(srcPath, 'index.html'),
    filename: 'index.html',
    chunks: ['index']
  }),
  new HtmlWebpackPlugin({
    template: path.join(srcPath, 'main.html'),
    filename: 'main.html',
    chunks: ['main']
  })
]

webpack.prod.js

output: {
  filename: '[name].[contentHash:8].js',:index 、main
  path: path.join(__dirname, '..', 'dist'),
}

2. 如何抽离公共代码和第三方代码?

  • optimization.splitChunks进行分割代码块
  • optimization.splitChunks.cacheGroups做缓存分组:第三方模块、公共模块
optimization: {
  splitChunks: {
    chunks: 'all',
    // 缓存分组
    cacheGroups: {
      // 第三方模块
      vendor: {
        name: 'vendor',
        priority: 1, // 优先级
        test: /node_modules/,
        minSize: 1024,
        minChunks: 1
      },
      // 公共的模块
      common: {
        name: 'common',
        priority: 0,
        minSize: 1024,
        minChunks: 2 // 引用两次则抽离
      }
    }
  }
}

3. 性能优化-打包构建速度?

  • babel-loader优化
  • IgnorePlugin避免引入无用模块
  • noParse避免重复打包
  • happyPack多进程打包工具
  • ParalleUglifyPlugin多进程打包压缩
  • DLLPlugin
  • 热更新

(1) 优化babel-loader

webpack.dev.js:

module: {
  rules: [{
      test: /\.js$/,
      loader: ['babel-loader?cacheDirectory'],
      include: path.join(__dirname, '..', 'src'),
      exclude: /node_modules/
    },
  ]
}

(2) IgnorePlugin忽略无用模块

webpack.prod.js:

plugins: [
  new webpack.IgnorePlugin(/\.\/locale/, /moment/)
]

(3) noParse避免重复打包

如vue.min.js已经模块化处理过了,需要忽略对此类型文件的打包。

webpack.prod.js:

rules: [{
  test: /\.vue$/,
  loader: ['vue-loader'],
  include: path.join(__dirname, '..', 'src')
}]

IgnorePlugin vs noParse

  • IgnorePlugin直接忽略掉,减少了产出代码体积;
  • noParse不被打包;

(4) happyPack

js是单线程的,开启多线程打包,可提高构建速度(特别是多核CPU)

module: {
  rules: [{
    test: /\.js$/,
    use: ['happypack/loader?id=babel'],
    include: path.join(__dirname, '..', 'src'),
  }]
},
plugins: [
  new HappyPack({
    id: 'babel',
    loaders: ['babel-loader?cacheDirectory']
  })
]

(5) ParalleUglifyPlugin多进程压缩JS

  • 开发环境下没必要使用;
  • 项目大、打包慢,开启多进程能提高速度;
  • 项目小、打包快,开启多进程会降低速度;
plugins: [
  new ParallelUglifyPlugin({
    uglifyJS: {
      output: {
        beautify: false,
        comments: false
      },
      compress: {
        drop_console: true,
        collapse_vars: true,
        reduce_vars: true
      }
    }
  })
]

(6) DllPlugin

使用背景:

  • 前端框架如Vue、React,体积大,编译慢;
  • 较稳定,不常升级版本;
  • 同一个版本只需构建一次,不用每次都重新构建;

DLLPlugin将常用框架打包成dll文件再引用,webpack5已内置DLLPlugin支持:

step 1: DLLPlugin打包出dll文件:

<1> 单独配置webpack.dll.js,用于生成dll文件(DllPlugin插件):

const DllPlugin = require('webpack/lib/DllPlugin')

module.exports = {
  entry: {
    react: ['react', 'react-dom']
  },
  output: {
    filename: '[name].dll.js',
    path: path.join(__dirname, '..', 'dist'),
    library: '_dll_[name]'
  },
  plugins: [
    new DllPlugin({
      name: '_dll_[name]',
      path: path.join(distPath, '[name].manifest.json'),
    })
  ]
}

<2> 在package.json配置dll命令,并运行:npm run dll:

script: {
  "dll": "webpack --config ./build/webpack.dll.js"
}

step 2: DllReferencePlugin 使用 dll 文件:

<1> 配置webpack.dev.js:

const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')

module: {
  rules: [
    {
      test: /\.js$/,
      loader: ['babel-loader'],
      include: path.join(__dirname, '..', 'src'),
      exclude: /node_modules/
    }
  ]
}

<2> index.html 里引用 react.dll.js:

<script src="./react.dll.js"></script>

(7) 热更新

const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin')

// devServer.hot: true

entry: {
  index: [
    'webpack-dev-server/client?http://localhost:3000/',
    'webpack/hot/dev-server',
    path.join(srcPath, 'index.js')
  ],
  main: path.join(srcPath, 'main.js')
},
plugins: [new HotModuleReplacementPlugin()]

// main.js 入口文件 开启热更新之后的代码逻辑
if (module.hot) {
  module.hot.accept(['./test'], () => {
    console.log('test in hot...')
  })
}