OXC Full Stack Practice: Building a Lightning-Fast Frontend Development Environment from Scratch
Combine OXC's six modules to build a complete lightning-fast frontend development environment, experience the performance leap brought by Rust toolchain.
OXC Full Stack Practice: Building a Lightning-Fast Frontend Development Environment from Scratch
Congratulations on making it to the final article! In the previous seven articles, we learned about OXC’s six modules one by one:
- Oxlint: Code linting, 50x faster than ESLint
- Oxfmt: Code formatting, 20x faster than Prettier
- Parser: Code parsing, 20x faster than Babel Parser
- Transformer: Code transformation, 18x faster than Babel
- Minifier: Code minification, 5x faster than Terser
- Resolver: Module resolution, 5x faster than enhanced-resolve
Today, we’ll combine these modules to build a complete lightning-fast frontend development environment!
Review of Six Modules
Before we start the practical work, let’s quickly review each module’s core value:
| Module | Purpose | Replaces | Typical Scenario |
|---|---|---|---|
| Oxlint | Code linting | ESLint | Real-time checking during development, CI pipeline |
| Oxfmt | Code formatting | Prettier | Auto-format on save, format before commit |
| Parser | Code parsing | @babel/parser | Build code tools, AST analysis |
| Transformer | Code transformation | Babel | TypeScript compilation, JSX transformation |
| Minifier | Code minification | Terser | Production build optimization |
| Resolver | Module resolution | enhanced-resolve | Custom build tools, path aliases |
Applicable Scenario Summary
Development Phase
├── Oxlint → Real-time code checking
├── Oxfmt → Format on save
└── Resolver → Module path resolution
Build Phase
├── Parser → Parse code to generate AST
├── Transformer → TypeScript/JSX transformation
├── Resolver → Dependency resolution
└── Minifier → Production code minification
Practical: Building a Complete Workflow
Let’s start from scratch to build a frontend project using the full OXC stack.
Step 1: Create Project
mkdir oxc-project
cd oxc-project
npm init -y
Step 2: Install Dependencies
# Core dependencies
npm install @oxc/parser @oxc/transform @oxc/minifier @oxc/resolver oxlint oxfmt --save-dev
# TypeScript
npm install typescript --save-dev
# Dev server (optional)
npm install vite --save-dev
Step 3: Create Project Structure
oxc-project/
├── src/
│ ├── components/
│ │ ├── Button.tsx
│ │ └── index.ts
│ ├── utils/
│ │ ├── date.ts
│ │ └── index.ts
│ ├── App.tsx
│ └── main.ts
├── dist/
├── oxlint.json
├── .oxfmtrc
├── tsconfig.json
└── package.json
Step 4: Configure Oxlint
Create oxlint.json:
{
"rules": {
"no-unused-vars": "error",
"no-console": "warn",
"no-debugger": "error",
"no-var": "error",
"prefer-const": "warn",
"eqeqeq": ["error", "always"]
}
}
Step 5: Configure Oxfmt
Create .oxfmtrc:
{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"bracketSpacing": true,
"arrowParens": "always"
}
Step 6: Configure TypeScript
Create tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"outDir": "./dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Step 7: Create Example Code
src/components/Button.tsx:
import React from "react";
interface ButtonProps {
children: React.ReactNode;
onClick?: () => void;
variant?: "primary" | "secondary";
}
export function Button({ children, onClick, variant = "primary" }: ButtonProps) {
const baseStyles =
"px-4 py-2 rounded font-medium transition-colors focus:outline-none focus:ring-2";
const variantStyles = {
primary: "bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500",
secondary:
"bg-gray-200 text-gray-800 hover:bg-gray-300 focus:ring-gray-400",
};
return (
<button className={`${baseStyles} ${variantStyles[variant]}`} onClick={onClick}>
{children}
</button>
);
}
src/utils/date.ts:
/**
* Format date
*/
export function formatDate(date: Date, format = "YYYY-MM-DD"): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return format.replace("YYYY", String(year)).replace("MM", month).replace("DD", day);
}
/**
* Get relative time
*/
export function getRelativeTime(date: Date): string {
const now = new Date();
const diff = now.getTime() - date.getTime();
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) return `${days} days ago`;
if (hours > 0) return `${hours} hours ago`;
if (minutes > 0) return `${minutes} minutes ago`;
return "just now";
}
src/App.tsx:
import React from "react";
import { Button } from "@/components/Button";
import { formatDate } from "@/utils/date";
export function App() {
const today = new Date();
const handleClick = () => {
console.log("Button clicked!");
};
return (
<div className="min-h-screen bg-gray-100 p-8">
<h1 className="text-3xl font-bold text-gray-900 mb-4">OXC Demo Project</h1>
<p className="text-gray-600 mb-4">Today is: {formatDate(today)}</p>
<div className="space-x-4">
<Button onClick={handleClick}>Primary Button</Button>
<Button variant="secondary">Secondary Button</Button>
</div>
</div>
);
}
src/main.ts:
import React from "react";
import { createRoot } from "react-dom/client";
import { App } from "./App";
const container = document.getElementById("root");
if (container) {
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
Step 8: Configure npm Scripts
Update package.json:
{
"name": "oxc-project",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "npm run lint && npm run format:check && npm run compile",
"lint": "oxlint ./src",
"lint:fix": "oxlint ./src --fix",
"format": "oxfmt \"./src/**/*.{ts,tsx,js,jsx}\" --write",
"format:check": "oxfmt \"./src/**/*.{ts,tsx,js,jsx}\" --check",
"compile": "node scripts/build.js",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@oxc/parser": "^0.15.0",
"@oxc/transform": "^0.15.0",
"@oxc/minifier": "^0.15.0",
"@oxc/resolver": "^0.15.0",
"oxlint": "^0.15.0",
"oxfmt": "^0.15.0",
"typescript": "^5.0.0",
"vite": "^5.0.0"
}
}
Complete Build Script
Create scripts/build.js:
// scripts/build.js
import { transformSync } from "@oxc/transform";
import { minifySync } from "@oxc/minifier";
import { Resolver } from "@oxc/resolver";
import { parseSync } from "@oxc/parser";
import fs from "fs";
import path from "path";
const config = {
srcDir: "./src",
outDir: "./dist",
extensions: [".ts", ".tsx", ".js", ".jsx"],
target: "es2020",
};
// Create resolver
const resolver = new Resolver({
projectRoot: process.cwd(),
alias: {
"@": "./src",
},
extensions: config.extensions,
});
// Compile single file
function compileFile(inputPath, outputPath) {
console.log(`📝 Compiling: ${path.relative(process.cwd(), inputPath)}`);
const code = fs.readFileSync(inputPath, "utf-8");
const lang = inputPath.endsWith(".tsx") ? "tsx" : inputPath.endsWith(".ts") ? "ts" : "js";
// 1. Parse code (optional, for analysis)
// const ast = parseSync(code, { lang });
// 2. Transform code
const transformed = transformSync(code, {
lang,
target: config.target,
jsx: "automatic",
jsxImportSource: "react",
sourcemap: true,
});
// 3. Minify code (production)
const minified = minifySync(transformed.code, {
compress: true,
mangle: true,
sourcemap: true,
});
// Ensure output directory exists
const outFilePath = outputPath.replace(/\.tsx?$/, ".js");
const outDir = path.dirname(outFilePath);
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir, { recursive: true });
}
// Write files
fs.writeFileSync(outFilePath, minified.code);
if (minified.map) {
fs.writeFileSync(`${outFilePath}.map`, minified.map);
}
const originalSize = Buffer.byteLength(code, "utf-8");
const minifiedSize = Buffer.byteLength(minified.code, "utf-8");
const reduction = ((1 - minifiedSize / originalSize) * 100).toFixed(1);
console.log(` ✅ ${path.basename(outFilePath)} (${reduction}% smaller)`);
}
// Walk directory
function walkDir(dir, callback) {
if (!fs.existsSync(dir)) return;
const files = fs.readdirSync(dir);
for (const file of files) {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
walkDir(filePath, callback);
} else if (config.extensions.some((ext) => file.endsWith(ext))) {
callback(filePath);
}
}
}
// Main build flow
function build() {
console.log("\n🚀 Starting OXC build...\n");
console.log("━".repeat(50));
const startTime = Date.now();
// Clean output directory
if (fs.existsSync(config.outDir)) {
fs.rmSync(config.outDir, { recursive: true });
}
fs.mkdirSync(config.outDir, { recursive: true });
// Compile all files
walkDir(config.srcDir, (inputPath) => {
const relativePath = path.relative(config.srcDir, inputPath);
const outputPath = path.join(config.outDir, relativePath);
compileFile(inputPath, outputPath);
});
const endTime = Date.now();
const duration = endTime - startTime;
console.log("━".repeat(50));
console.log(`\n✨ Build completed in ${duration}ms\n`);
}
// Run build
build();
Performance Improvement Showcase
Let’s compare the performance difference between traditional toolchain and OXC toolchain.
Test Scenario
- Project size: 100 TypeScript files
- Total code: About 20,000 lines
- Environment: MacBook Pro M1
Traditional Toolchain vs OXC Toolchain
| Task | Traditional Tool | Time | OXC Tool | Time | Improvement |
|---|---|---|---|---|---|
| Code linting | ESLint | 25s | Oxlint | 0.4s | 62x |
| Code formatting | Prettier | 2.8s | Oxfmt | 0.15s | 18x |
| TypeScript compilation | tsc | 8s | OXC Transformer | 0.6s | 13x |
| Code minification | Terser | 3.5s | OXC Minifier | 0.6s | 5.8x |
| Total time | - | 39.3s | - | 1.75s | 22x |
CI/CD Time Comparison
| Pipeline Step | Traditional Toolchain | OXC Toolchain |
|---|---|---|
| Install dependencies | 45s | 45s |
| Type checking | 8s | 8s (tsc) |
| Code linting | 25s | 0.4s |
| Build | 12s | 1.5s |
| Test | 20s | 20s |
| Total | 110s | 75s |
CI time reduced by 32%!
Development Experience Improvement
| Scenario | Before | After |
|---|---|---|
| pre-commit hook | 20-30s | 1-2s |
| On-save checking | Perceptible delay | Instant |
| Full project formatting | Need to wait | Almost instant |
| Large project build | Minutes | Seconds |
Learning Path Recommendations
Based on your needs, you can choose different learning paths:
Beginner Path: Improve Daily Development Efficiency
Week 1: Oxlint
├── Replace ESLint in your project
├── Configure VS Code extension
└── Experience the joy of instant checking
Week 2: Oxfmt
├── Replace Prettier in your project
├── Configure format on save
└── Use with lint-staged
Intermediate Path: Deep Dive into Code Processing
Week 3-4: Parser + Transformer
├── Learn AST basics
├── Build code analysis tools with Parser
├── Handle TypeScript with Transformer
└── Try custom code transformations
Advanced Path: Build Tool Development
Week 5-6: Minifier + Resolver
├── Understand code minification principles
├── Learn module resolution mechanisms
├── Try building a simple bundler
└── Deep dive into frontend toolchain
Resource Summary
Official Resources
- 📖 OXC Documentation: https://oxc.en.libdoc.top
- 🌟 GitHub Repository: https://github.com/oxc-project/oxc
- 💬 Discord Community: Join discussions, get help
This Series of Articles
- Introduction to OXC: A New Choice for Frontend Toolchain
- Oxlint Practical Tutorial
- Oxfmt Practical Tutorial
- Parser Tutorial
- Transformer Tutorial
- Minifier Practical Tutorial
- Resolver Tutorial
- This article: Summary Practice
Related Tools
| Tool | Description |
|---|---|
| Vite | Next-gen build tool with OXC support |
| Rolldown | Rust-based Rollup alternative |
| Rspack | Rust-based Webpack alternative |
| Biome | Another Rust frontend toolchain |
Summary
Through these eight articles, we comprehensively learned the OXC toolchain:
Key Takeaways
| Knowledge Point | Description |
|---|---|
| Why Choose OXC | Extreme performance from Rust |
| Oxlint | 50x faster code linting |
| Oxfmt | 20x faster code formatting |
| Parser | Understand AST, build code tools |
| Transformer | TypeScript compilation and JSX transformation |
| Minifier | Production code minification |
| Resolver | Module path resolution |
| Integration | Build complete development environment |
One Sentence Summary
OXC is reshaping the frontend toolchain with Rust speed.
Future Outlook
OXC is still rapidly developing:
- More ESLint rule support
- More complete syntax downleveling
- Plugin system
- More bundler integrations
The future of frontend tooling has arrived.
💡 Final Words:
If you fell in love with OXC through this series, welcome to visit OXC Documentation to learn more, and feel free to give the project a Star on GitHub!
Happy coding! 🚀