Frontend Engineering Overview
Mở đầu
Sao FE từ "viết file HTML đơn giản" trở thành "engineering chuyên ngành" với cả ngàn tool? Vì project ngày càng phức tạp, cần build, transform, optimize, automate. Chương này dẫn bạn từ "manual workshop" → "modern factory".
1. Sao cần "engineering"?
Project nhỏ (1-2 file HTML)
- Viết HTML thẳng, mở browser xem
- Đủ rồi, không cần gì
Project lớn (vài trăm component)
- Code cần modularize (ES Modules)
- Có TypeScript, Sass, Vue/JSX (browser không hiểu thẳng)
- Cần test, lint, format
- Bundle phải nhỏ
- Multi-env (dev/staging/prod)
- Multi-team collaborate
→ Cần chain tool tự động hoá: build, transform, bundle, optimize, deploy.
2. Core concept: Transpile, Bundle, Build
2.1 Transpile (translate)
Code bạn viết ≠ code browser execute. Cần "translator":
- TypeScript → JavaScript
- Sass/Less → CSS
- Vue SFC (.vue) → JavaScript
- JSX (React) → JavaScript
- ES2024+ features → ES5 (cho browser cũ)
Tool: TypeScript compiler, Babel, Sass, esbuild, SWC.
2.2 Bundle (đóng gói)
Project có 100 file .js. Browser load 100 request = chậm. Bundle = merge thành ít file (vd 1-5 file).
Bundle còn xử:
- Tree shaking: loại code không dùng
- Minify: compress (xoá space, rename variable)
- Code splitting: chia bundle theo route/feature
Tool: Webpack, Rollup, Parcel, Vite, esbuild, Bun.
2.3 Build (full process)
Build = transpile + bundle + optimize + assets handling.
npm run build
# →
# 1. Type check (tsc)
# 2. Transpile TS/Vue/JSX → JS
# 3. Transpile Sass → CSS
# 4. Bundle modules
# 5. Minify, tree shake
# 6. Hash filename (cache busting)
# 7. Output → dist/3. Thực chiến: team evolution
Stage 1: No tools (2010)
<script src="jquery.js"></script>
<script src="app.js"></script>
<script src="utils.js"></script>Vấn đề: order load matter, global pollution, không modularize.
Stage 2: Webpack (2015-2020)
npm install webpack webpack-cli
npx webpack
# Wait 30s...☕
# [INFO] Compiled successfully in 30123ms
# Sửa code → save → wait 5s → finally thấyLợi: modularize, transpile, bundle. Hại: setup phức tạp, dev server chậm.
Stage 3: Vite (2020+)
npm create vite@latest
npm install
npm run dev
# Wait 300ms...không kịp react đã xong
# [INFO] ready in 312ms
# Sửa code → save → instantLợi: cực nhanh, config đơn giản, modern.
4. Sao Vite nhanh thế?
4.1 Dev mode: native ESM
Browser hiện đại support ES Modules native. Vite không bundle dev:
<script type="module" src="/src/main.js"></script>Browser request main.js → Vite chỉ transpile file đó on-demand → trả về. Không pre-bundle toàn bộ.
Webpack: bundle hết → start server (chậm) Vite: start server ngay → on-demand compile (cực nhanh)
4.2 Production: Rollup
Production thì cần bundle (browser cũ + perf). Vite dùng Rollup.
4.3 Pre-bundle dependencies với esbuild
Lib node_modules (vd lodash, react) Vite pre-bundle 1 lần bằng esbuild (Go-based, cực nhanh).
# esbuild bundle 10x-100x faster than Webpack/Rollup5. Webpack: Loader + Plugin
5.1 Loader: transform 1 loại file
// webpack.config.js
module.exports = {
module: {
rules: [
{ test: /\.tsx?$/, use: 'ts-loader' }, // TS → JS
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }, // CSS
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
{ test: /\.(png|jpg|svg)$/, type: 'asset/resource' }
]
}
}5.2 Plugin: extend chức năng
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' }),
new MiniCssExtractPlugin()
]
}6. Vite config template
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' // hoặc @vitejs/plugin-react
import path from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src') // import '@/utils'
}
},
server: {
port: 3000,
proxy: {
'/api': 'http://localhost:8080' // Backend API proxy
}
},
build: {
outDir: 'dist',
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'] // Split chunk
}
}
}
}
})6.1 SourceMap
Production code đã minify (a.b.c = 1; var x = function(){}). Debug khó!
SourceMap = file map giữa minified code và source. DevTools dùng để hiện source khi debug.
// vite.config.js
build: {
sourcemap: true // dev: true mặc định, prod: tuỳ
}Lưu ý: sourcemap public = lộ source code. Cân nhắc:
'hidden-source-map': gen nhưng không reference trong code- Upload sourcemap riêng cho Sentry, không expose public
6.2 Asset fingerprint
Output filename có hash:
app.[hash].js → app.a3f5b9.jsKhi code đổi, hash đổi → URL đổi → browser fetch lại. Code không đổi → URL giữ → browser dùng cache (cực nhanh).
// Vite default: filename hash auto
build: {
rollupOptions: {
output: {
entryFileNames: 'assets/[name].[hash].js',
chunkFileNames: 'assets/[name].[hash].js',
assetFileNames: 'assets/[name].[hash].[ext]'
}
}
}7. Engineering toolchain
7.1 Package manager
- npm: default Node.js
- pnpm: nhanh hơn, save disk (hard link)
- yarn: alternative, classic
- bun: rất nhanh, all-in-one (runtime + manager)
7.2 Linter + Formatter
# ESLint: tìm bug, code style
npm install -D eslint @typescript-eslint/parser
# Prettier: format code
npm install -D prettier
# .prettierrc
{
"semi": false,
"singleQuote": true,
"tabWidth": 2
}7.3 Type check
# TypeScript
npm install -D typescript
npx tsc --noEmit # Type check only
# Vue + TS
npm install -D vue-tsc
npx vue-tsc --noEmit7.4 Testing
- Unit: Vitest (mới), Jest (classic)
- Component: Vitest + Testing Library
- E2E: Playwright (best), Cypress (popular)
npm install -D vitest @testing-library/vue7.5 Git hooks
# Husky + lint-staged: chạy lint trước commit
npm install -D husky lint-staged
# .husky/pre-commit
npx lint-staged
# package.json
"lint-staged": {
"*.{js,ts,vue}": ["eslint --fix", "prettier --write"]
}7.6 CI/CD
# .github/workflows/ci.yml
name: CI
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with: { node-version: 20 }
- run: npm ci
- run: npm run lint
- run: npm run type-check
- run: npm test
- run: npm run build8. Tổng kết
Engineering = automate + standardize toàn FE workflow.
Chain tool 2026 typical:
- Package manager: pnpm hoặc bun
- Build tool: Vite
- Framework: Vue 3 / React / Svelte
- TypeScript: must
- Linter: ESLint (+ Prettier format)
- Test: Vitest (unit) + Playwright (E2E)
- Git hooks: Husky + lint-staged
- CI: GitHub Actions / GitLab CI
- Deploy: Vercel / Netlify / Cloudflare Pages
- Monitor: Sentry / Vercel Analytics
2026 cho VN dev
- Vite is king: tốc độ + DX không có đối thủ
- Bun runtime: nhanh hơn Node 3-5x, có thể thay npm + vite cho 1 số project
- Turbopack (Next.js): Rust-based, faster Webpack
- Rsbuild (Rspack-based): Webpack-compatible nhưng Rust, nhanh
- Storybook: dev + showcase component isolated
- Changesets: version + changelog cho monorepo
- VN setup chuẩn: Vite + Vue 3 hoặc Next.js, pnpm, Vercel deploy, GitHub Actions CI
Anti-pattern
- Không có build → import từng
<script>(project nhỏ thì OK) - Webpack config 500 dòng → dùng template (vue-cli, create-react-app) hoặc switch Vite
- Không lint, không format → team chaos nhanh
- Không test → bug tăng theo dependency
- Không CI → deploy phải manual, dễ sót