4. 搭建前端构建流程

任务说明

本案例为企业前端工程搭建一个基于 Vite 的生产级构建流程,实现 JavaScript(含 JSX)、CSS(含 CSS Modules)、图片资源的打包与基础优化。选择 Vite 而非 Webpack,是因为其基于原生 ES Module 的开发服务器启动更快、配置更简洁,且内置了 Rollup 生产构建能力,足以覆盖本案例所需的资源打包与代码分割优化目标。

项目结构与依赖

在空目录中创建以下文件结构:


vite-demo/
├── index.html
├── package.json
├── vite.config.js
├── src/
│   ├── main.jsx
│   ├── App.jsx
│   ├── styles/
│   │   ├── global.css
│   │   └── app.module.css
│   └── assets/
│       └── logo.svg

在 package.json 中声明依赖与脚本:


{
  "name": "vite-demo",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^4.2.1",
    "vite": "^5.2.0"
  }
}

构建配置

创建 vite.config.js,配置 React 插件、CSS 代码分割、图片内联阈值与打包体积提示:


import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  build: {
    // 小于 4KB 的图片转为 base64 内联,减少 HTTP 请求
    assetsInlineLimit: 4096,
    // 开启 CSS 代码分割,按需加载
    cssCodeSplit: true,
    // 构建提示:当 chunk 超过 500KB 时输出警告
    chunkSizeWarningLimit: 500,
    rollupOptions: {
      output: {
        // 手动分包:将 react 相关依赖单独打包,利用浏览器缓存
        manualChunks: {
          'react-vendor': ['react', 'react-dom']
        }
      }
    }
  },
  server: {
    port: 5173,
    open: true
  }
});

应用源码

index.html 作为入口模板:


<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Vite 构建流程示例</title>
</head>
<body>
  <div id="root"></div>
  <script type="module" src="/src/main.jsx"></script>
</body>
</html>

src/main.jsx 引入全局 CSS 并挂载 React 应用:


import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
import './styles/global.css';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

src/App.jsx 使用 CSS Modules 与图片资源:


import React from 'react';
import styles from './styles/app.module.css';
import logoSvg from './assets/logo.svg';

function App() {
  return (
    <div className={styles.container}>
      <img src={logoSvg} alt="logo" className={styles.logo} />
      <h1 className={styles.title}>Vite 构建流程已生效</h1>
      <p className={styles.description}>
        此页面由 React + Vite 构建,包含 JSX、CSS Modules 与 SVG 资源。
      </p>
    </div>
  );
}

export default App;

src/styles/global.css 全局样式:


* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: #f5f7fa;
  color: #333;
}

src/styles/app.module.css 模块化样式:


.container {
  max-width: 600px;
  margin: 80px auto;
  padding: 40px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  text-align: center;
}

.logo {
  width: 120px;
  height: 120px;
  margin-bottom: 24px;
}

.title {
  font-size: 28px;
  color: #2c3e50;
  margin-bottom: 16px;
}

.description {
  font-size: 16px;
  line-height: 1.6;
  color: #666;
}

src/assets/logo.svg 示例图片资源:


<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="45" fill="#646cff" />
  <text x="50" y="65" text-anchor="middle" font-size="40" fill="#fff">V</text>
</svg>

构建流程与优化机制

Vite 在开发模式下利用浏览器原生 ES Module 按需编译,无需预打包;生产构建时通过 Rollup 执行以下优化:

  • JS 打包与压缩:将 JSX 编译为浏览器可执行的 JavaScript,并压缩为 ES5 兼容代码(默认目标为现代浏览器,可通过 build.target 调整)。
  • CSS 处理:global.css 被提取为独立样式文件;app.module.css 通过 CSS Modules 机制生成带哈希的局部类名,避免样式冲突,同样被提取到产物 CSS 中。
  • 图片优化:小于 4KB 的 SVG 被转为 base64 内联到 JS 包中,减少请求数;大于阈值的图片会输出到 dist/assets 目录并自动加哈希指纹。
  • 代码分割:通过 manualChunks 将 React 相关依赖单独拆分为 react-vendor chunk,利用浏览器长期缓存减少重复下载。

运行与验证

在项目根目录执行以下命令:


npm install
npm run build

构建完成后,检查 dist/ 目录结构,预期应包含:

  • index.html:入口 HTML,自动注入打包后的 JS/CSS 引用。
  • assets/ 目录:包含 index-*.js、react-vendor-*.js、index-*.css 等文件,文件名带内容哈希。
  • SVG 文件不会单独出现在 dist/assets 中,因为它小于 4KB 已被内联。

执行 npm run preview 启动本地预览服务器,浏览器访问 http://localhost:4173,页面应正常显示蓝色圆形 V 字 Logo 与标题文字。打开浏览器开发者工具的网络面板,刷新页面,可观察到:

  • JS 被拆分为两个请求(业务代码与 react-vendor),CSS 为单独请求。
  • 没有单独的 SVG 网络请求,证明图片已内联。

判定标准:若页面渲染正常、网络面板中无 SVG 请求、且 JS 被拆分为两个 chunk,则说明构建流程配置成功,JS/CSS/图片资源的打包与优化目标达成。

Vite 构建流程与产物结构 源码 (src/) main.jsx (入口) App.jsx (JSX组件) global.css (全局样式) app.module.css (CSS Modules) logo.svg (图片资源) vite.config.js (构建配置) Vite 生产构建 JSX → JavaScript 编译 (Rollup + esbuild) CSS 提取与 Modules 处理 (类名哈希 + 代码分割) 图片内联 / 指纹命名 (<4KB base64, >4KB 哈希) 代码分割 manualChunks (react-vendor 独立 chunk) 压缩与优化 (JS/CSS minify) 构建产物 (dist/) index.html (入口) assets/index-*.js (业务代码) assets/react-vendor-*.js assets/index-*.css SVG 已内联,无独立文件 文件名含内容哈希 验证:npm run build → npm run preview → 检查网络面板无 SVG 请求、JS 分两个 chunk