源本科技 | 码上会

Webpack 开发服务器

2026/04/21
7
0

引言

在开发过程中,每次修改代码都执行完整打包流程非常繁琐耗时。完整打包需要重新解析入口、构建依赖图、读取磁盘文件、通过 Loader / Plugin 处理文件,最终将产物写入磁盘。代码频繁修改时,重复操作会大幅降低开发效率。

为解决该问题,我们可以使用 webpack-dev-server,这是 Webpack 官方提供的开发服务器工具,能极大简化开发流程,提升开发体验。

开发服务器

webpack-dev-server 是 Webpack 官方提供的开发服务器工具,核心功能如下:

  • 快速构建:打包产物存储在内存中,不写入磁盘,减少 I/O 操作,大幅提升构建速度

  • 热模块替换(HMR):无需刷新整个页面,即可替换 / 更新模块,保留应用运行状态

  • 自动刷新:检测到代码修改后,自动刷新浏览器,实现实时预览

  • 跨域代理:内置代理功能,轻松解决前端开发中的接口跨域问题

  • 自定义配置:支持端口、自动打开、代理等个性化配置,适配不同开发场景

安装

使用 webpack-dev-server 前,需将其安装为项目开发依赖:

npm install webpack-dev-server -D

配置

package.json

{
  "name": "node",
  "version": "1.0.0",
  "type": "module",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "serve": "webpack serve",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^7.1.4",
    "html-webpack-plugin": "^5.6.7",
    "less": "^4.6.4",
    "less-loader": "^12.3.2",
    "style-loader": "^4.0.0",
    "ts-loader": "^9.5.7",
    "typescript": "^6.0.3",
    "webpack": "^5.106.2",
    "webpack-cli": "^7.0.2",
    "webpack-dev-server": "^5.2.3"
  }
}

tsconfig.json

{
  "compilerOptions": {
    // 编译目标版本(现代浏览器)
    "target": "ES2020",
    // 使用 ES Module 模块化规范
    "module": "ESNext",
    // 适配 Webpack5 的模块解析策略
    "moduleResolution": "bundler",
    "rootDir": "./src",
    // 输出目录(与 webpack 保持一致)
    "outDir": "./dist",
    // 开启严格类型检查(推荐,工程化必备)
    "strict": true,
    // 生成 TS 类型声明文件(库开发必备)
    "declaration": false,
    // 跳过第三方库类型检查(提升编译速度)
    "skipLibCheck": true,
    // 强制文件扩展名(ESM 规范要求)
    "forceConsistentCasingInFileNames": true
  },
  // 编译范围
  "include": [
    "./src/**/*"
  ]
}

webpack.config.js

import path from 'path';
import { fileURLToPath } from 'url';
// ESM 模式导入 HTML 插件
import HtmlWebpackPlugin from 'html-webpack-plugin';

// 手动定义 __dirname(兼容 ESM 模式)
const __filename = fileURLToPath(import.meta.url); // 获取当前文件的绝对路径
const __dirname = path.dirname(__filename); // 获取当前文件所在目录的绝对路径

// Webpack 配置导出(ESM 模式)
export default {
  // 区分开发和生产环境
  mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
  // 入口文件
  entry: './src/index.ts',

  // 输出配置
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    // 在开发环境中不强制输出ES模块,以确保样式加载正常
    ...(process.env.NODE_ENV === 'production' 
      ? { 
          module: true, // 生产环境输出 ES Module 格式产物
          clean: true   // Webpack5 内置:打包前自动清空 dist 目录
        } 
      : {}
    )
  },

  // 开发环境下不需要实验性特性
  experiments: process.env.NODE_ENV === 'production' 
    ? {
        outputModule: true
      } 
    : {},

  // 模块解析
  resolve: {
    // 自动识别文件后缀,引入模块时可省略对应后缀名
    extensions: ['.js', '.ts', '.css', '.less', '.vue']
  },

  // TS 文件加载器
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/
      },
      {
        // 匹配所有以 .css 结尾的文件
        test: /\.css$/,
        // Loader 执行顺序:从右向左 执行
        // 1. css-loader 解析 CSS 文件
        // 2. style-loader 将样式注入 DOM
        use: ["style-loader", "css-loader"]
      },
      {
        // 匹配所有以 .less 结尾的文件
        test: /\.less$/,
        // 执行顺序:less-loader → css-loader → style-loader
        // 1. less-loader 编译 Less 为 CSS
        // 2. css-loader 解析 CSS 模块
        // 3. style-loader 将样式注入页面 DOM
        use: ["style-loader", "css-loader", "less-loader"]
      },
      {
        // 匹配所有图片格式文件,i 表示不区分大小写
        test: /\.(png|jpg|gif|jpeg)$/i,
        // Webpack 5 内置资源类型,自动判断资源处理方式
        type: 'asset',
        // 自定义打包输出规则
        generator: {
          // 输出到 dist/images 目录
          // [name]:原文件名
          // [hash:4]:4 位哈希值,防止缓存
          // [ext]:文件后缀名
          filename: 'images/[name].[hash:4][ext]'
        }
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/i,
        // 固定输出资源文件:不做 base64 转换,直接复制到打包目录
        type: 'asset/resource',
        generator: {
          // 输出到 dist/fonts 目录
          // [name] 原文件名,[hash:4] 4 位哈希值,[ext] 文件后缀
          filename: 'fonts/[name].[hash:4][ext]'
        }
      }
    ]
  },

  // 插件配置:生成 HTML 并自动注入打包资源
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html', // HTML 模板路径
      filename: 'index.html', // 输出的 HTML 文件名
      inject: true // 自动注入 JS/CSS 资源
    })
  ],

  // 开发服务器配置
  devServer: {
    port: 3000,       // 服务监听端口 3000
    open: true,       // 自动打开浏览器
    hot: true,        // 启用热更新
    static: {
      directory: path.join(__dirname, 'public'), // 静态资源目录
    },
    client: {
      overlay: false,  // 是否显示编译错误在浏览器中
    }
  },

  // 开发环境启用source map,便于调试
  devtool: process.env.NODE_ENV === 'production' ? false : 'eval-source-map'
};

运行

配置完成后,在终端执行命令,启动开发服务器:

npm run serve

服务启动后,会默认监听 3000 端口,并自动打开浏览器访问项目地址。

其他配置

mode 是 Webpack 核心配置,用于区分环境:

  • development:开发模式,优化构建速度,开启调试,代码不压缩

  • production:生产模式,自动启用代码压缩、Tree Shaking 等优化

Webpack 5 中,webpack-dev-server 默认开启热模块替换(HMR),修改代码后无需手动刷新,即可实时更新页面。