找回密码
 会员注册
查看: 25|回复: 0

如何华丽的实现一套脚手架-以umicli和转转zzcli为例

[复制链接]

5

主题

0

回帖

16

积分

新手上路

积分
16
发表于 2024-9-19 23:02:42 | 显示全部楼层 |阅读模式
文章背景  对前端开发者而言,脚手架是快速开发不可或缺的一环。脚手架方便开发者从基于已有的代码库,去下载符合项目所使用的模板,并根据需求修改配置并生成项目文件。从而减少新建项目时重复的配置工作,统一团队开发中各项目的配置和规范。  本文作为本次umi系列的最后一篇,既然umi的源码在前面的文章已经分析完了,那么探索下umi3的脚手架的运行内容也是不错的~在此基础上,也分享一下现阶段转转内部的脚手架zz-cli的一些实现与构建内容。umi脚手架如何运作  从官方文档可以看到,执行以下命令就可以让脚手架运行起来$ yarn create @umijs/umi-app# 或 npx @umijs/create-umi-appcreate-umi-app.js中包含require('../lib/cli')cli.ts  cli文件内默认引入执行index.tsrequire('./')  .default({    cwd: process.cwd(),    args,  })  代码中,先实例化AppGenerator类,然后执行run方法;import AppGenerator from './AppGenerator/AppGenerator';const generator = new AppGenerator({  cwd,  args,});generator.run();  紧接着我们来看看AppGenerator类做了什么事情。AppGenerator.ts  AppGenerator类继承Generator类,并定义了writing方法,该方法执行copyDirectory复制目录,方法参数包含版本号、路由模式、模板文件地址、目标产生文件的地址等参数。import { Generator } from '@umijs/utils';export default class AppGenerator extends Generator {  async writing() {    this.copyDirectory({      context: {        version, //根据配置文件获取版本号       conventionRoutes,// 常规路由?约定路由      },      path, // 找到对应templates文件      target: this.cwd,     });  }}Generator.ts  介绍Generator类之前,还是要简单提一下umi2的基础上umi3的脚手架做了哪些更改。  umi2的脚手架项目独立于umi项目,在生成模板文件前,会在模板询问处提供3套项目模板供用户选择,选择完成后,直接去远程拉取内容下载;Generator类的构造则是通过yeoman这个脚手架工具去完成。(yeoman是一个通用型脚手架工具,容易拓展。我们在搭建脚手架时也可以把它作为一个方案备选,毕竟构建Generator类的方式多样,使用方式参考这里)  umi3则将脚手架的创建功能收拢到umi项目的/packages/create-umi-app文件夹下,项目只有一套默认模板供使用,并且极大程度上的去除了脚手架创建时用户配置能力。  言归正传,我们先来看看umi3的Generator类包含了哪些内容。  最主要的是引用nodejsfs模块的copyFileSync、readFileSync、statSync、writeFileSync等方法,去获取文件的读写能力;引入nodejspath模块获取处理文件路径的能力。  其次引用了chalk(优化命令行显示),glob(文件名称匹配),mkdirp(创建文件夹),Mustache(模板引擎),prompts(询问交互),yargs(获取命令行参数)等工具插件去获取各种能力。  Generator类主要定义了run,prompting,writing,copyTpl,copyDirectory等方法。run是外部调用时执行的入口,如果有其他配置问题需要额外写入的话,也可以在外面手动传入prompting的内容,执行完prompting的内容后才会开始执行writingwriting主要是在执行文件模板拷贝的一个入口方法(在外部的AppGenerator中,writing执行了copyDirectory复制目录)copyTpl解析.tpl格式的模板文件并写入copyDirectory遍历模板文件,根据文件名称进行区分,对.tpl执行copyTpl写入,对普通文件直接进行复制  定义完Generator类、在项目中进行引用之后,我们就可以对模板文件进行解析和操作。class Generator {  ...  constructor({ cwd, args }: IOpts) {    this.cwd = cwd;    this.args = args;    this.prompts = {};  }    /**   * run函数执行,当前没有写入prompting内容,需要可以根据需求自行定义   */  run() {    this.writing();  }  prompting() {    return [] as any;  }    // 写入动作  async writing() {}  // 复制模板  copyTpl(opts: { templatePath: string; target: string; context: object }) {    const tpl = readFileSync(opts.templatePath, 'utf-8');    // 解析模板替换变量,得到新的模板内容    const content = Mustache.render(tpl, opts.context);    mkdirp.sync(dirname(opts.target));    writeFileSync(opts.target, content, 'utf-8');  }  // 复制文件目录 这个是脚手架执行的主要内容  copyDirectory(opts: { path: string; context: object; target: string }) {    const files = glob.sync('**/*', {      cwd: opts.path,      dot: true,      ignore: ['**/node_modules/**'],    });        files.forEach((file: any) => {      const absFile = join(opts.path, file);      // 判断文件是否是相关的模板引擎文件,如果是的话需要解析模板再输出文件      if (file.endsWith('.tpl')) {        this.copyTpl();      } else {        // 直接复制文件        const absTarget = join(opts.target, file);        mkdirp.sync(dirname(absTarget));        copyFileSync(absFile, absTarget);      }    });      }}总结  umi3脚手架总体上满足了脚手架的完整功能,既能够创建初始模板项目,也能够预置配置。当前需要用户直接参与进行配置的内容很少,因此手写定义Generator类的方法也是合适的。  讲完了umi3脚手架,再来看看咱们转转的zz-cli:一样是脚手架,却有点不一样。zz-cli  zz-cli是转转前端脚手架工具,内置了转转fe各团队在日常开发中的各项代码模板,除了创建项目代码,同时还提供了与公司内部其他项目交互的能力,如统跳平台、zz-ui区块组件文件、上传基建项目文档等等,通过一个脚手架将一份项目代码与fe业务的各个节点衔接了起来。zz-cli的内容揭秘  zz-cli引用了commander做命令管理工具,安装完脚手架后,在命令行输入zz,就会展示下面的内容  可以看到,zz定义了5个Commands,就是脚手架可执行的命令。我们主要要看的是create,这个命令主要执行的是脚手架最基本也是最重要的功能:创建标准模板项目。完成只需要四步,咱们往下看吧第一步:模板选择询问  我们先输入命令行让脚手架的create命令执行起来:zz create my-appnode bin/zz create my-app  // 源码调试可以执行这个~原理一样的  执行完之后,找到program.command('create
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 13:06 , Processed in 2.330432 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表