--- title: "20-前端万用模板开发教程" created: 2025-12-02 tags: - 项目 aliases: - 前端万用模板开发教程 --- # 前端万用模板开发教程 ## 初始化 本前端初始模板使用 Ant Design Pro。 官方地址:[开箱即用的中台前端/设计解决方案 - Ant Design Pro](https://pro.ant.design/zh-CN/) Vue 版本官方地址:[Ant Design Pro of Vue (antdv.com)](https://pro.antdv.com/) 初始化命令: ```bash npm i @ant-design/pro-cli -g pro create yuzi-generator-web-frontend ``` 注意:一定要选择 umi@4! ![[1b6e4d40-8522-4398-bbbe-52ef31accf97-0af051d2.png]] 项目版本最好一致:6.0.0 ![[c0ed5594-30e0-434f-a7be-ac92c32ac845-9225bff5.png]] 可以使用 npm、yarn、pnpm、cnpm 下载依赖,建议版本不要过低,也就是 node 版本最好在 16 及以上。 ![[0e03c580-5975-44bc-b677-e92af268e9de-eb2374c5.png]] 运行 npm dev 测试执行,运行 npm start 可以开启 Mock 数据。 ![[3e1546f4-2d61-4f3a-8d24-504ac873aff1-f32bb788.png]] ### 初始化可能遇到的问题 1)可能会因为缺少 .git 文件导致 husky 执行报错,忽略即可。 ## 开发规范 Prettier 格式化工具,用来统一代码格式 格式化快捷键建议勾选,Vue 技术栈同学建议手动加 .Vue 后缀 ![[bf1c5725-9aa8-4d91-acb8-55cb5c7f8247-fc480fd9.png]] Eslint 保持代码风格,减少代码出错。 同样的,Vue 技术栈手动加上即可 ![[4c285a96-08a1-4d14-be54-72f3de418d95-866bebd4.png]] ## 模板瘦身 ### 移除模块 #### 注意事项(重点) 一次移除后,去重启一下项目,看看能否正常运行,控制变量法,如果不行,直接回滚一下就可以了,一次性删除太多,容易找不到源头。 #### 移除 husky 一个用来提交前检查代码的规范,保证代码的一致性,一般用于团体协作,个人没有必要。 ![[1ae1ce1d-a2eb-475c-a0ee-5e4da4e628c0-ff1011fc.png]] 移除相关的命令 ![[4d12aea8-bf81-4b7f-9e3f-af19d1cb2ba6-589ae3c3.png]] #### 移除 mock mock 是官方提供的模拟数据,而我们自己是有真实的后端接口要对接的,因此移除。 ![[8f9e6fdb-efa6-4aac-a4a1-c2b6a3a7ed85-788be663.png]] ![[98b6cd14-843b-4bc7-9076-cb02e735d344-fa3f3339.png]] #### 移除 icons 和 manifest.json 图标和适配移动端所需要的 Json,直接删除即可。 ![[ca377473-1934-47f3-bdca-afc27d0e32b4-4013adff.png]] #### 移除 cname 域名映射,官方提供的,和我们自己的域名无关。 ![[9ba03ad3-ccfc-44c5-8347-6602cb7ac226-c836aa7e.png]] #### 移除国际化 一般我们自己的上线的项目只对本国用户去开放,而且访问人数也较少,没有必要去用国际化,会增加打包体积,而且页面加载速度也会变慢。 步骤: 1)前端本地执行: yarn add eslint-config-prettier --dev yarn add eslint-plugin-unicorn --dev 2)注释 es2022 找到 node\_modules / @umijs/lint/dist/config/eslint/index.js, 注释掉 es2022 那行 ![[dc73c1ee-8586-46b6-ad4a-66e0514a746c-27e4b31e.png]] 3)执行 i18n-remove 命令 ![[f98ad86b-bfc5-4d7b-99ab-76482ecd4b0c-687c12b8.png]] 4)删除对应的文件夹 locales ![[a8197352-c690-469f-99ba-9fb4b6392bcd-e3ae3fed.png]] #### 移除单元测试( Jest 相关的全部移除 ) ![[ae75649d-21a1-4436-8bb4-3f029b542144-5c6e2b43.png]] ![[a8353a59-e81d-4e07-b169-00532e9a7671-d94b92b7.png]] #### 移除 types 我们自己会用 OpenAPI 规划去生成接口和类型。 ![[ab74fee4-acd4-43ff-be0a-88909eb51f93-91651bf3.png]] #### 移除 swagger ![[715cdea0-15c7-4f51-a130-4a8e029f9b0c-9588aec9.png]] #### 移除 openapi.json 我们有自己的后端接口地址,不需要官方提供。 ![[bb9d8854-2123-46a9-8d47-81bc5240adfc-8b610647.png]] ## 基本类型 修改 typings.d.ts ![[d52d628c-a9f3-430f-b625-f7e8ab1255d2-cec9e033.png]]```tsx declare module 'slash2'; declare module '\*.css'; declare module ```ts '\*.less'; declare module '\*.scss'; declare module '\*.sass'; declare module '\*.svg'; declare module '\*.png'; declare module '\*.jpg'; declare module '\*.jpeg'; declare module '\*.gif'; declare module '\*.bmp'; declare module '\*.tiff'; declare module 'omit.js'; declare module 'numeral'; declare module '@antv/data-set'; declare module 'mockjs'; declare module 'react-fittext'; declare module 'bizcharts-plugin-slider'; declare const REACT\_APP\_ENV: 'test' | 'dev' | 'pre' | false;1806613115223461889\_0.291683599058729 /** - 分页信息 \*/ interface PageInfo { current: number; size: number; total: number; records: T[]; } /**1806613115223461889\_0.4592083904443922 - 分页请求 \*/ interface PageRequest { current?: number; pageSize?: number; sortField?: string; sortOrder?: 'ascend' | 'descend'; } /** - 删除请求 \*/ interface DeleteRequest { id: number; } 1806613115223461889\_0.4279687789570217 /** - 返回封装 \*/ interface BaseResponse { code: number; data: T; message?: string; } /**1806613115223461889\_0.7157203774996626 - 全局初始化状态 \*/ interface InitialState { currentUser?: API.LoginUserVO; } ``` ## 请求 ### 请求代码生成 注意项:由于 Swagger V3 版本文件上传请求有 BUG,还是推荐用 Swagger 2 版本。 接口文档地址:[http://localhost:8101/api/v2/api-docs](http://localhost:8101/api/v3/api-docs) 修改配置: ```tsx openAPI: [ { requestLibPath: "import { request } from '@umijs/max'", schemaPath: "http://localhost:8101/api/v2/api-docs", projectName: 'yuzi-generator-web-backend', }, ], ``` ![[7da1271c-ccf5-4bed-b8ec-5351324b7262-e1a260ce.png]] 生成结果: ![[53428241-f23a-4383-8691-12b89e806ccb-da999cc7.png]] ### 全局请求处理 1)修改 requestErrorConfig.ts 的名称为 requestConfig.ts 2)修改昵称至 requestConfig ![[65b7e2a0-193b-45b7-9b93-92287568770f-f582b21a.png]] 3)app.tsx 中引入 ![[c0386102-4fbb-4007-9a8f-dca67f4b3418-addb25b8.png]] 4)创建 index.ts 常量区别开发环境和部署环境1806613115223461889\_0.5625128030034061 ![[fe7534bb-b976-477b-8960-50048720b379-66297b48.png]] 5)引入环境变量,根据环境变量区分不同环境请求地址 ![[5e9142d0-04b8-49f9-aa4a-19f880c528dc-fdf60968.png]] 6)删除错误处理,官方给的过于复杂,这边直接删除。 ![[2275b342-5f35-49a2-b22f-a2221ed3a4ed-3516e0a3.png]] 7)删除官方的拼接 Token,一般你要使用 Token,可以直接在Authorization 请求头中携带 Token。 ```java // 请求拦截器 requestInterceptors: [ (config: RequestOptions) => { // 拦截请求配置,进行个性化处理。 return config; }, ], ``` ![[3d13eae2-79ac-4de2-9bfe-c65e1e9e1bcb-0edd55ca.png]] 8)修改封装好的响应拦截器 ![[1f63262d-66bd-4aa1-8edd-24a8c60de8f2-20b7a4c1.png]] ```tsx // 响应拦截器 responseInterceptors: [ (response) => { // 请求地址 const requestPath: string = response.config.url ?? ''; ``` // 响应 const { data } = response as unknown as ResponseStructure; if (!data) { throw new Error('服务异常'); } // 错误码处理 const code: number = data.code; // 未登录,且不为获取用户登录信息接口 if ( code === 40100 && !requestPath.includes('user/get/login') && !location.pathname.includes('/user/login') ) { // 跳转至登录页 window.location.href = `/user/login?redirect=${window.location.href}`; throw new Error('请先登录'); } if (code !== 0) { throw new Error(data.message ?? '服务器错误'); } return response; }, ], ```text ``` ## 临时登录 1)修改 app.tsx 中的 getInitialState,获取用户初始化状态,先利用 Mock 模拟数据,替换后将报错的 username、avatar 等全局替换即可。 ```tsx /** * @see https://umijs.org/zh-CN/plugins/plugin-initial-state * */ export async function getInitialState(): Promise { const initialState: InitialState = { currentUser: undefined, }; // 如果不是登录页面,执行 const { location } = history; if (!location.pathname.startsWith(loginPath)) { // 获取当前登录用户 const res = await getLoginUser(); initialState.currentUser = res.data; const mockUser: API.LoginUserVO = { userAvatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png', userName: 'yupi', userRole: 'admin', }; initialState.currentUser = mockUser; } return initialState; } ``` ![[341b49db-30c7-4382-9d6d-fdb1a7a6f795-c035c2d7.png]] 2)先用 @ ts-ignore 忽略 ts 类型提示错误 ![[09b9464e-003b-4ad7-bfe9-eed347737233-f7ffaa51.png]] 2.1)移除无用配置,比如 setting drawers 可以不要,需要可视化得到配置可以使用在线地址:[分析页 - Ant Design Pro](https://preview.pro.ant.design/dashboard/analysis) ![[45a14d23-ce56-4084-bacf-84c4dadf2e3e-8c2eb237.png]] ![[0cc36369-e122-4c93-956e-c9d0154fce11-539c9b8f.png]] ![[72f298ee-4a3c-480a-8eef-35f5d8602fc9-2eeead37.png]] 3)注释请求后端的代码,访问主页面,不会再重定向到登录页 ![[a5a729db-992c-4548-ab39-597b13dbd4e3-c2643c83.png]] 4)如果侧边栏没有展示,给路由加上 name 属性即可 ![[7b811311-16bb-4ede-9401-ff554e101a31-ffe56bc2.png]] 5)查看登录效果 ![[3ebd866f-d771-4af3-bb12-20fc4006b217-52997d03.png]] 6)优化 layout 的配置 ```javascript // ProLayout 支持的api https://procomponents.ant.design/components/layout // @ts-ignore export const layout: RunTimeLayoutConfig = ({ initialState }) => { return { actionsRender: () => [], avatarProps: { src: initialState?.currentUser?.userAvatar, title: , render: (_, avatarChildren) => { return {avatarChildren}; }, }, waterMarkProps: { content: initialState?.currentUser?.userName, }, footerRender: () =>