4、构建工具配置:Webpack/Vite核心配置、环境变量管理、路径别名配置、构建优化基础

说到构建工具,我这些年跟Webpack和Vite都打过不少交道。说实话,早期用Webpack的时候,光是配置就能写满一整个屏幕。后来Vite出来了,确实清爽很多。但不管用哪个,核心要解决的问题其实都一样——怎么让代码跑起来,怎么让构建更快,怎么让环境切换不出幺蛾子。

4.1 Webpack核心配置:从零搭一个能用的架子

先聊聊Webpack。我个人习惯,每次新建项目都会从这几个核心配置入手:

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // 入口文件
  entry: './src/index.js',
  
  // 输出配置
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
    clean: true // 每次构建前清理dist
  },
  
  // 模块处理规则
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  
  // 插件
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    })
  ]
};
我的小经验:contenthash这个配置一定要加上。我在项目中遇到过好几次,改了代码但用户浏览器不更新,就是因为没用hash。加上之后,文件内容变了hash就变,缓存问题迎刃而解。

4.2 Vite核心配置:快就一个字

Vite为什么快?说白了就是开发时用ES Module,不用打包。我第一次用Vite的时候,那个启动速度真的惊到我了——秒开。

// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],
  
  // 开发服务器配置
  server: {
    port: 3000,
    open: true,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true
      }
    }
  },
  
  // 构建配置
  build: {
    outDir: 'dist',
    sourcemap: false,
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom']
        }
      }
    }
  }
});
注意:Vite的proxy配置在开发时非常好用。我曾经有个项目,后端接口跨域问题折腾了半天,最后发现Vite的proxy一行配置就搞定了。你想想看,省了多少事。

4.3 环境变量管理:别让配置泄露到线上

环境变量这块,我踩过不少坑。最惨的一次,不小心把测试环境的API密钥提交到了代码仓库...嗯,从那以后我对环境变量管理就特别上心。

Webpack和Vite处理环境变量的方式不太一样:

特性 Webpack Vite
内置支持 需要DefinePlugin 默认支持import.meta.env
环境文件 .env文件 + dotenv .env文件(内置支持)
变量前缀 自定义 VITE_
类型提示 需要额外配置 内置类型定义
// .env.development
VITE_API_BASE_URL=http://localhost:8080/api
VITE_APP_TITLE=开发环境

// .env.production
VITE_API_BASE_URL=https://api.example.com
VITE_APP_TITLE=生产环境

// 在代码中使用
const apiUrl = import.meta.env.VITE_API_BASE_URL;
避坑指南:千万不要把敏感信息(比如数据库密码、私钥)放到前端环境变量里。前端代码是公开的,这些变量最终会被打包到JS文件中。我曾经见过有人把阿里云AccessKey放进去...后果你懂的。

4.4 路径别名配置:告别../../../地狱

写过大型项目的人都知道,相对路径引用有多痛苦。我记得有个项目,一个组件引用了七层目录外的文件,那个路径长得...我每次看到都想骂人。

路径别名就是来解决这个问题的:

// Webpack配置
resolve: {
  alias: {
    '@': path.resolve(__dirname, 'src'),
    '@components': path.resolve(__dirname, 'src/components'),
    '@utils': path.resolve(__dirname, 'src/utils')
  }
}

// Vite配置
resolve: {
  alias: {
    '@': path.resolve(__dirname, 'src'),
    '@components': path.resolve(__dirname, 'src/components')
  }
}

// 使用方式(两者一样)
import Button from '@/components/Button';
import { formatDate } from '@utils/date';
我的习惯:我会在项目一开始就把常用的路径别名配好,比如@(src根目录)、@components、@utils、@styles。这样后面写代码的时候,引用路径清晰又简短。你想想看,import '@/components/Button' 和 import '../../../../components/Button',哪个看着舒服?

4.5 构建优化基础:让打包快一点,再快一点

构建优化这个话题,我可以聊一整天。这里先讲几个最基础、最实用的优化点:

4.5.1 代码分割

为什么要做代码分割?说白了就是不要让用户一次性下载所有代码。我见过一个项目,首屏JS包有3MB...加载了快10秒。

// 动态导入实现代码分割
const AdminPage = () => import('./pages/AdminPage');

// Webpack的splitChunks配置
optimization: {
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        chunks: 'all'
      }
    }
  }
}

4.5.2 Tree Shaking

Tree Shaking,说白了就是去掉没用到的代码。Webpack和Vite都支持,但有个前提——你的代码必须是ES Module格式。

关键点:使用import/export语法,不要用require/module.exports。我在项目中遇到过,明明配了Tree Shaking但体积没变化,最后发现是某个库用了CommonJS格式。

4.5.3 压缩与缓存

这两个优化点,配置起来很简单,但效果很明显:

// Webpack配置
const TerserPlugin = require('terser-webpack-plugin');

optimization: {
  minimize: true,
  minimizer: [new TerserPlugin({
    terserOptions: {
      compress: {
        drop_console: true // 去掉console.log
      }
    }
  })],
  // 持久化缓存
  cache: {
    type: 'filesystem'
  }
}

// Vite配置(默认已开启)
build: {
  minify: 'terser', // 或 'esbuild'
  target: 'es2015'
}
一个小技巧:开发环境不要开压缩,不然调试起来很痛苦。生产环境再开压缩和去掉console.log。我一般会在CI/CD流程里区分环境配置。

4.6 总结一下

构建工具配置这块,说白了就是三个核心:

  • 基础配置:入口、出口、loader、plugin,这是骨架
  • 环境管理:开发/测试/生产环境分开,变量别泄露
  • 构建优化:代码分割、Tree Shaking、压缩缓存,让项目跑得快

我个人建议,刚开始接触的时候,先用Vite搭个小项目试试手。等理解了构建流程,再去研究Webpack的深度配置。毕竟,工具是为人服务的,别让配置本身成了负担。

下一章,我们会聊聊代码规范与质量保障。嗯,那又是一个能聊很多的话题。