webpack5的配置使用,这次打算记录一下

39 阅读7分钟

没有打包工具,那么组织管理代码就会变得非常麻烦,并且不利于新语法的使用

webpack看了听了很多次,趁着最近准备面试,再次回忆记录下来

下面是webpack的常规配置和使用

为什么需要Webpack?

在现代前端开发中,我们通常需要处理大量的JavaScript模块、样式文件、图片等资源。手动管理这些资源不仅费时费力,还容易出错。Webpack作为一个强大的静态模块打包工具,可以:

  • 将分散的模块打包成少数几个优化过的文件
  • 自动处理文件之间的依赖关系
  • 转换、优化各种前端资源
  • 提供开发服务器和热更新功能,加速开发流程

从最简单的配置开始

先创建一个基本的Webpack配置文件,初始化了一个Node.js项目(pnpm init)并安装了Webpack(pnpm install webpack webpack-cli -D)。

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.js', // 入口文件,文件树的根节点
  output: {
    path: path.resolve(__dirname, 'dist'), // 输出文件的目录
    // 主JavaScript文件命名模式
    // [name]: 入口名称,默认为main
    // [contenthash:8]: 基于内容生成的8位hash值,内容改变时hash值改变
    // .js: 文件扩展名
    filename: '[name].[contenthash:8].js' // 输出的文件的名称
  },
  mode: 'development' // 开发模式
}

这个配置告诉Webpack从src/index.js开始构建我们的应用,并将结果输出到dist/xxx.js。很简单,但实际项目远比这复杂,我们需要处理各种类型的文件,js,css,img等。

配置为hash值的原因是为了避免浏览器缓存问题,hash值会随着文件内容的变化而变化,这样可以确保用户总是加载最新的文件

配置完成之后,就可以在package.json中添加执行脚本:

{
  "scripts": {
    "build": "webpack",
    "dev": "webpack serve --mode development",
    "prod": "webpack --mode production"
  }
}

执行pnpm dev, 或者直接执行 npx webpack 后能看见输出的内容:

img_2025_03_27_11_02_58.png

js资源的打包就完成了

让Webpack加载各种资源

在开发的需求里面,最终需要在客户的浏览器上去渲染展示:那么离不开三件套 html css 和 js

为了提高开发效率,往往会使用高版本的语法,使用更适合开发的特定格式文件。对此最终都需要转换为浏览器能够识别的内容,如下:

JavaScript 降级

客户的开发环境各种各样的,如何处理高版本语法就是一个问题

es5往后的js版本,包含很多浏览器尚未完全支持的特性,比如import export。我们可以使用Babel来转换这些代码:

// 安装依赖:pnpm install -D babel-loader @babel/core @babel/preset-env

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: '/\.js$/', // 匹配所有的 .js 文件
        exclude: '/node_modules/', // 排除所有的 node_modules 文件夹,因为它们已经被编译过了
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel-preset-env'] // 使用预设转换为ES5代码
          }
        }
      }
    ]
  }
}

这样配置后,你就可以放心使用ES6+的特性了,Webpack会处理兼容性问题,比如将import转换为require,将箭头函数转换为普通函数等。

上面是显式的使用了babel去做js的转换,实际上webpack在处理模块时会将ES模块语法(import/export)转换为CommonJS模块语法(require/module.exports),即使没在使用babel-loader。这是webpack的默认行为,它需要兼容node.js 的模块系统

思考点🤔: babel的设计原理是什么?编译原理吧,符合某种的规范的是不是都可以转换为AST抽象语法树。日常语言可以抽象为语法树吗? 答案是:自然语言具有歧义性;语义理解和上下文有关,而AST通常是上下文无关的;隐含信息需要常识或者背景知识来理解;非结构化的自然语言难以用AST表示,而编程语言通常是结构化的

加载样式文件

网页少不了css文件,在webpack中处理css内容也很简单:

// 安装: pnpm install -D css-loader style-loader

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',  // 将CSS注入到DOM中
          'css-loader'     // 解析CSS文件中的@import和url()
        ]
      }
    ]
  }
};

现在你可以在JavaScript中直接导入CSS文件了:import './styles.css',Webpack会负责将这些样式应用到页面上,如果你使用了Sass或Less,只需要安装相应的loader(如sass-loaderless-loader)并在配置中添加即可。

css文件加载转存失败,建议直接上传图片文件

在webpack构建过程中,module.rules 数组中的规则顺序非常重要,总的来说,遵循以下规则:

  1. 从上到下,从左到右
    • 对于同一个rule中的use数组,loader的执行顺序是从右到左的
    • 对于rules数组中的多个rule,执行顺序的是从下到上(后面的规则先执行)
  2. 优先级规则:
    • enforce: 'pre' 的loader最先执行
    • 普通loader(没有enforce属性)其次执行
    • enforce: 'post' 的loader最后执行

上面两个css的loader的执行顺序如下:

  1. css-loader先执行,将CSS转换为包含CSS字符串的JS模块
  2. style-loader后执行,生成将CSS注入DOM的JavaScript代码

