Part 1: webpack5 的打包介绍和基础配置

webpack

webpack 简介

webpack 是一个静态模块打包工具,也内置本地开发服务器。不仅能编译打包各类型的模块,而且插件种类、可定制化的配置项非常丰富,是当前比较主流的构建打包工具,类似的还有 Rollup、Snowpack、Vite 等。

webpack 4.x 和 webpack 5.x 是当下使用最多的 webpack 版本,自己也在大小项目中实战过,结合最近做的 webpack 5.x 性能优化,讲解下 webpack 5.x 的常用配置和高性能的构建优化配置。

打包原理

在项目构建时,他会递归地构建一个依赖关系图,其中包含应用需要的各个模块,然后将模块打包成一个或多个 bundle。

  • 识别入口文件
  • 通过逐层识别模块依赖。(Commonjs、amd 或者 es6 的 import,webpack 都会对其进行分析。来获取代码的依赖)
  • webpack 做的就是分析代码。转换代码,编译代码,输出代码
  • 最终形成打包后的代码

打包配置项介绍

module.exports = {
  mode: "development" | "production" | "none", //  默认值为 production
  entry: string | object, // 入口
  output: {
    publicPath: string, // 网站baseUrl
    filename: string, // 打包后输出的文件名称
    chunkFilename: string, // 间接引用的文件会走这个配置
    path: string, // 打包后产物的根目录
  },
  module: object, // 对各类模块识别和转换规则的定义
  plugins: array, // 做loader以外更多的工作,如打包优化、资源管理、注入环境变量等
  optimization: object, // 性能优化、分包策略的定义
  cache: string | object, // 是否启用构建缓存
};

上面列举了一些常用的构建配置项,定义合理的构建配置项,很大程度上能提高应用的开发体验、页面性能和用户体验。提高页面性能的配置内容主要体现在 module、plugins、optimization、cache 这四大块上。

构建的基础配置

module 配置的定义

1. 处理样式模块

主要包含style-loadercss-loaderless-loader、·和 postcss-loader的使用

  • 使用 css-loader 必须要配合使用 style-loader

  • css-loader 的作用是帮我们分析出各个 css 文件之间的关系,把 各个 css 文件合并成一段 css

  • style-loader 的作用是将 css-loader 生成的 css 代码挂载 到页面的 header 部分

  • 多个 loader 配合使用时,处理顺序是:从下到上,从右到左 的顺序;

  • postcss-loader 负责进一步处理 CSS 文件,比如添加浏览器前缀,压缩 CSS,px 转 rem 等

  • less-loader 负责将 less 模块转换为浏览器可识别的 css 模块

  • sass-loader 负责将 sass 模块转换为浏览器可识别的 css 模块

以使用 less 项目为范例的样式 module 定义

需要安装以下 loader 模块

npm i -D style-loader css-loader postcss-loader mini-css-extract-plugin

Dev 模式(启用 sourceMap,开发调试可定位到源文件)

[
  {
    test: /\.css$/, //寻找css文件
    use: ["style-loader", "css-loader", "postcss-loader"], //不提取时使用这种方式
  },
  {
    /**less的配置 */
    test: /\.less$/, //寻找less文件
    exclude: /node_modules/, //忽略
    use: [
      { loader: "style-loader" },
      {
        loader: "css-loader",
        options: {
          modules: { localIdentName: "[local]___[hash:base64:5]" },
          importLoaders: 2,
          sourceMap: true,
        },
      },
      {
        loader: "postcss-loader",
        options: {
          sourceMap: true,
        },
      },
      {
        loader: "less-loader",
        options: {
          sourceMap: true,
        },
      },
    ],
  },
];

Prod 模式(提取 css 样式到文件中,以 Link 外链方式引用)

const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //想要分开打包我们的css文件,需要使用mini-css-extract-plugin这个插件,

[
  {
    test: /\.css$/, //寻找css文件
    use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"], //使用MiniCssExtractPlugin.loader,css-loader,postcss-loader
  },
  {
    /**less的配置 */
    test: /\.less$/, //寻找less文件
    exclude: /node_modules/, //忽略
    use: [
      "style-loader",
      {
        loader: "css-loader",
        options: {
          modules: { localIdentName: "[local]___[hash:base64:5]" },
          importLoaders: 2,
        },
      },
      {
        loader: "postcss-loader",
      },
      {
        loader: "less-loader",
      },
    ],
  },
];
2. 处理 js 模块

编译 JS 用的Babel

babel 是 JavaScript 的编译器

它主要的作用是以下三点:

  • 转换语法
  • 为目标环境中缺失的语法提供垫片(Polyfill)
  • 源码转换(模块代码)

涉及到的主要模块分别是 babel-loader、@babel/core 和@babel/preset-env

  • babel-loader: 依赖@babel/core, 允许使用 babel 和 webpack 编译 JavaScript 文件
  • @babel/core: 把 js 代码分析成 ast(Abstract Syntax Tree,抽象语法树) ,方便各个插件分析语法进行相应的处理。有些新语法在低版本 js 中是不存在的,如箭头函数,rest 参数,函数默认值等,这种语言层面的不兼容只能通过将代码转为 ast,分析其语法后再转为低版本 js。
  • @babel/preset-env:智能预设,它使你可以使用最新的 JavaScript,而无需微观管理目标环境所需的语法转换(以及可选的浏览器 polyfill)

