【打包工具】webpack基础

Webpack 基础教程

  • [1. 基础概念](#1. 基础概念)
    • [1.1 核心概念](#1.1 核心概念)
  • [2. 开发环境配置](#2. 开发环境配置)
    • [2.1 打包资源(样式,html,图片,其他)](#2.1 打包资源(样式,html,图片,其他))
      • [2.1.1 样式处理](#2.1.1 样式处理)
      • [2.1.2 HTML处理](#2.1.2 HTML处理)
      • [2.1.3 图片处理](#2.1.3 图片处理)
      • [2.1.4 其他资源处理](#2.1.4 其他资源处理)
    • [2.2 devServer](#2.2 devServer)
      • [2.2.1 Webpack5 重要更新](#2.2.1 Webpack5 重要更新)
      • [2.2.2 旧版配置](#2.2.2 旧版配置)
    • [2.3 CSS处理](#2.3 CSS处理)
      • [2.3.1 处理成单独文件](#2.3.1 处理成单独文件)
      • [2.3.2 CSS兼容性处理](#2.3.2 CSS兼容性处理)
      • [2.3.3 压缩CSS](#2.3.3 压缩CSS)
    • [2.4 ESLint](#2.4 ESLint)
    • [2.5 JS兼容性处理](#2.5 JS兼容性处理)
    • [2.6 压缩HTML和JS代码](#2.6 压缩HTML和JS代码)
  • [3. 生产环境配置](#3. 生产环境配置)
    • [3.1 性能优化](#3.1 性能优化)
    • [3.2 HMR(热模块替换)](#3.2 HMR(热模块替换))
      • [3.2.1 开启热更新](#3.2.1 开启热更新)
      • [3.2.2 不同文件类型的HMR支持](#3.2.2 不同文件类型的HMR支持)
    • [3.3 source-map](#3.3 source-map)
      • [3.3.1 属性说明](#3.3.1 属性说明)
      • [3.3.2 各类型区别](#3.3.2 各类型区别)
      • [3.3.3 内联和外部区别](#3.3.3 内联和外部区别)
      • [3.3.4 选择建议](#3.3.4 选择建议)
    • [3.4 OneOf](#3.4 OneOf)
    • [3.5 缓存](#3.5 缓存)
      • [3.5.1 Babel缓存](#3.5.1 Babel缓存)
      • [3.5.2 文件资源缓存](#3.5.2 文件资源缓存)
      • [3.5.3 文件资源缓存hash值说明](#3.5.3 文件资源缓存hash值说明)
    • [3.6 tree shaking](#3.6 tree shaking)
    • [3.7 code split](#3.7 code split)
      • [3.7.1 单入口和多入口](#3.7.1 单入口和多入口)
      • [3.7.2 依赖单独打包](#3.7.2 依赖单独打包)
      • [3.7.3 通过js代码将某个文件单独打包成一个chunk](#3.7.3 通过js代码将某个文件单独打包成一个chunk)
    • [3.8 懒加载和预加载](#3.8 懒加载和预加载)
    • [3.9 PWA](#3.9 PWA)
      • [3.9.1 注册serviceworker](#3.9.1 注册serviceworker)
      • [3.9.2 注意事项](#3.9.2 注意事项)
    • [3.10 多进程打包](#3.10 多进程打包)
      • [3.10.1 设置多线程打包数量](#3.10.1 设置多线程打包数量)
    • [3.11 externals](#3.11 externals)
      • [3.11.1 函数形式](#3.11.1 函数形式)
    • [3.12 dll](#3.12 dll)
      • [3.12.1 webpack.dll.js配置](#3.12.1 webpack.dll.js配置)
      • [3.12.2 webpack.config.js中使用](#3.12.2 webpack.config.js中使用)
  • [4. 优化环境配置](#4. 优化环境配置)
    • [4.1 性能优化总结](#4.1 性能优化总结)
      • [4.1.1 开发环境性能优化](#4.1.1 开发环境性能优化)
      • [4.1.2 生产环境性能优化](#4.1.2 生产环境性能优化)
  • [5. Webpack配置详解](#5. Webpack配置详解)
    • [5.1 entry](#5.1 entry)
      • [5.1.1 Webpack Entry 入口起点配置说明](#5.1.1 Webpack Entry 入口起点配置说明)
        • [5.1.1.1 String 字符串形式](#5.1.1.1 String 字符串形式)
        • [5.1.1.2 Array 数组形式](#5.1.1.2 Array 数组形式)
        • [5.1.1.3 Object 对象形式](#5.1.1.3 Object 对象形式)
        • [5.1.1.4 特殊用法说明](#5.1.1.4 特殊用法说明)
    • [5.2 output](#5.2 output)
    • [5.3 module](#5.3 module)
    • [5.4 resolve](#5.4 resolve)
    • [5.5 devserver](#5.5 devserver)
    • [5.6 optimization](#5.6 optimization)
      • [5.6.1 splitChunks](#5.6.1 splitChunks)
      • [5.6.2 runtimeChunk](#5.6.2 runtimeChunk)
      • [5.6.3 minimizer](#5.6.3 minimizer)

1. 基础概念

1.1 核心概念

  • Entry
    • 以哪个文件为起点
  • Output
    • 打包的资源输出到哪,以及命名
  • Loader
    • 处理非JavaScript文件
  • Plugins
    • 用于执行范围更广的任务。包括打包优化,压缩,一直到重新定义环境变量等
  • Mode
    • 两个值:development/production,对应本地和生产环境
    • 区别:
      1. process.NODE_ENV的值不同,为设置的mode值
      2. 设置不同:production会启用一些生产环境的插件

2. 开发环境配置

2.1 打包资源(样式,html,图片,其他)

2.1.1 样式处理

javascript 复制代码
module: {
  rules: [
    {
      test: /\.css$/,
      // loader 从右到左执行
      // style-loader 创建style标签,将js中的样式插入到style标签中,添加到head中
      // css-loader 将css文件变成commonjs模块加载到js中,里面内容是css字符串
      use: ['style-loader', 'css-loader'],
    },
    {
      // less-loader 将less文件编译为css文件
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'less-loader'],
    }
  ]
}

2.1.2 HTML处理

javascript 复制代码
const HTMLWebpackPlugin = require('html-webpack-plugin');

plugins: [
  new HTMLWebpackPlugin({
    template: './src/index.html',
  }),
],

2.1.3 图片处理

javascript 复制代码
module: {
  rules: [
    // 处理图片资源
    {
      test: /\.(png|jpg|jpeg|gif|svg)$/,
      // url-loader和file-loader功能类似,url-loader会调用file-loader
      loader: 'url-loader',
      options: {
        // 当图片小于8192字节时,将图片转换为base64编码,否则会转换为文件
        // 好处:减少请求数量
        // 坏处:图片体积会变大,因为base64编码的图片体积会变大
        limit: 8192,
        // 解决图片引入问题
        // 默认是true,表示是commonjs模块,会通过require方式引入
        // 如果设置为false,表示是es模块,会通过import方式引入
        esModule: false,
        // 输出文件名
        // [hash:8]:8位hash值
        // [ext]:文件扩展名
        name: '[hash:8].[ext]',
      },
    },
    {
      // 处理html文件中的图片
      test: /\.html$/,
      loader: 'html-loader',
    }
  ]
},

2.1.4 其他资源处理

javascript 复制代码
module: {
  rules: [
    // 打包其他资源
    {
      exclude: /\.(js|css|html|less)$/,
      loader: 'file-loader',
      options: {
        name: '[hash:8].[ext]',
      },
    }
  ]
},

2.2 devServer

2.2.1 Webpack5 重要更新

webpack5的devServer的contentBase属性改为了static/directory。示例:

javascript 复制代码
devServer: {
  static: {  // 服务器所加载文件的目录
    directory: path.join(__dirname, 'dist'),
  },
  compress: true,
  port: 8080,
  // 热更新
  hot: true,
},

2.2.2 旧版配置

javascript 复制代码
// 只会在内存中编译,不会生成文件
// 启动命令: npx webpack-dev-server
devServer: {
  // 打包后的资源目录
  contentBase: resolve(__dirname, 'dist'),
  // 压缩
  compress: true,
  // 端口
  port: 3000,
  // 自动打开浏览器
  open: true,
},

2.3 CSS处理

2.3.1 处理成单独文件

javascript 复制代码
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
import HTMLWebpackPlugin from 'html-webpack-plugin';

module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        // MiniCssExtractPlugin.loader取代style-loader。作用:提取js中的css成单独文件
        MiniCssExtractPlugin.loader, 
        // 将css整合到js文件中
        'css-loader'
      ],
    },
  ],
},
plugins: [
  new HTMLWebpackPlugin({
    template: './src/index.html',
    filename: 'index.html',
  }),
  new MiniCssExtractPlugin({
    filename: 'css/main.css',
  }),
],

2.3.2 CSS兼容性处理

通过postcss-loader和postcss-preset-env

javascript 复制代码
// package.json中
"browserslist": {
  "production": [
    "> 0.2%",
    "not dead",
    "not op_mini all"
  ],
  "development": [
    "last 1 chrome version",
    "last 1 firefox version",
    "last 1 safari version"
  ]
}

// webpack.config.js中
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
    clean: true,
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: ["postcss-preset-env"],
              },
            },
          },
        ],
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      filename: "index.html",
    }),
    new MiniCssExtractPlugin({
      filename: "css/index.css",
    }),
  ],
  mode: "development",
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    compress: true,
    port: 8080,
  },
};

2.3.3 压缩CSS

javascript 复制代码
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");

plugins: [
  new OptimizeCssAssetsPlugin(),
],

2.4 ESLint

安装eslint eslint-loader eslint-config-airbnb-base eslint-plugin-import

javascript 复制代码
// package.json中
"eslintConfig": {
  "extends": "airbnb-base"
}

// webpack.config.js中
module: {
  rules: [
    {
      test: /\.js$/,
      loader: "eslint-loader",
      exclude: /node_modules/,
      options: {
        // 自动修复eslint的错误
        fix: true,
      },
    }
  ],
},

2.5 JS兼容性处理

安装插件:babel-loader @babel/core @babel/preset-env

  1. 基本 JS 兼容性处理 → @babel/preset-env

    问题:只能转换基本语法(如 Promise 无法转换)。

  2. 全部 JS 兼容性处理 → @babel/polyfill

    问题:会引入所有兼容性代码,体积过大,但实际只需要部分兼容性处理。

  3. 按需加载兼容性处理 → core-js

    实现:仅对需要做兼容性处理的内容进行按需加载。

javascript 复制代码
// 配置示例
{
  test: /\.js$/,
  exclude: /node_modules/,
  loader: 'babel-loader',
  options: {
    presets: [
      [
        '@babel/preset-env',
        {
          useBuiltIns: 'usage',
          corejs: {
            version: 3
          },
          targets: {
            chrome: '60',
            firefox: '60',
            ie: '9',
            safari: '10',
            edge: '17'
          }
        }
      ]
    ]
  }
}

2.6 压缩HTML和JS代码

  1. 设置mode为production,js代码会自动压缩
  2. 压缩html
javascript 复制代码
plugins: [
  new HtmlWebpackPlugin({
    template: "./src/index.html",
    // 压缩html代码
    minify: {
      // 移除注释
      removeComments: true,
      // 移除空格
      collapseWhitespace: true,
    },
  }),
],

3. 生产环境配置

3.1 性能优化

开发环境性能优化

  • 优化打包构建速度
  • 优化代码调试

生产环境性能优化

  • 优化打包构建速度
  • 优化代码运行的性能

3.2 HMR(热模块替换)

HMR:热模块替换,简称热替换

作用:一个模块发生变化时,只会重新打包这一个模块,而不是重新打包所有模块,极大提升构建速度

3.2.1 开启热更新

javascript 复制代码
// webpack.config.js
devServer: {
  contentBase: path.join(__dirname, "dist"),
  compress: true,
  port: 8080,
  // 开启热更新
  hot: true,
},

3.2.2 不同文件类型的HMR支持

样式文件:可以使用HMR功能,style-loader内置。

JS文件 :默认不能使用HMR功能,需要修改js代码添加支持HMR功能的代码。注意:HMR功能只能处理非入口js文件。

javascript 复制代码
// 入口js文件中
if(module.hot){
  // 添加需要热更新的模块
  module.hot.accept('./other.js');
}

HTML文件:默认不能使用HMR功能,同时会导致问题:html文件不能热更新了。(一般来说html文件只会有一个,所以不用HMR功能)。解决办法:修改entry入口,将html文件引入

javascript 复制代码
// webpack.config.js
entry: ["./src/index.js", "./src/index.html"],

3.3 source-map

一种提供构建后代码映射到源代码的技术。构建后代码报错,可以通过映射追踪到源代码。

3.3.1 属性说明

【inline-|hidden-|eval-】【nosources-】【cheap-【module-】】source-map

3.3.2 各类型区别

  • inline-source-map :内联只生成一个内联source-map
    • 错误代码准确信息 和 源代码的错误位置
  • hidden-source-map :外部
    • 错误代码错误原因,但是没有错误位置
    • 不能追踪源代码错误,只能提示到构建后代码的错误位置
  • eval-source-map :内联
    • 每一个文件都生成对应的source-map,都在eval
    • 错误代码准确信息 和 源代码的错误位置
  • nosources-source-map :外部
    • 错误代码准确信息,但是没有任何源代码信息
  • cheap-source-map :外部
    • 错误代码准确信息 和 源代码的错误位置
    • 只能精确的行
  • cheap-module-source-map :外部
    • 错误代码准确信息 和 源代码的错误位置

3.3.3 内联和外部区别

  1. 外部生成了文件,内联没有
  2. 内联构建速度更快

3.3.4 选择建议

开发环境:速度快,调试更友好

  • 速度快(eval>inline>cheap>...)
    • eval-cheap-source-map | eval-source-map
  • 调试更友好
    • source-map
    • cheap-module-source-map cheap-source-map
  • 推荐:eval-source-map / eval-cheap-module-source-map

生产环境:源代码要不要隐藏?调试要不要更友好

  • 内联会让代码体积变大,所以在生产环境不用内联
  • nosources-source-map 全部隐藏
  • hidden-source-map 只隐藏源代码,会提示构建后代码错误信息
  • 推荐:source-map / cheap-module-source-map

3.4 OneOf

默认情况下,所有文件都会经过 rules 中的每一个 loader 进行匹配,效率低下。而 oneOf 的优化在于:文件只要被列表中的任一 loader 成功匹配,就会停止后续匹配,有效加快了构建速度。

注意

  • oneOf中,一个文件只能被一个loader处理
  • 当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序
  • 例如:先执行eslint在执行babel

3.5 缓存

3.5.1 Babel缓存

cacheDirectory: true

--> 让第二次打包构建速度更快

javascript 复制代码
{
  test: /\.js$/,
  exclude: /node_modules/, 
  loader: 'babel-loader',
  options: {
    presets: [...],
  },
  // 开启babel缓存
  // 第二次构建时,会读取之前的缓存
  cacheDirectory: true
}

3.5.2 文件资源缓存

在需要缓存的文件中设置后缀

javascript 复制代码
// js
output: {
  filename: 'js/built.[contenthash:10].js'
}

// css
plugins: [
  new MiniCssExtractPlugin({
    filename: 'css/built.[contenthash:10].css'
  })
]

3.5.3 文件资源缓存hash值说明

  • hash :每次webpack构建时会生成一个唯一的hash值
    • 问题:因为js和css同时使用一个hash值。如果重新打包,会导致所有缓存失效。(可能我只改动一个文件)
  • chunkhash :根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样
    • 问题:js和css的hash值还是一样的,因为css是在js中被引入的,所以同属于一个chunk
  • contenthash:根据文件的内容生成hash值。不同文件hash值一定不一样

3.6 tree shaking

tree shaking:去除无用代码

前提

  1. 必须使用ES6模块化
  2. 开启production环境

作用:减少代码体积

配置

在package.json中配置

json 复制代码
"sideEffects": false  // 所有代码都没有副作用(都可以进行tree shaking)

问题:可能会把css / @babel/polyfill(副作用)文件干掉

解决方案

json 复制代码
"sideEffects": ["*.css", "*.less"]

3.7 code split

3.7.1 单入口和多入口

javascript 复制代码
module.exports = {
  // 单入口
  // entry: './src/js/index.js'
  entry: {
    // 多入口:有一个入口,最终输出就有一个bundle
    index: '/src/js/index.js', 
    test: './src/js/test.js'
  },
  output: {
    // [name]:取文件名
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  }
}

3.7.2 依赖单独打包

  1. 可以将node_modules中代码单独打包一个chunk最终输出
  2. 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk
javascript 复制代码
optimization: {
  splitChunks: {
    chunks: 'all'
  },
}

3.7.3 通过js代码将某个文件单独打包成一个chunk

通过js代码,让某个文件被单独打包成一个chunk

import动态导入语法:能将某个文件单独打包

javascript 复制代码
import(/* webpackChunkName: 'test' */'./test')
  .then(({ mul }) => {
    // 文件加载成功~
    // eslint-disable-next-line
    console.log(mul(2, 5));
  }).catch(() => {
    // eslint-disable-next-line
    console.log('文件加载失败~');
  });

3.8 懒加载和预加载

  1. 懒加载:只有在特定条件下才加载文件
  2. 预加载/* webpackPrefetch: true */,在其他文件加载完毕后,才加载此文件(有可能有兼容性问题,在caniuse网站可以查看能否使用)
javascript 复制代码
document.getElementById('btn').onclick = function(){
  import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then(({ mul }) => {
    console.log(mul(4, 5));
  })
}

3.9 PWA

PWA技术,离线可访问,使用workbox-webpack-plugin插件

javascript 复制代码
new WorkboxWebpackPlugin.GenerateSW({
  // 1.帮助servicework快速启动
  // 2.删除旧的serviceworker
  // 最终生成一个servicework配置文件
  clientsClaim: true,
  skipWaiting: true,
})

3.9.1 注册serviceworker

javascript 复制代码
// 注册serviceworker
// 处理兼容性问题
if('serviceworker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceworker
      .register('/service-worker.js')
      .then(() => {
        console.log('sw注册成功了')
      })
      .catch(() => {
        console.log('sw注册失败了');
      });
  });
}

3.9.2 注意事项

  1. eslint不认识 window、navigator全局变量

    解决:需要修改package.json中eslintConfig配置

    javascript 复制代码
    "env": {
      "browser": true // 支持浏览器端全局变量
    }
  2. sw代码必须运行在服务器上

    bash 复制代码
    // nodejs
    npm i serve -g
    serve -s build  // 启动服务器,将build目录下所有资源作为静态资源暴露出去

3.10 多进程打包

使用thread-loader开启多线程打包

开启多进程打包。

  • 进程启动大概为680ms,进程通信也有开销
  • 只有工作消耗时间比较长,才需要多进程打包
javascript 复制代码
{
  test: /\.js$/,
  exclude: /node_modules/, 
  use: [
    /*
    开启多进程打包。
    进程启动大概为680ms,进程通信也有开销。
    只有工作消耗时间比较长,才需要多进程打包
    */
    'thread-loader',
    {
      loader: 'babel-loader',
      options: {
        presets: [...]
      }
    }
  ]
}

3.10.1 设置多线程打包数量

javascript 复制代码
{
  loader: 'thread-loader', 
  options: {
    workers: 2 // 进程2个
  }
}

3.11 externals

排除掉不需要加到最终包里的内容,由我们自己选择引入的方式,如CDN或本地资源

KEY通过import引入的名称

javascript 复制代码
externals: {
  // 拒绝jQuery被打包进来
  jquery: 'jquery'
  // [KEY]: [VALUE]
}

3.11.1 函数形式

通过函数动态决定是否排除某个模块:

javascript 复制代码
externals: [
  function ({ request }, callback) {
    if (/^yourregex$/.test(request)) {
      return callback(null, 'commonjs ' + request);
    }
    callback();
  }
]

3.12 dll

作用:对某些库(第三方库:jquery、react、vue等)单独打包

步骤

  1. 首先定义webpack.dll.js文件
  2. 进行单独打包当你运行 webpack 时,默认查找 webpack.config.js 配置文件,所以我们需要修改打包命令为webpack --config webpack.dll.js

3.12.1 webpack.dll.js配置

其中webpack插件DLLPlugin的manifest用来提供映射关系

javascript 复制代码
// webpack.dll.js 
const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {
    // 最终打包生成的[name] --> jquery
    // ['jquery'] --> 要打包的库是jquery
    jquery: ['jquery']
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dll'),
    library: '[name]_[hash]', // 打包的库里面向外暴露出去的内容叫什么名字
  },
  plugins: [
    // 打包生成一个 manifest.json --> 提供和jquery映射
    new webpack.DllPlugin({
      name: '[name]_[hash]', // 映射库的暴露的内容名称
      path: path.resolve(__dirname, 'dll/manifest.json') // 输出文件路径
    })
  ],
  mode: 'production'
};

3.12.2 webpack.config.js中使用

在webpack.config.js中:

  • 使用插件add-asset-html-webpack-plugin将某个文件打包输出去,并在html中自动引入该资源
  • 使用插件DllReferencePlugin告诉webpack哪些库不参与打包,同时使用时的名称也得变
javascript 复制代码
// webpack.config.js
plugins: [
  new HtmlWebpackPlugin({
    template: './src/index.html'
  }),
  // 告诉webpack哪些库不参与打包,同时使用时的名称也得变~
  new webpack.DllReferencePlugin({
    manifest: path.resolve(__dirname, 'dll/manifest.json')
  }),
  // 将某个文件打包输出去,并在html中自动引入该资源
  new AddAssetHtmlWebpackPlugin({
    filepath: path.resolve(__dirname, 'dll/jquery.js')
  })
],

4. 优化环境配置

4.1 性能优化总结

4.1.1 开发环境性能优化

  • 优化打包构建速度
    • HMR
  • 优化代码调试
    • source-map

4.1.2 生产环境性能优化

  • 优化打包构建速度
    • oneOf
    • babel缓存
    • 多进程打包
    • externals
    • dll
  • 优化代码运行的性能
    • 缓存(hash-chunkhash-contenthash)
    • tree shaking
    • code split
    • 懒加载/预加载
    • pwa

5. Webpack配置详解

5.1 entry

具体可以去webpack官网看

5.1.1 Webpack Entry 入口起点配置说明

5.1.1.1 String 字符串形式
javascript 复制代码
entry: './src/index.js'
  • 单入口:打包形成一个chunk,输出一个bundle文件
  • 此时chunk的名称默认是 main
5.1.1.2 Array 数组形式
javascript 复制代码
entry: ['./src/index.js', './src/add.js']
  • 多入口:所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件
  • 只有在HMR功能中让html热更新生效
5.1.1.3 Object 对象形式
javascript 复制代码
entry: {
  index: ['./src/index.js', './src/count.js'],
  add: './src/add.js'
}
  • 多入口:有几个入口文件就形成几个chunk,输出几个bundle文件
  • 此时chunk的名称是key
5.1.1.4 特殊用法说明
  • index: ['./src/index.js', './src/count.js'] - 所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件
  • add: './src/add.js' - 形成一个chunk,输出一个bundle文件

5.2 output

具体可以去webpack官网看

javascript 复制代码
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/[name].js', // 文件名称(指定名称+目录)
    path: resolve(__dirname, 'build'), // 输出文件目录(将来所有资源输出的公共目录)
    publicPath: '/', // 所有资源引入公共路径前缀 --> 'imgs/a.jpg' --> '/imgs/a.jpg'
    chunkFilename: 'js/[name]_chunk.js', // 非入口chunk的名称
    // library: '[name]', // 整个库向外暴露的变量名
    // libraryTarget: 'window' // 变量名添加到哪个上 browser
    // libraryTarget: 'global' // 变量名添加到哪个上 node
    // libraryTarget: 'commonjs'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ],
  mode: 'development'
}

library向外暴露的变量名在最终打包的js文件中

5.3 module

具体可以去webpack官网看

javascript 复制代码
rules: [
  // loader的配置
  {
    test: /\.css$/,
    // 多个loader用use
    use: ['style-loader', 'css-loader']
  },
  {
    test: /\.js$/,
    // 排除node_modules下的js文件
    exclude: /node_modules/,
    // 只检查 src下的js文件
    include: resolve(__dirname, 'src'),
    // 优先执行
    enforce: 'pre',
    // 延后执行
    // enforce: 'post',
    // 单个loader用loader
    loader: 'eslint-loader',
    options: {}
  },
  {
    // 以下配置只会生效一个
    oneOf: []
  }
]

5.4 resolve

具体可以去webpack官网看

javascript 复制代码
// 解析模块的规则
resolve: {
  // 配置解析模块路径别名: 优点简写路径 缺点路径没有提示
  alias: {
    $css: resolve(__dirname, 'src/css')
  },
  // 配置省略文件路径的后缀名
  extensions: ['.js', '.json', '.jsx', '.css'],
  // 告诉 webpack 解析模块是去找哪个目录
  modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
}

5.5 devserver

具体可以去webpack官网看

javascript 复制代码
devServer: {
  static: {
    directory: path.join(__dirname, 'build'),
  },
  // 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
  watchFiles: ['build/**/*'],
  watchOptions: {
    // 忽略文件
    ignored: /node_modules/
  },
  // 启动gzip压缩
  compress: true,
  // 端口号
  port: 5000,
  // 域名
  host: 'localhost',
  // 自动打开浏览器
  open: true,
  // 开启HMR功能
  hot: true,
  // 不要显示启动服务器日志信息
  clientLogLevel: 'none',
  // 除了一些基本启动信息以外,其他内容都不要显示
  quiet: true,
  // 如果出错了,不要全屏提示~
  overlay: false,
  // 服务器代理 --> 解决开发环境跨域问题
  proxy: {
    //一旦devServer(5000)服务器接受到/api/xxx的请求,就会把请求转发到另外一个服务器(3000)
    '/api': {
      target: 'http://localhost:3000',
      // 发送请求时,请求路径重写:将/api/xxx --> /xxx (去掉/api)
      pathRewrite: {
        '^/api': ''
      }
    }
  }
}

5.6 optimization

5.6.1 splitChunks

javascript 复制代码
optimization: {
  splitChunks: {
    chunks: 'all', // 分割的chunk最小为30kb
    minSize: 30 * 1024, // 分割的chunk最小为30kb
    maxSiza: 0, // 最大没有限制
    minChunks: 1, // 要提取的chunk最少被引用1次
    maxAsyncRequests: 5, // 按需加载时并行加载的文件的最大数量
    maxInitialRequests: 3, // 入口js文件最大并行请求数量
    automaticNameDelimiter: '~', // 名称连接符
    name: true, // 可以使用命名规则
    cacheGroups: { // 分割chunk的组
      // node_modules文件会被打包到 vendors 组的chunk中。--> vendors~xxx.js
      // 满足上面的公共规则,如:大小超过30kb,至少被引用一次。
      vendors: {
        test: /[\\/]node_modules[\\/]/, // 优先级
        priority: -10
      },
      default: {
        // 要提取的chunk最少被引用2次
        minChunks: 2,
        // 优先级
        priority: -20,
        // 如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块
        reuseExistingChunk: true
      }
    }
  }
}

5.6.2 runtimeChunk

5.6.3 minimizer

javascript 复制代码
optimization: {
  // 将当前模块的记录其他模块的hash单独打包为一个文件 runtime
  // 解决:修改a文件导致b文件的contenthash变化
  runtimeChunk: {
    name: entrypoint => `runtime-${entrypoint.name}`
  },
  minimizer: [
    // 配置生产环境的压缩方案:js和css
    new TerserWebpackPlugin({
      // 开启缓存
      cache: true,
      // 开启多进程打包
      parallel: true,
      // 启动source-map
      sourceMap: true
    })
  ]
}
相关推荐
知识分享小能手4 小时前
React学习教程,从入门到精通,React 单元测试:语法知识点及使用方法详解(30)
前端·javascript·vue.js·学习·react.js·单元测试·前端框架
PineappleCoder7 小时前
搞定用户登录体验:双 Token 认证(Vue+Koa2)从 0 到 1 实现无感刷新
前端·vue.js·koa
EveryPossible8 小时前
展示内容框
前端·javascript·css
伊织code8 小时前
WebGoat - 刻意设计的不安全Web应用程序
前端·安全·webgoat
子兮曰8 小时前
Vue3 生命周期与组件通信深度解析
前端·javascript·vue.js
拉不动的猪8 小时前
回顾关于筛选时的隐式返回和显示返回
前端·javascript·面试
yinuo8 小时前
不写一行JS!纯CSS如何读取HTML属性实现Tooltip
前端
gnip9 小时前
脚本加载失败重试机制
前端·javascript
遗憾随她而去.9 小时前
Uni-App 页面跳转监控实战:快速定位路由问题
前端·网络·uni-app