当前位置: 首页 > news >正文

使用 Umi 的微生成器快速助力业务交付

在项目中的最好的提效方案就是复用,比如将常用模块封装,给到其他页面复用,就是我们经常提到的组件(复制使用的情况)。将项目中的方案进行封装,给到不同的项目中使用,就是我们说到的脚手架。而这些好的组件或者脚手架,要快速的被其他人员使用,就要用到生成器。简单的理解就是使用脚本帮你复制了一份,像很多项目中经常会执行的新建项目就是生成器的一种能力体现。

npx create-xxx appName 

Umi 中将生成器的目标定的更加细化,不是提供一整个脚手架,而是提供脚手架中的某一个方案,所以取名微生成器,其实灵感来源是 modern.js 的微生成器。

Umi 的微生成器有统一的命令入口调用:

umi generate (alias: umi g) [type] 

内置微生成器列表

页面生成器

比如快速生成一个初始的简单页面,可以使用一下方法方式。

交互式输入页面名称和文件生成方式:

$ umi g page
? What is the name of page? › mypage
? How dou you want page files to be created? › - Use arrow-keys. Return to submit.
❯ mypage/index.{tsx,less}mypage.{tsx,less} 

或者直接指明页面名称直接生成:

$ umi g page foo
Write: src/pages/foo.tsx
Write: src/pages/foo.less 

如果你的项目风格是使用目录方式,比如基于 Umi 构建的前端框架 alita 中,就只有目录下的 index 文件才会被识别成路由,所以就可以采用以目录方式生成页面,目录下为页面的组件和样式文件:

$ umi g page bar --dir
Write: src/pages/bar/index.less
Write: src/pages/bar/index.tsx 

批量生成多个页面:

$ umi g pagepage1page2 a/nested/page3
info- @local
Write: src/pages/page1.tsx
Write: src/pages/page1.less
Write: src/pages/page2.tsx
Write: src/pages/page2.less
Write: src/pages/a/nested/page3.tsx
Write: src/pages/a/nested/page3.less 

剩余内置微生成器清单

后续我们会在介绍每一个能力的时候,使用到对应的微生成器。

组件生成器

src/components/ 目录下生成项目需要的组件。和页面生成器一样,组件生成器也有多种生成方式。

交互式生成:

$ umi g component
info- @local
✔ Please input you component Name … foo
Write: src/components/Foo/index.ts
Write: src/components/Foo/Foo.tsx 

直接生成:

$ umi g component bar
info- @local
Write: src/components/Bar/index.ts
Write: src/components/Bar/Bar.tsx 

嵌套生成:

$ umi g component group/subgroup/baz
info- @local
Write: src/components/group/subgroup/Baz/index.ts
Write: src/components/group/subgroup/Baz/Baz.tsx 

批量生成:

$ umi g component apple banana orange
info- @local
Write: src/components/Apple/index.ts
Write: src/components/Apple/Apple.tsx
Write: src/components/Banana/index.ts
Write: src/components/Banana/Banana.tsx
Write: src/components/Orange/index.ts
Write: src/components/Orange/Orange.tsx 

RouteAPI 生成器

生成 routeAPI 功能的模板文件。

交互式生成:

$umi g api
info- @local
✔ please input your api name: … starwar/people
Write: api/starwar/people.ts 

直接生成:

$ umi g api films
info- @local
Write: api/films.ts 

嵌套生成器:

$ umi g api planets/[id]
info- @local
Write: api/planets/[id].ts 

批量生成:

$ umi g api spaceships vehicles species
info- @local
Write: api/spaceships.ts
Write: api/vehicles.ts
Write: api/species.ts 

Mock 生成器

生成 Mock 功能的模板文件,mock 的具体实现参考文档。

交互式生成:

$ umi g mock
info- @local
✔ please input your mock file name … auth
Write: mock/auth.ts 

直接生成:

$ umi g mock acl
info- @local
Write: mock/acl.ts 

嵌套生成:

$ umi g mock users/profile
info- @local
Write: mock/users/profile.ts 

Prettier 配置生成器

为项目生成 prettier 配置,命令执行后,umi 会生成推荐的 prettier 配置和安装相应的依赖。

$ umi g prettier
info- @local
info- Write package.json
info- Write .prettierrc
info- Write .prettierignore 

Jest 配置生成器

为项目生成 jest 配置,命令执行后,umi 会生成 Jest 配置和安装相应的依赖。根据需要选择是否要使用 @testing-library/react 做 UI 测试。

$ umi g jest
info- @local
✔ Will you use @testing-library/react for UI testing?! … yes
info- Write package.json
info- Write jest.config.ts 

Tailwind CSS 配置生成器

为项目开启 Tailwind CSS 配置,命令执行后,umi 会生成 Tailwind CSS 和安装相应的的依赖。

$ umi g tailwindcss
info- @local
info- Write package.json
set config:tailwindcss on /Users/umi/playground/.umirc.ts
set config:plugins on /Users/umi/playground/.umirc.ts
info- Update .umirc.ts
info- Write tailwind.config.js
info- Write tailwind.css 

DvaJS 配置生成器

为项目开启 Dva 配置,命令执行后,umi 会生成 Dva

$ umi g dva
info- @local
set config:dva on /Users/umi/umi-playground/.umirc.ts
set config:plugins on /Users/umi/umi-playground/.umirc.ts
info- Update config file
info- Write example model 

自定义微生成器

当然官方提供的基本的微生成器,肯定无法满足我们特定的项目需求,我们可以通过简单的调用和约定来自定义微生成器。 比如官方提供的 g page 只生成了简单的页面。

import React from 'react';
import styles from './abc.less';

export default function Page() {return (<div><h1 className={styles.title}>Page abc</h1></div>);
} 