这种设计体现了"单一职责原则",每个loader只负责一种转换,通过组合使用实现完整功能。类似的设计模式在许多前端工具中都能看到,如Babel的插件系统、PostCSS的处理器链等

这种设计体现了 "单一职责原则",每个loader只负责一种功能,通过组合使用实现完整功能,可以简化调试和维护。类似的设计模式在babel的插件系统也能看见,比如babel/preset-env只负责将ES6+转换为ES5,而babel/plugin-transform-runtime则负责处理运行时的polyfill和helper函数

style-loader 的工作原理

style-loader接收css-loader处理后的结果,将CSS样式插入到DOM中:

  1. 生成注入代码:创建JavaScript代码,用于将CSS内容注入到<style>标签中
  2. 运行时注入:在浏览器运行时,动态创建<style>元素并将CSS内容插入到其中
  3. 添加到DOM:将创建的样式标签添加到HTML文档的<head>部分

简化的实现逻辑类似于:

// 简化的style-loader实现原理
const css = require("./style.css"); // 这里获取css-loader的输出
const styleElement = document.createElement("style");
styleElement.innerHTML = css;
document.head.appendChild(styleElement);

图片和静态资源怎么办?

处理图片、字体等资源也很简单,Webpack 5内置了资源模块功能:

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|jpeg|gif|svg)$/,
        type: "asset/resource",
        generator: {
          // 为图片资源单独设置输出路径和文件名
          filename: "images/[name].[hash:8][ext]",
        },
      },
      // 为字体文件设置命名模式
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: "asset/resource",
        generator: {
          filename: "fonts/[name].[hash:8][ext]",
        },
      },
    ]
  }
}

如果你使用的是 webpack4,可以使用file-loaderurl-loader 来处理图片

// 安装:pnpm install -D file-loader url-loader
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|jpeg|gif)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              limit: 8192, // 小于8k的图片会被转为base64格式的文件
              name: '[name].[hash].[ext]', // 输出文件名
              outputPath: 'images/' // 输出目录
            }
          }
        ]
      }
    ]
  }
}

这个配置使你可以直接导入图片和字体:import logo from './logo.png'

webpack图片打包效果,图片模块返回的是图片资源的一个资源地址:

img_2025_03_27_18_03_02.png

img_2025_03_27_18_08_04.png

常用好用插件

以下是一些常用的webpack的插件:

自动生成HTML文件:html-webpack-plugin插件

插件作用

  • 自动引入打包后的bundle.js资源
  • 支持模板引擎,可以自定义HTML结构

插件用法

// 安装依赖: pnpm install -D html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      // HTML模板路径
      template: './src/index.html',  
      // 输出文件名
      filename: 'index.html',  
      // HTML标题
      title: '我的'   
    })
  ]
};

配置完成后,webpack 会自动将打包后的文件注入到HTML中,省去手动修改,它还可以在模版中使用变量,来动态生成模版,比如:

<title><%= htmlWebpackPlugin.options.title %></title>

参考文档: npm:www.npmjs.com/package/htm… webpack:webpack.docschina.org/plugins/htm…

自动清理构建目录:clean-webpack-plugin插件

插件作用

  • 每次构建前自动清理dist目录,避免文件堆积

插件用法

// 安装依赖: pnpm install -D clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  plugins: [
    new CleanWebpackPlugin(),  // 清理dist文件夹,告别手动删除的烦恼
  ]
};

参考文档: npm:www.npmjs.com/package/cle… webpack:webpack.docschina.org/plugins/cle…

开发环境配置:让调试变得轻松

上面是一个资源的打包配置,但是在实际开发中,我们期望看见的是一个完整的页面,而不是静态资源文件。Webpack提供了一个开发服务器,可以让我们在本地快速预览和调试代码web

调试工具如下:

使用webpack-dev-server

插件作用

  • 提供一个开发服务器,自动刷新页面
  • 支持热模块替换(HMR),修改代码后无需刷新页面

插件用法

// 安装依赖: pnpm install -D webpack-dev-server
module.exports = {
  mode: 'development',
  devtool: 'source-map',  // 生成source map方便代码调试
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'), // 静态资源目录
    },
    hot: true,  // 启用热模块替换(HMR),修改代码后无需刷新页面
    port: 8080,  // 开发服务器端口
    open: true   // 自动打开浏览器
  }
};

现在运行npx webpack serve,就能启动一个开发服务器,代码变更会即时反映在浏览器中,大大提升开发效率

npx 的作用: npx 是 npm 5.2.0 版本引入的工具 它允许我们执行 node_modules/.bin 目录下的可执行文件,而无需全局安装或直接指定路径 它会优先查找本地安装的包,如果找不到才会临时下载并执行

如图:

img_2025_03_28_10_21_42.png


至此就可以做简单开发了,并且修改代码后会自动刷新页面,里面看见代码效果

webpack的使用非常简单,牛的,喝口水庆祝一下

img_2025_03_28_16_02_17.png