前端工程化¶
📚 章节目标¶
本章节将全面介绍前端工程化的核心技术和工具,包括 Webpack 、 Vite 、 Rollup 、模块化等,帮助学习者掌握前端工程化的核心方法。
学习目标¶
- 理解前端工程化的核心概念
- 掌握 Webpack 的深度配置
- 掌握 Vite 的构建优化
- 掌握 Rollup 的打包技术
- 理解模块化规范
- 掌握工程化最佳实践
🏗️ 前端工程化概述¶
1. 什么是前端工程化¶
JavaScript
// 前端工程化的核心要素
// 1. 模块化:将代码拆分成独立的模块
// 2. 组件化:将UI拆分成可复用的组件
// 3. 规范化:制定代码规范和项目规范
// 4. 自动化:自动化构建、测试、部署
// 5. 优化化:性能优化、代码优化
// 示例:模块化
// utils.js
export function formatDate(date) {
return new Date(date).toLocaleDateString();
}
// main.js
import { formatDate } from './utils';
console.log(formatDate(new Date()));
// 示例:组件化
// Button.jsx
export function Button({ children, onClick }) {
return <button onClick={onClick}>{children}</button>;
}
// App.jsx
import { Button } from './Button';
function App() {
return <Button onClick={() => console.log('clicked')}>Click me</Button>;
}
2. 工程化工具链¶
JavaScript
// 前端工程化工具链
// 1. 包管理器:npm, yarn, pnpm
// 2. 构建工具:Webpack, Vite, Rollup
// 3. 代码规范:ESLint, Prettier
// 4. 测试工具:Jest, Cypress, Playwright
// 5. CI/CD:GitHub Actions, GitLab CI, Jenkins
// 示例:使用pnpm
pnpm install
pnpm add react
pnpm add -D typescript
// 示例:使用ESLint
npx eslint src/
npx eslint src/ --fix
// 示例:使用Prettier
npx prettier --write src/
📦 Webpack 深度配置¶
1. Webpack 基础¶
1.1 基本配置¶
JavaScript
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 入口文件
entry: './src/index.js',
// 输出配置
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
// 模式
mode: 'production',
// Loader配置
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|jpg|jpeg|gif|svg)$/,
type: 'asset/resource',
},
],
},
// 插件配置
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
1.2 多入口配置¶
JavaScript
// webpack.config.js
module.exports = {
entry: {
main: './src/index.js',
vendor: './src/vendor.js',
},
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
};
2. Loader 配置¶
2.1 JavaScript Loader¶
JavaScript
// babel-loader配置
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: [
'@babel/plugin-transform-runtime',
'@babel/plugin-transform-class-properties',
],
},
},
},
],
},
};
// .babelrc
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["> 1%", "last 2 versions", "not dead"]
}
}],
"@babel/preset-react",
"@babel/preset-typescript"
],
"plugins": [
"@babel/plugin-transform-runtime",
"@babel/plugin-transform-class-properties"
]
}
2.2 CSS Loader¶
JavaScript
// CSS Loader配置
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
],
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader',
],
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader',
],
},
],
},
};
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer'),
require('cssnano'),
],
};
2.3 CSS 现代特性(2024+)¶
随着浏览器对现代 CSS 特性的全面支持,以下特性已可在生产环境中使用:
CSS
/* 1. Container Queries - 容器查询(2023+ 全支持)*/
/* 允许根据父容器尺寸而非视口尺寸进行响应式设计 */
.card-container {
container-type: inline-size;
container-name: card;
}
/* 当容器宽度 >= 400px 时应用样式 */
@container card (min-width: 400px) {
.card {
display: flex;
gap: 1rem;
}
.card-image {
width: 40%;
}
}
/* 2. CSS Nesting - 原生嵌套语法(2023+ 全支持)*/
/* 无需预处理器即可使用嵌套 */
.article {
padding: 1rem;
& h2 {
font-size: 1.5rem;
color: #333;
}
& p {
line-height: 1.6;
& a {
color: blue;
text-decoration: underline;
}
}
/* 媒体查询也可嵌套 */
@media (min-width: 768px) {
padding: 2rem;
}
}
/* 3. :has() 选择器 - 父选择器(2023+ 全支持)*/
/* CSS "父选择器",可根据子元素状态选择父元素 */
/* 选择包含 img 的 figure */
figure:has(img) {
border: 1px solid #ddd;
}
/* 选择有 :checked 子元素的 label */
label:has(input:checked) {
background-color: lightblue;
}
/* 选择相邻兄弟有 :invalid 的表单组 */
.form-group:has(+ .form-group input:invalid) {
border-left: 3px solid red;
}
/* 4. subgrid - 子网格(2023+ 全支持)*/
.grid-parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.grid-child {
display: grid;
grid-template-columns: subgrid; /* 继承父级的列轨道 */
grid-column: span 3;
}
/* 5. @layer - 层叠层(2022+ 全支持)*/
/* 控制样式优先级,解决特异性问题 */
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; }
}
@layer components {
.btn { padding: 0.5rem 1rem; }
}
@layer utilities {
.mt-4 { margin-top: 1rem !important; }
}
/* 6. color-mix() - 颜色混合(2023+ 全支持)*/
.button {
--brand: #3b82f6;
background: var(--brand);
&:hover {
/* 混合 20% 黑色实现暗化效果 */
background: color-mix(in srgb, var(--brand), black 20%);
}
}
JavaScript
// 现代 CSS 浏览器支持检测
const supportsContainerQueries = CSS.supports('container-type', 'inline-size');
const supportsNesting = CSS.supports('selector(&)');
const supportsHas = CSS.supports('selector(:has(*))');
console.log('Container Queries:', supportsContainerQueries); // true (Chrome 105+)
console.log('CSS Nesting:', supportsNesting); // true (Chrome 120+)
console.log(':has() Selector:', supportsHas); // true (Chrome 105+)
2.4 资源 Loader¶
JavaScript
// 资源Loader配置
module.exports = {
module: {
rules: [
// 图片处理
{
test: /\.(png|jpg|jpeg|gif|svg|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024, // 8kb以下转base64
},
},
generator: {
filename: 'images/[name].[hash:6][ext]',
},
},
// 字体处理
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash:6][ext]',
},
},
// 媒体文件
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)$/,
type: 'asset/resource',
generator: {
filename: 'media/[name].[hash:6][ext]',
},
},
],
},
};
3. Plugin 配置¶
3.1 HTML Plugin¶
JavaScript
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
filename: 'index.html',
title: 'My App',
minify: {
collapseWhitespace: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
useShortDoctype: true,
},
}),
],
};
3.2 清理插件¶
JavaScript
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ['**/*', '!static-files/**'],
}),
],
};
3.3 环境变量插件¶
JavaScript
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.API_URL': JSON.stringify(process.env.API_URL),
}),
],
};
4. 优化配置¶
4.1 代码分割¶
JavaScript
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
},
common: {
minChunks: 2,
priority: 5,
reuseExistingChunk: true,
},
},
},
runtimeChunk: {
name: 'runtime',
},
},
};
4.2 Tree Shaking¶
JavaScript
module.exports = {
optimization: {
usedExports: true,
sideEffects: false,
minimize: true,
},
};
// package.json
{
"sideEffects": false
}
4.3 压缩优化¶
JavaScript
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
}),
new CssMinimizerPlugin(),
],
},
};
⚡ Vite 构建优化¶
1. Vite 基础¶
1.1 基本配置¶
JavaScript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
server: {
port: 3000,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
build: {
outDir: 'dist',
assetsDir: 'assets',
sourcemap: false,
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
},
},
},
},
});
1.2 环境变量¶
JavaScript
// .env
VITE_API_URL=https://api.example.com
// .env.development
VITE_API_URL=http://localhost:8080
// .env.production
VITE_API_URL=https://api.example.com
// 在代码中使用
const apiUrl = import.meta.env.VITE_API_URL;
2. Vite 插件¶
2.1 常用插件¶
JavaScript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import vitePluginImp from 'vite-plugin-imp';
import legacy from '@vitejs/plugin-legacy';
import viteCompression from 'vite-plugin-compression';
export default defineConfig({
plugins: [
react(),
// 按需引入
vitePluginImp({
libList: [
{
libName: 'antd',
style: (name) => `antd/es/${name}/style`,
},
],
}),
// 兼容旧浏览器
legacy({
targets: ['defaults', 'not IE 11'],
}),
// Gzip压缩
viteCompression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: 'gzip',
ext: '.gz',
}),
],
});
2.2 自定义插件¶
JavaScript
// vite.config.js
import { defineConfig } from 'vite';
function myPlugin() {
return {
name: 'my-plugin',
transform(code, id) {
if (id.endsWith('.js')) {
// 转换代码
return code.replace(/console\.log\(/g, 'logger.log(');
}
},
};
}
export default defineConfig({
plugins: [myPlugin()],
});
3. Vite 优化¶
3.1 依赖预构建¶
JavaScript
// vite.config.js
export default defineConfig({
optimizeDeps: {
include: ['react', 'react-dom'],
exclude: ['your-custom-dep'],
},
});
3.2 构建优化¶
JavaScript
// vite.config.js
export default defineConfig({
build: {
// 代码分割
rollupOptions: {
output: {
manualChunks: (id) => {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
},
},
},
// 压缩配置
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
// Chunk大小警告
chunkSizeWarningLimit: 1000,
},
});
⚡ Vite 6 新特性¶
版本说明: Vite 6 ( 2024 年末发布)引入 Environment API ,是该版本最重要的架构升级。
1. Environment API¶
TypeScript
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
// Vite 6 核心新特性:多 Environment 配置
// 可同时处理 client / server(SSR)/ 自定义 Worker 环境
environments: {
client: {
// 浏览器环境默认配置
build: {
outDir: 'dist/client',
},
},
server: {
// Node.js SSR 环境
resolve: {
// SSR 环境使用 node 导出条件
conditions: ['node'],
externalConditions: ['node'],
},
build: {
outDir: 'dist/server',
},
},
worker: {
// Web Worker 专属环境
webCompatible: true,
},
},
plugins: [react()],
});
2. 在插件中使用 Environment API¶
TypeScript
// Environment API 让插件可以感知当前运行环境,实现差异化处理
import type { Plugin } from 'vite';
function myPlugin(): Plugin {
return {
name: 'my-env-aware-plugin',
// resolveId 钩子现在可以访问 this.environment
resolveId(id) {
if (this.environment.name === 'client') {
// 浏览器环境特定处理
if (id === 'virtual:config') return id;
}
if (this.environment.name === 'server') {
// SSR 环境特定处理
if (id === 'virtual:server-config') return id;
}
},
load(id) {
if (id === 'virtual:config') {
const ssr = this.environment.name !== 'client';
return `export const isSSR = ${ssr};`;
}
},
};
}
3. Vite 6 其他改进¶
TypeScript
// vite.config.ts
export default defineConfig({
// 1. resolve.conditions 新增 'module' 和 'default' 条件支持
resolve: {
conditions: ['browser', 'module', 'import', 'default'],
},
build: {
// 2. CSS 代码分割更智能(默认按使用方自动分割 CSS chunk)
cssCodeSplit: true,
// 3. 内置 Rollup 4 支持更好的 treeshaking 和更小的产物
rollupOptions: {
// Rollup 4 的 output.experimentalMinChunkSize(减少碎片化 chunk)
output: {
experimentalMinChunkSize: 10_000, // bytes
},
},
},
// 4. preview 命令新增 --outDir 参数支持多环境静态预览
preview: {
port: 5173,
},
// 5. 废弃提醒:Vite 6 移除了对 CommonJS API(createServer 等)
// 从 CJS 模块引入的支持,需迁移到 ESM
});
// Vite 6 迁移注意事项
// - default import 了 Vite 配置需改用 ESM import(import { defineConfig } from 'vite')
// - sass-embedded 现在是 sass 的默认实现(旧 node-sass 不再支持)
// - this.environment.consumer 值从 'browser' 改为 'client'
� Turbopack¶
版本说明:Turbopack 在 Next.js 15 中正式稳定,已成为
next dev的默认打包器。基于 Rust 的增量式打包引擎,大型项目下比 Webpack 快数倍到数十倍。
1. Turbopack 核心概念¶
Text Only
体系结构:
└── Turbopack(调度层)
├── Turbo Engine(增量计算引擎)
│ ├── Task Graph(任务依赖图)
│ ├── Cache Layer(函数级缓存)
│ └── Parallel Execution(Rust async)
├── SWC(JS/TS 转译)
└── 内置 CSS/资源处理
关键特性:
- 函数级缓存:仅重新计算已变更的函数输出(非文件级)
- 惰性计算:只构建当前请求的模块
- 跨进程缓存:持久化到磁盘,冷启动同样受益
2. 在 Next.js 15 中使用¶
Bash
# Next.js 15 中 turbopack 已成为 next dev 的默认引擎
npx next dev # 默认使用 Turbopack
npx next dev --turbo # 明确开启(与上一行等价)
npx next build # 生产构建仍使用 Webpack(Turbopack 不支持 build)
JavaScript
// next.config.js——当前 Turbopack 配置项
/** @type {import('next').NextConfig} */
const nextConfig = {
// Next.js 15 中 turbopack 配置已移至顶层
turbopack: {
// 自定义路径别名(等同于 Webpack resolve.alias)
resolveAlias: {
'@components': './src/components',
'@utils': './src/utils',
},
// 自定义文件扩展名解析顺序
resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
// 自定义 Loaders(命名规则跟 Webpack loaders 不同)
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
'*.mdx': {
loaders: ['./my-mdx-loader.js'],
as: '*.js',
},
},
},
};
module.exports = nextConfig;
3. Turbopack vs Webpack vs Vite 性能对比¶
| 指标 | Webpack 5 | Vite 6 | Turbopack |
|---|---|---|---|
| 冷启动时间(大型项目) | ~30-60s | ~1-3s | ~0.5-1s |
| HMR 速度 | ~1-5s | <100ms | <50ms |
| 内存占用 | 高 | 中 | 低(Rust) |
| 跨进程缓存 | ✅ filesystem cache | ❌ | ✅ persistent |
| 完整生产构建 | ✅ | ✅ | ❌(开发阶段) |
| 生态成熟度 | ✅ 成熟 | ✅ 成熟 | ⚠️ 发展中 |
⚠️ 使用确认:Turbopack 面向 Next.js 项目的开发阶段;独立项目依然推荐 Vite。Turborepo(构建流水线工具)与 Turbopack(模块打包工具)是两个独立的项目。
�🔄 Rollup 打包技术¶
1. Rollup 基础¶
1.1 基本配置¶
JavaScript
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import terser from '@rollup/plugin-terser';
export default {
input: 'src/index.ts',
output: [
{
file: 'dist/bundle.js',
format: 'cjs',
exports: 'auto',
},
{
file: 'dist/bundle.esm.js',
format: 'esm',
},
{
file: 'dist/bundle.umd.js',
format: 'umd',
name: 'MyLibrary',
},
],
plugins: [
resolve(),
commonjs(),
typescript(),
terser(),
],
};
1.2 多入口配置¶
JavaScript
// rollup.config.js
export default {
input: {
main: 'src/index.ts',
utils: 'src/utils/index.ts',
},
output: {
dir: 'dist',
format: 'esm',
entryFileNames: '[name].js',
chunkFileNames: '[name]-[hash].js',
},
};
2. Rollup 插件¶
2.1 常用插件¶
JavaScript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import json from '@rollup/plugin-json';
import babel from '@rollup/plugin-babel';
import replace from '@rollup/plugin-replace';
import alias from '@rollup/plugin-alias';
import postcss from 'rollup-plugin-postcss';
export default {
plugins: [
// 路径别名
alias({
entries: [
{ find: '@', replacement: './src' },
],
}),
// 解析node_modules
resolve({
browser: true,
}),
// 转换CommonJS
commonjs(),
// TypeScript支持
typescript(),
// JSON支持
json(),
// Babel转译
babel({
babelHelpers: 'bundled',
exclude: 'node_modules/**',
}),
// 环境变量替换
replace({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
preventAssignment: true,
}),
// PostCSS
postcss(),
],
};
2.2 自定义插件¶
JavaScript
// rollup.config.js
function myPlugin(options = {}) {
return {
name: 'my-plugin',
transform(code, id) {
if (id.endsWith('.js')) {
// 转换代码
return {
code: code.replace(/console\.log\(/g, 'logger.log('),
map: null,
};
}
},
generateBundle(options, bundle) {
// 生成bundle时执行
console.log('Bundle generated');
},
};
}
export default {
plugins: [myPlugin()],
};
3. Rollup 优化¶
3.1 Tree Shaking¶
JavaScript
// rollup.config.js
export default {
treeshake: {
moduleSideEffects: false,
propertyReadSideEffects: false,
unknownGlobalSideEffects: false,
},
};
3.2 代码分割¶
JavaScript
// rollup.config.js
export default {
output: {
manualChunks: (id) => { // 箭头函数:简洁的函数语法
if (id.includes('node_modules')) {
return 'vendor';
}
},
},
};
📦 模块化规范¶
1. CommonJS¶
JavaScript
// 导出
// utils.js
function formatDate(date) {
return new Date(date).toLocaleDateString();
}
function formatNumber(num) {
return num.toLocaleString();
}
module.exports = {
formatDate,
formatNumber,
};
// 或者
exports.formatDate = formatDate;
exports.formatNumber = formatNumber;
// 导入
const { formatDate, formatNumber } = require('./utils'); // 解构赋值:从对象/数组提取值
// 或者
const utils = require('./utils'); // const不可重新赋值;let块级作用域变量
utils.formatDate(new Date());
2. ES Modules¶
JavaScript
// 导出
// utils.js
export function formatDate(date) {
return new Date(date).toLocaleDateString();
}
export function formatNumber(num) {
return num.toLocaleString();
}
// 默认导出
export default function logger(message) {
console.log(message);
}
// 导入
import { formatDate, formatNumber } from './utils';
import logger from './logger';
// 或者
import * as utils from './utils';
utils.formatDate(new Date());
// 动态导入
button.addEventListener('click', async () => { // async定义异步函数;await等待Promise完成
const module = await import('./heavy-module.js'); // await等待异步操作完成
module.doSomething();
});
3. UMD¶
JavaScript
// UMD模块
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['exports'], factory);
} else if (typeof exports === 'object') {
// CommonJS
factory(exports);
} else {
// Browser globals
factory(root.myLibrary = {});
}
}(this, function (exports) {
exports.formatDate = function(date) {
return new Date(date).toLocaleDateString();
};
exports.formatNumber = function(num) {
return num.toLocaleString();
};
}));
🛠️ 工程化最佳实践¶
1. 项目结构¶
Text Only
project/
├── public/ # 静态资源
│ ├── index.html
│ └── favicon.ico
├── src/ # 源代码
│ ├── assets/ # 资源文件
│ ├── components/ # 组件
│ ├── pages/ # 页面
│ ├── services/ # 服务
│ ├── utils/ # 工具函数
│ ├── hooks/ # 自定义Hooks
│ ├── store/ # 状态管理
│ ├── router/ # 路由配置
│ ├── styles/ # 样式文件
│ └── index.js # 入口文件
├── tests/ # 测试文件
├── .eslintrc.js # ESLint配置
├── .prettierrc.js # Prettier配置
├── .gitignore # Git忽略文件
├── package.json # 项目配置
└── README.md # 项目说明
2. 代码规范¶
2.1 ESLint 配置¶
JavaScript
// .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['react', '@typescript-eslint', 'prettier'],
rules: {
'react/react-in-jsx-scope': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'prettier/prettier': 'error',
},
settings: {
react: {
version: 'detect',
},
},
};
2.2 Prettier 配置¶
JavaScript
// .prettierrc.js
module.exports = {
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'es5',
printWidth: 80,
arrowParens: 'always',
endOfLine: 'lf',
};
3. Git 工作流¶
Bash
# 分支策略
# main - 主分支
# develop - 开发分支
# feature/* - 功能分支
# hotfix/* - 紧急修复分支
# 工作流程
# 1. 从develop创建功能分支
git checkout -b feature/new-feature
# 2. 开发并提交
git add .
git commit -m "feat: add new feature"
# 3. 推送到远程
git push origin feature/new-feature
# 4. 创建Pull Request
# 5. 代码审查
# 6. 合并到develop
# 7. 定期合并到main
4. CI/CD 配置¶
YAML
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Test
run: npm test
- name: Build
run: npm run build
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.ORG_ID }}
vercel-project-id: ${{ secrets.PROJECT_ID }}
vercel-args: '--prod'
📝 练习题¶
1. 基础题¶
题目 1 :配置 Webpack 处理 TypeScript
JavaScript
// webpack.config.js
module.exports = {
// 配置Webpack处理TypeScript
module: {
rules: [
// 添加TypeScript loader
],
},
};
2. 进阶题¶
题目 2 :配置 Vite 实现按需引入
JavaScript
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
// 配置按需引入插件
],
});
3. 面试题¶
题目 3 :比较 Webpack 和 Vite 的区别
JavaScript
// 答案要点:
// 1. Webpack使用bundle模式,Vite使用ESM模式
// 2. Webpack冷启动慢,Vite冷启动快
// 3. Webpack热更新中等,Vite热更新快
// 4. Webpack配置复杂,Vite配置简单
// 5. Webpack生态成熟,Vite生态快速发展
// 6. Webpack适合所有项目,Vite适合现代项目
🎯 本章总结¶
本章节全面介绍了前端工程化的核心技术和工具,包括 Webpack 、 Vite 、 Rollup 、模块化等。关键要点:
- 工程化概念:理解前端工程化的核心要素
- Webpack:掌握 Webpack 的深度配置和优化
- Vite:掌握 Vite 的构建优化和插件
- Rollup:掌握 Rollup 的打包技术
- 模块化:理解 CommonJS 、 ES Modules 、 UMD 规范
- 最佳实践:掌握项目结构、代码规范、 Git 工作流、 CI/CD 配置
下一步将深入学习前端测试技术。