而我们的项目中需要的初始化页面内容可能会更加复杂,要带有请求等页面模版:

import React from 'react';
import type { FC } from 'react';
import { useRequest } from 'umi';
import { query } from './service';
import styles from './index.less';

interface HomePageProps {}

const HomePage: FC<HomePageProps> = () => {const { data } = useRequest(query);return <div className={styles.center}>Hello {data?.text}</div>;
};

export default HomePage; 

以上模版中提到的能力和内容会在后续的文章中体现,这里仅仅作为一个展示

要自定义微生成器,只需要调用 generateFile 指定模版存放的路径,指定需要替换的模版中的变量,既可。

generateFile({path: join(__dirname, '../../../templates/generate/page'),target: join(api.paths.absPagesPath, name),data: {color: randomColor(),name: lodash.upperFirst(name),},
}); 

generateFile 的目的是让开发人员在编写微生成器的时候,将精力更加聚焦于目标文件生成时的模版维护工作中。 不许花费而外的心力,去学习微生成器的功能开发。

比如我们生成上面的页面,用到的模版如下:

import React from 'react';
import type { FC } from 'react';
import { useRequest } from 'alita';
import { query } from './service';
import styles from './index.less';

interface {{{ name }}}PageProps {}

const {{{ name }}}Page: FC<{{{ name }}}PageProps> = () => {const { data } = useRequest(query);return <div className={styles.center}>Hello {data?.text}</div>;
};

export default {{{ name }}}Page; 

在为用户提供微生成器时,有一些数据需要用户提供给我们,会有一些交互式的问答功能需要实现,在微生成器中,我们只需要关注问题本身。

Umi 中提供了两种问答的手段,(底层是同一套方案)第一种就是在插件中使用的,配合上面提到的 generateFile 使用

import { prompts } from '@umijs/utils'; 

if (!name) {const response = await prompts({type: 'text',name: 'name',message: 'What is the name of page?',});name = response.name;
} 

使用 Umi 的基础微生成器工具

第二种方式就是可以脱离 Umi 的声明周期使用的,是一个基础的生成模块,你可以将它用在任意的项目中,比如我们实现一个脚手架的生成器。

const appPrompts = [{name: 'name',type: 'text',message: `What's the app name?`,default: name,},{name: 'author',type: 'text',message: `What's your name?`,},
];

const generator = new BaseGenerator({path: join(__dirname, '..', 'templates', args.plugin ? 'plugin' : 'app'),target: name ? join(cwd, name) : cwd,data:{version: require('../package').version,npmClient,registry,},questions: appPrompts,
});
await generator.run(); 

我们的关注点就只在模版文件(templates)和问题(questions)这两点上,如果模版有修改或者问题有变更,我们也只需修改这两个地方,不用耗费大量的心力去处理当前复制和写入的是文件还是文件夹,目标文件夹是否为空等文件写入边界问题。

以上提供的只是基本的模块使用方式,后续的课程中我们会展示以上代码的完整场景和实现。

(cwd, name) : cwd,data:{version: require('../package').version,npmClient,registry,},questions: appPrompts,
});
await generator.run(); 

我们的关注点就只在模版文件(templates)和问题(questions)这两点上,如果模版有修改或者问题有变更,我们也只需修改这两个地方,不用耗费大量的心力去处理当前复制和写入的是文件还是文件夹,目标文件夹是否为空等文件写入边界问题。

以上提供的只是基本的模块使用方式,后续的课程中我们会展示以上代码的完整场景和实现。

感谢阅读,今天教程仓库中没写一行代码,就不放源码归档链接了。今天更多的是微生成器的介绍,实际应用场景涉及整个最佳实践方案,我们会在后续的文章中一一体现。

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

相关文章:

  • flink窗口聚合函数之aggregateFuction学习
  • DNS域名解析系统-BIND服务
  • 【rainbowzhou 面试21/101】综合提问--为什么选择做测试/大数据测试?
  • 【日拱一卒行而不辍20220923】自制操作系统
  • 【高质量C/C++】3.命名规则
  • 湖仓一体电商项目(二十):业务实现之编写写入DM层业务代码
  • Msquic客户端详解
  • Eclipse Theia技术揭秘——构建桌面IDE
  • 交换机的构成以及其工作原理
  • 想换壁纸找不到高质量的?来这里用python采集上万张壁纸
  • Mybatis-Plus(核心功能篇 ==> 条件构造器
  • vue2.X+Cesium1.93Demo
  • 适配器模式【Java设计模式】
  • 聊一下接口幂等性
  • springboot源码理解十二、springMVC功能
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • 77. Combinations
  • Apache Pulsar 2.1 重磅发布
  • CSS实用技巧
  • Date型的使用
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • Linux CTF 逆向入门
  • vagrant 添加本地 box 安装 laravel homestead
  • 彻底搞懂浏览器Event-loop
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 容器镜像
  • 通过调用文摘列表API获取文摘
  • ​queue --- 一个同步的队列类​
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #162 (Div. 2)
  • #Ubuntu(修改root信息)
  • (007)XHTML文档之标题——h1~h6
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (一)为什么要选择C++
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .NET delegate 委托 、 Event 事件
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • @ConditionalOnProperty注解使用说明
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [2]十道算法题【Java实现】
  • [Android 13]Input系列--获取触摸窗口
  • [Angular] 笔记 20:NgContent
  • [BetterExplained]书写是为了更好的思考(转载)
  • [boost]使用boost::function和boost::bind产生的down机一例
  • [CF494C]Helping People
  • [git] windows系统安装git教程和配置
  • [GN] 后端接口已经写好 初次布局前端需要的操作(例)
  • [HAOI2016]食物链
  • [iOS]-UIKit