需要安装以下 loader 模块

npm i -D babel-loader @babel/core @babel/preset-env

工程根目录下放置文件.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        // 将es6的语法翻译成es5语法
        "targets": {
          //兼容目标浏览器
          //"chrome": "67", //指定浏览器版本
          //"browsers": ["last 2 versions", "safari >= 7"], //支持每个浏览器最后两个版本和safari大于等于7版本所需的polyfill代码转换
          "browsers": "> 5%", //支持市场份额超过5%的浏览器
          "node": "current" //如果通过Babel编译Node.js代码的话,可以设置 "target.node" 是 'current', 含义是 支持的是当前运行版本的nodejs。
        },
        "useBuiltIns": "usage", // 做@babel/polyfill补充时,按需补充,用到什么才补充什么,例:只转换用到的es6语法.
        "corejs": "3" //声明corejs版本
      }
    ],
    "@babel/preset-react" //转换react JSX
  ]
}

Rule 定义如下:

const path = require("path");
[
  {
    /**js的配置 */
    test: /\.(js|jsx)$/,
    include: path.resolve(__dirname, "../src"), // 表示只解析以下目录,减少loader处理范围
    exclude: /node_modules/, // 排除node_modules中的代码
    use: [
      {
        loader: "babel-loader", // 只是babel和webpack之间的桥梁,并不会将代码转译
        options: {
          cacheDirectory: true,
        },
      },
    ],
  },
];
3. 处理图片、字体模块

主要用到 url-loader、file-loader 加载器。
url-loader 允许你有条件地将文件转换为内联的 base-64 URL (当文件小于给定的阈值),这会减少小文件的 HTTP 请求数。 如果文件大于该阈值,会自动的交给 file-loader 处理。 这个问题可以通过 url-loader 解决。 url-loader 会将引入的图片编码,生成 dataURl

需要安装以下 loader 模块

npm i -D url-loader file-loader
const path = require("path");
[
  /**图标和图片的处理配置 */
  {
    test: /\.(png|jpe?g|svg|gif|webp)$/i,
    include: path.resolve(__dirname, "../src"), // 表示只解析以下目录,减少loader处理范围
    use: [
      {
        loader: "url-loader",
        options: {
          name: "[name].[hash:8].[ext]", // placeholder 占位符
          outputPath: "assets/", // 打包文件名
          limit: 1024 * 5, // 小于5KB则打包到js文件里,大于则使用file-loader的打包方式打包到assets里
          esModule: false, // 支持img标签使用require动态指定图片
        },
      },
    ],
  },
  /**字体的处理配置 */
  {
    test: /\.(eot|woff2?|ttf|otf)$/,
    include: path.resolve(__dirname, "../src"), // 表示只解析以下目录,减少loader处理范围
    use: {
      loader: "file-loader",
      options: {
        name: "[name]-[hash:8].min.[ext]", // 和上面同理
        outputPath: "fonts/",
        limit: 5000,
      },
    },
  },
];

常见 plugins 的配置

  • clean-webpack-plugin: 插件默认会清空 webpack 的 output 中配置的 path 指定的文件夹(默认 dist 目录)
  • html-webpack-plugin: 向 dist 目录中自动添加模版 html,可定义 title、template、favicon 等
  • mini-css-extract-plugin: 将 CSS 提取到单独的文件中,并且支持 CSS 和 SourceMaps 的按需加载
  • copy-webpack-plugin: 拷贝静态资源到 build 目录中
  • webpack.DefinePlugin: 对外暴露环境变量

需要安装以下模块

npm i -D clean-webpack-plugin html-webpack-plugin mini-css-extract-plugin copy-webpack-plugin

配置范例如下:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
[
  (new CleanWebpackPlugin(), // 打包前先清除dist文件,先于HtmlWebpackPlugin运行
  new HtmlWebpackPlugin({
    template: "public/index.html",
    favicon: "public/favicon.ico",
  }),
  new MiniCssExtractPlugin({
    ignoreOrder: true,
    filename: "static/css/[name].[contenthash:5].css",
    chunkFilename: "static/css/[name].[contenthash:5].css",
  }),
  new webpack.DefinePlugin({
    "process.env.PUBLIC_URL": JSON.stringify(process.env.PUBLIC_URL),
  }),
  new CopyWebpackPlugin({
    patterns: [
      {
        from: path.join(__dirname, "../mock"),
        to: path.join(__dirname, "../dist/mock"),
      },
      {
        from: path.join(__dirname, "../server/mockServer.js"),
        to: path.join(__dirname, "../dist/server"),
      },
    ],
  })),
];

以上是本次提供的 webpack 5.x 打包入门简介和常用基础配置介绍,附上的代码范例都已经过实践验证,大可放心使用,如有问题请及时指出。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值