前端工程化实践:从复制粘贴到一键生成,xcli 解决了什么问题,又是如何设计的。
bash 体验AI代码助手 代码解读复制代码# 第1步:创建目录
mkdir my-project && cd my-project
# 第2步:初始化 package.json
npm init -y
# 第3步:安装 TypeScript
npm install -D typescript
npx tsc --init
# 然后手动改 tsconfig.json ...
# 第4步:安装 ESLint
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
# 然后创建 .eslintrc.json,配置规则 ...
# 第5步:安装 Prettier
npm install -D prettier eslint-config-prettier
# 然后创建 .prettierrc ...
# 第6步:安装 Vite
npm install -D vite @vitejs/plugin-react
# 然后创建 vite.config.ts ...
# 第7步:配置 browserslist
# 创建 .browserslistrc,写兼容配置 ...
# 第8步:配置 PostCSS
npm install -D postcss autoprefixer
# 创建 postcss.config.js ...
# ... 此处省略 20 步
# 第 N 步:终于跑起来了
npm run dev耗时:约 2 小时
bash 体验AI代码助手 代码解读复制代码npx @jserxiao/xcli init my-project -t react -d
cd my-project
pnpm dev耗时:约 3 分钟
xcli 是一个可插拔的 TypeScript 项目脚手架 CLI 工具。
它的核心理念:配置标准化、可复用、开箱即用。
bash 体验AI代码助手 代码解读复制代码# 全局安装
npm install -g @jserxiao/xcli
# 或者直接用 npx
npx @jserxiao/xcli init my-project根据实际业务场景,我设计了三种模板:
适合开发 npm 包、工具函数库。
perl 体验AI代码助手 代码解读复制代码my-lib/
├── src/
│ └── index.ts # 入口文件
├── dist/ # 编译输出
├── package.json
├── tsconfig.json
└── README.md特性:
基于 pnpm monorepo 的企业级前端项目。
perl 体验AI代码助手 代码解读复制代码my-app/
├── src/ # 主应用源码
│ ├── main.tsx
│ ├── App.tsx
│ ├── pages/ # 页面
│ ├── components/ # 组件
│ ├── router/ # 路由
│ ├── api/ # HTTP 请求
│ │ └── request.ts # Axios/Fetch 封装
│ └── store/ # 状态管理
│ ├── index.ts
│ ├── counterSlice.ts
│ └── middleware/
├── packages/ # pnpm workspace
│ ├── shared/ # 共享工具库
│ └── ui/ # UI 组件库
├── vite.config.ts # Vite 配置
├── eslint.config.js # ESLint Flat Config
├── tsconfig.json
├── postcss.config.js
├── .browserslistrc # 浏览器兼容
└── pnpm-workspace.yaml状态管理可选:
HTTP 请求可选:
同样是 pnpm monorepo 结构,默认集成 Pinia。
css 体验AI代码助手 代码解读复制代码my-vue-app/
├── src/
│ ├── main.ts
│ ├── App.vue
│ ├── pages/
│ ├── components/
│ ├── router/
│ ├── api/
│ └── store/ # Pinia 状态管理
├── packages/
│ ├── shared/
│ └── ui/
└── ...配置文件scss 体验AI代码助手 代码解读复制代码插件系统
├── 代码规范
│ ├── ESLint 9 (Flat Config) ⭐ 最新格式
│ ├── Prettier
│ └── Stylelint (支持 CSS/Less/SCSS)
│
├── 构建工具
│ ├── Vite 5 ⭐ 默认推荐
│ ├── Webpack 5
│ └── Rollup
│
├── 测试工具
│ ├── Vitest ⭐ Vite 原生
│ └── Jest
│
└── Git 工具
├── Husky (Git Hooks)
└── Commitlint (提交规范)每个插件都是独立、可插拔的。你可以选择需要的,跳过不需要的。
这是我最想重点介绍的功能。
CSS 前缀和 JS Polyfill 分开配置,经常对不上:
javascript 体验AI代码助手 代码解读复制代码// postcss.config.js
module.exports = {
plugins: {
autoprefixer: {
overrideBrowserslist: ['last 2 versions'] // 这里
}
}
}
// babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
targets: { browsers: ['> 1%'] } // 和这里不一致!
}]
]
}结果:CSS 兼容 Chrome 70,JS 兼容 Chrome 60,乱套了。
统一使用 .browserslistrc:
ini 体验AI代码助手 代码解读复制代码# .browserslistrc
[production]
> 0.5%
last 2 versions
not dead
not IE 11
Chrome >= 86 # 明确指定 Chrome 86+
[development]
last 1 chrome version
last 1 firefox version
last 1 safari version然后所有工具自动读取:
工具 | 作用 | 配置方式 |
|---|---|---|
Autoprefixer | 添加 CSS 前缀 | 自动读取 .browserslistrc |
Babel preset-env | JS Polyfill | 自动读取 .browserslistrc |
Vite Legacy | 旧浏览器兼容 | 自动读取 .browserslistrc |
一处配置,处处生效。再也不用操心兼容性问题。
很多脚手架还在用 ESLint 8 的 .eslintrc.json 格式,xcli 直接上了 ESLint 9+ Flat Config。
json 体验AI代码助手 代码解读复制代码// .eslintrc.json
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"env": {
"node": true
}
}问题:
.eslintrc + .eslintignore)javascript 体验AI代码助手 代码解读复制代码// eslint.config.js
import js from '@eslint/js';
import globals from 'globals';
import tseslint from 'typescript-eslint';
import prettierConfig from 'eslint-config-prettier';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
},
},
prettierConfig,
);优势:
bash 体验AI代码助手 代码解读复制代码# 交互式创建
npx @jserxiao/xcli init my-react-app
# 然后根据提示选择:
# ? 项目类型: React
# ? 样式预处理器: Less
# ? 状态管理: Redux Toolkit
# ? HTTP 请求库: Axios
# ? 打包工具: Vite
# ? 创建 VSCode 配置: Yes或者直接命令行一把梭:
bash 体验AI代码助手 代码解读复制代码npx @jserxiao/xcli init my-react-app \
-t react \
-s less \
-m redux \
-h axios \
-b vite \
-d生成的项目结构:
csharp 体验AI代码助手 代码解读复制代码my-react-app/
├── src/
│ ├── main.tsx # React 18 入口
│ ├── App.tsx # 根组件
│ ├── pages/
│ │ ├── Home.tsx # 首页(带 Redux 示例)
│ │ └── About.tsx # 关于页
│ ├── components/
│ │ └── Layout.tsx # 布局组件
│ ├── router/
│ │ └── index.tsx # React Router 6
│ ├── api/
│ │ └── request.ts # Axios 封装(含拦截器)
│ ├── store/
│ │ ├── index.ts # Store 配置
│ │ ├── counterSlice.ts # Counter 示例
│ │ ├── apiSlice.ts # RTK Query
│ │ └── middleware/
│ │ └── logger.ts # 日志中间件
│ └── assets/
├── packages/
│ ├── shared/ # 共享工具函数
│ │ └── src/
│ │ └── index.ts
│ └── ui/ # UI 组件库
│ └── src/
│ └── index.ts
├── public/
├── vite.config.ts # Vite 5 配置
├── eslint.config.js # ESLint 9 Flat Config
├── tsconfig.json # TypeScript 5
├── postcss.config.js # PostCSS + Autoprefixer
├── .browserslistrc # 浏览器兼容
├── .prettierrc
├── pnpm-workspace.yaml
└── package.json直接运行:
bash 体验AI代码助手 代码解读复制代码cd my-react-app
pnpm install
pnpm dev打开浏览器,一个完整的 React 项目已经跑起来了:
总耗时:3 分钟
bash 体验AI代码助手 代码解读复制代码npx @jserxiao/xcli init my-vue-app \
-t vue \
-s scss \
-b webpack \
-d注意这里用了 Webpack 而不是 Vite。
为什么?因为有些企业项目需要:
xcli 的 Webpack 配置包含:
javascript 体验AI代码助手 代码解读复制代码// webpack.config.cjs 节选
module.exports = (env, argv) => {
return {
// ...
module: {
rules: [
// Babel:自动读取 .browserslistrc
{
test: /\.[jt]sx?$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage', // 按需 Polyfill
corejs: 3,
}],
'@babel/preset-typescript',
],
},
},
},
// CSS + PostCSS
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader', // Autoprefixer
],
},
],
},
// 代码分割
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
},
},
},
},
};
};bash 体验AI代码助手 代码解读复制代码npx @jserxiao/xcli init my-utils -t library -d生成的 Library 项目:
perl 体验AI代码助手 代码解读复制代码my-utils/
├── src/
│ └── index.ts # 入口文件
├── dist/ # ESM + CJS 输出
├── package.json
├── tsconfig.json
├── rollup.config.ts # Rollup 配置
└── README.mdpackage.json 自动配置:
json 体验AI代码助手 代码解读复制代码{
"name": "my-utils",
"version": "1.0.0",
"type": "module",
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
}
},
"files": ["dist"],
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w"
}
}直接发布到 npm:
bash 体验AI代码助手 代码解读复制代码pnpm build
npm publish每个插件都是一个独立的对象:
typescript 体验AI代码助手 代码解读复制代码export const vitePlugin: Plugin = {
name: 'vite',
displayName: 'Vite',
description: '下一代前端构建工具',
category: 'bundler',
defaultEnabled: true,
devDependencies: {
vite: '^5.0.0',
'@vitejs/plugin-react': '^4.0.0',
'@vitejs/plugin-legacy': '^5.0.0',
},
scripts: {
dev: 'vite',
build: 'vite build',
preview: 'vite preview',
},
files: [
{
path: 'vite.config.ts',
content: (context) => getViteConfig(context),
},
],
};好处:
模板负责生成项目结构:
typescript 体验AI代码助手 代码解读复制代码export const reactTemplate = {
type: 'react',
displayName: 'React',
description: 'React 前端项目 (pnpm monorepo)',
createStructure: async (projectPath, context) => {
// 1. 创建目录结构
// 2. 生成配置文件
// 3. 生成源代码
// 4. 根据选项调整(Redux/MobX、Axios/Fetch、Vite/Webpack)
},
getDependencies: (styleType, stateManager, httpClient, bundler) => {
// 根据选择返回对应的依赖
return {
dependencies: { ... },
devDependencies: { ... },
};
},
};所有依赖版本统一在 versions.ts 中管理:
typescript 体验AI代码助手 代码解读复制代码export const BUNDLER_VERSIONS = {
vite: '^5.0.12',
webpack: '^5.98.0',
// ...
};
export const FRAMEWORK_VERSIONS = {
react: '^18.2.0',
vue: '^3.4.15',
// ...
};好处:
特性 | xcli | create-react-app | Vite 官方模板 |
|---|---|---|---|
TypeScript | ✅ 原生支持 | ⚠️ 需要 eject | ✅ 支持 |
Monorepo | ✅ pnpm workspace | ❌ 不支持 | ❌ 不支持 |
状态管理 | ✅ 可选 Redux/MobX/Pinia | ❌ 无 | ❌ 无 |
HTTP 封装 | ✅ 可选 Axios/Fetch | ❌ 无 | ❌ 无 |
ESLint 9 | ✅ Flat Config | ❌ 旧格式 | ⚠️ 需手动配 |
浏览器兼容 | ✅ 统一配置 | ⚠️ 需手动配 | ⚠️ 需手动配 |
构建工具 | ✅ Vite/Webpack | ❌ 仅 Webpack | ✅ Vite |
插件系统 | ✅ 可插拔 | ❌ 无 | ❌ 无 |
bash 体验AI代码助手 代码解读复制代码# 快速启动,默认配置够用
xcli init my-app -t react -dbash 体验AI代码助手 代码解读复制代码# 明确指定每个选项,确保一致性
xcli init team-project \
-t react \
-s scss \
-m redux \
-h axios \
-b vite \
-d建议团队制定一份 xcli 使用规范,确保所有项目配置统一。
bash 体验AI代码助手 代码解读复制代码xcli init my-lib -t library -dxcli 解决的是一个"小"问题——省去配置的时间。
但它带来的价值是"大"的:
如果你也受够了重复配置,不妨试试:
bash 体验AI代码助手 代码解读复制代码npx @jserxiao/xcli init my-projectbash 体验AI代码助手 代码解读复制代码# 创建项目
xcli init my-project
xcli init my-project -t react -d
xcli init my-project -t vue -d
xcli init my-lib -t library -d
# 插件管理
xcli plugin list
xcli plugin add vitest
xcli plugin remove jest
# 升级 CLI
xcli upgrade --check
xcli upgrade
# 查看版本
xcli version原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。