Webpack系列笔记(四):webpack高级概念

文章目录

    • 三、Webpack 高级概念
      • 3.1 Tree Shaking
      • 3.2 Development 和 Production 模式的区分打包
      • 3.3 Webpack 和 Code Splitting

三、Webpack 高级概念

3.1 Tree Shaking

webpack在进行模块化打包的时候,会将模块中用得到的用不到的全部都打包,我们希望它只打包我们用到的,在 webpack2+ 引入了 Tree Shaking ,它可以帮我们把我们不需要的东西“从树上摇晃掉”。

注意: Tree Shaking 只支持 ES Module 的引入

在开发模式下,tree shaking 默认是关闭的,我们只需在 plugins 下方加入以下配置:

// webpack.config.js
module.exports = {
    mode: 'development', // 开发环境
    plugins: [...],
    optimization: {
      usedExports: true
    },
    output: {...}
}

如果某些模块你不想使用 tree shaking,可以在 package.json 中加入以下配置:

// package.json
{
  "sideEffects": ["@babel/polyfill", "*.css"], // 对@babel/polyfill和所有的css文件不使用Tree Shaking
}

3.2 Development 和 Production 模式的区分打包

开发环境和生产环境的打包需求是不一样的,例如开发环境我们想要让代码不压缩,而生产环境需要减小体积而要求代码压缩。因此,我们需要将 Development 和 production 模式区分打包。因为打包需求不同,因此每次打包我们都需要手动修改配置项来配置不同的打包模式,这样未免有些过于繁琐,我们可以通过一些配置项来简化这一步操作。

  • 复制一份 webpack.config.js,重命名为 webpack.dev.js
  • 重命名原文件 webpack.prod.js
  • 修改 webpack.prod.js 文件,将不必要的部分去掉,修改配置项
  • 在 package.json 中修改 scripts,指定配置文件
// package.json
"scripts": {
    "dev": "webpack-dev-server --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js"
}

运行不同的命令即可进行不同环境的打包。

接下来我们就要对这两个配置文件进行精简——将相同的配置合并到一个文件中。

  1. 新建一个文件 webpack.common.js

  2. 将 webpack.dev.js 和 webpack.prod.js 中公共的部分移到 webpack.common.js 中

  3. 安装 webpack-merge

    npm i webpack-merge -D
    
  4. 在 webpack.dev.js 和 webpack.prod.js 中引入 webpack-merge、webpack.common.js

  5. 使用 webpack-merge 合并 common 配置

我们可以将这三个文件放到一个文件夹里面(需要修改出口文件夹路径和配置文件路径),下面是我的目录结构以及详细配置

在这里插入图片描述

目录结构

webpack.dev.js:

const webpack = require('webpack');
const merge = require('webpack-merge');
const commonConfig = require('./webpack.common');

const devConfig = {
  mode: 'development', // 打包模式,默认是 production
  devtool: 'cheap-module-eval-source-map',
  devServer: {
    contentBase: './dist',
    open: true,
    hot: true, // 开启热模块替换
    hotOnly: true // 即使热模块替换不生效,浏览器也不自动刷新
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  optimization: {
    usedExports: true
  }
}

module.exports = merge(commonConfig, devConfig);

webpack.prod.js:

const merge = require('webpack-merge');
const commonConfig = require('./webpack.common');

const prodConfig = {
  mode: 'production', // 打包模式,默认是 production
  devtool: 'cheap-module-source-map'
}

module.exports = merge(commonConfig, prodConfig);

webpack.common.js:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: {
    main: './src/index.js', // 打包的入口文件,即打包 index.js 文件
  },
  module: {
    rules: [{
      test: /\.(png|jpg|gif)$/,
      use: {
        loader: 'url-loader',
        options: {
          // 这种配置语法叫做 placeholder, 占位符
          name: '[name].[ext]', // 打包后的文件名以及后缀不变
          outputPath: 'images/', // 打包后的图片文件会放到出口文件夹中的 images 文件夹下
          limit: 2048 // 当图片大小大于 2048bit,即大于2Kb时,url-loader就不会将图片转成base64字符串,而是单独生成一个文件,打包到出口文件夹下指定文件夹内
        }
      }
    }, {
      test: /\.css$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1
          }
        },
        'postcss-loader'
      ]
    },{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader',
      options: {
        presets: [['@babel/preset-env', {
          targets: {
            edge: "17",
            firefox: "60",
            chrome: "67",
            safari: "11.1",
          },
          useBuiltIns: 'usage'
        }]]
      } 
    }]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html'
    }), 
    new CleanWebpackPlugin()
  ],
  output: {
    filename: '[name].js', // 打包后的文件名
    path: path.resolve(__dirname, '../dist'), // 打包后的文件放在哪个文件夹内,这里必须是绝对路径
  }
}

package.json:

{
  "scripts": {
    "dev": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
  }
}

3.3 Webpack 和 Code Splitting

在一些项目中,我们经常对项目公用部分进行拆分,这就是 代码分割,这样做可以给用户更好的使用体验。

举个手动分割的栗子:在某个项目中使用了一个大小为 1MB 的第三方库,自己的业务逻辑代码也有 1MB

Webpack系列笔记(四):webpack高级概念_第1张图片

未进行代码分割

Webpack系列笔记(四):webpack高级概念_第2张图片

代码分割

webpack4 自带了一个代码分割插件,不用我们手动分割

只需在webpack的配置文件中加入一下配置项就可以最简单粗暴的代码分割了:

// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
}

split plugins 参数配置:

  • chunks:默认是 async,initial 同步代码分割,async 异步引入代码作分割,all 同步/异步都作分割
  • minSize:默认 30000,即当同步或异步js超过 30000字节即30 kb才做分割打包
  • maxSize:如果分割打包后的代码超过所设置的大小(字节),会尝试在打包后的基础上再做一次代码分割,直到小于所设置的大小
  • minChunks:默认 1,模块至少引用 1 次,才做代码分割
  • maxAsyncRequests:默认 5,如果需要分割的代码模块查过 5 个,只会分割打包前 5 个,超过 5 个就不会再打包了
  • maxInitialRequests:默认 3,入口文件如果做代码分割,最多做 3 个代码分割的js文件
  • automaticNameDelimiter:默认 ‘~’,打包文件生成的时候,中间会有一些连接符,默认的链接符是 ‘~’
  • name:默认 true,打包生成文件的名字取名有效(取 CacheGroups 里面的文件名有效)

你可能感兴趣的:(前端,webpack4)