资讯专栏INFORMATION COLUMN

从零开始搭建自己的前端脚手架(一)

gxyz / 1819人阅读

摘要:以下阅读将花费分钟前言日常开发中,我们都只专注在业务上的开发,拿起一套开箱即用的模板项目就直接开搞了,不知道大家有没有思考过,平时我们使用的脚手架里面到底做了什么,并且如果是自己来搭一套脚手架,应该怎么去搭呢在本博客中,将记录作者搭建脚手架

(以下阅读将花费10分钟)

前言

日常开发中,我们都只专注在业务上的开发,拿起一套开箱即用的模板项目就直接开搞了,不知道大家有没有思考过,平时我们使用的脚手架里面到底做了什么,并且如果是自己来搭一套脚手架,应该怎么去搭呢?

在本博客中,将记录作者搭建脚手架的过程,整体将分为两个部分,第一部分是cli的搭建,第二部分是模板项目的搭建;

cli的搭建

在搭建脚手架cli之前,我们首先思考一下,一个cli,需要什么能力呢?答案是初始化能力,那么初始化的功能需要怎样去实现呢,这里,我们先梳理一下思路。

思路

我们在使用其他cli时,会发现,它们有问询的功能,比如询问项目名称,项目描述等;然后还可以选择模板项目将要使用什么css预处理器等的问题;所以,cli首先就要具备问询功能,用以获取定制化信息;
问询结束后,我们的cli会获得即将创建的项目的基本信息,接下来我们就需要以一个模板项目作为模板去创建,模板项目将会在第二部分讲解,这里一笔带过~;OK,既然有了模板项目,cli就需要下载这个项目,然后复制这个项目,同时将前面问询所得的定制化信息写入项目配置中,所以cli还需要有下载复制,写入模板功能;
到此,一个模板项目基本已经创建成功了,那后面我们还希望脚手架可以帮忙进行git初始化以及安装依赖的功能,所以最终,还需要添加git初始化安装依赖的功能;
总结一下,实现一个cli的初始化功能我们需要有如下能力:
问询 ==> 下载模板 ==> 复制,写入模板 ==> git初始化 ==> 安装依赖

准备

好了,为了实现上述思路,cli将会引入如下依赖去实现对应的功能:

</>复制代码

  1. const program = require("commander"); // commander负责读取命令
  2. const inquirer = require("inquirer"); // inquirer负责问询
  3. const download = require("download-git-repo"); // download-git-repo负责下载对应模板项目的git仓库
  4. const fse = require("fs-extra"); // fs-extra负责文件的复制
  5. const memFs = require("mem-fs");
  6. const editor = require("mem-fs-editor"); // mem-fs-editor负责模板的复制以及嵌入模板字符串,它需要依赖mem-fs
  7. const { exec } = require("child_process"); // child_process负责执行命令行

当然除了上述必须的依赖外,为了更好的交互体验,还引入了如下依赖:

</>复制代码

  1. const chalk = require("chalk"); // 改变命令行输出样式
  2. const ora = require("ora"); // 一个优雅地命令行交互spinner

至此,准备的工作已经完毕,下面,就开始一步步来编写cli了

cli的编写

万事开头难,有了思路后,实现思路才是真正的开始,下面将介绍如何组织cli项目

项目组织

首先看一下,工程的组织

</>复制代码

  1. ├── bin
  2. | ├── begin
  3. | ├── begin-init
  4. ├── src
  5. | ├── constants.js
  6. | ├── project.js
  7. | └── utils.js
  8. ├── .gitignore
  9. ├── .npmrc
  10. ├── README.md
  11. └── package.json
第一步,解析命令

bin/begin中引入commander,并且声明init命令,commander会在同级目录中寻找begin-init文件

</>复制代码

  1. const program = require("commander");
  2. program
  3. .usage(" [options]")
  4. .command("init [name]", "init a project")
  5. .parse(process.argv);
第二步,问询

有了第一步的解析后,我们可以在begin-init文件中编写创建逻辑,这里,我们再抽象project文件到src目录底下,以便更好地分离职责,bin文件只负责解析命令就好啦~
下面就看看project文件中,如何实现问询

</>复制代码

  1. inquirer.prompt([{
  2. type: "input",
  3. name: "projectName",
  4. message: "请输入项目名:",
  5. validate(input) {
  6. if (!input) {
  7. return "项目名不能为空";
  8. }
  9. if (fse.existsSync(input)) {
  10. return "当前目录已存在同名项目,请更换项目名";
  11. }
  12. return true;
  13. }
  14. }]);

inquirer提供prompt函数来实现问询,其参数为数组,问询顺序将按照数组的顺序来进行;

第三步,下载仓库

在问询结束后,我们基本知道需要创建的项目的名称、描述等信息了,下一步,就是下载仓库了,下面我们来看看核心代码:

</>复制代码

  1. const downloadPath = path.join(projectPath, "__download__");
  2. download(TEMPLATE_GIT_REPO, downloadPath, { clone: true }, (err) => {
  3. // 拷贝
  4. // 此处省略若干代码
  5. // 拷贝完成后删除临时文件
  6. fse.remove(downloadPath);
  7. }

这里需要注意的是,模板工程所在的仓库,即TEMPLATE_GIT_REPO,最好是public的

第四步,复制文件,将信息写入模板

下载仓库只是把模板工程存放在一个临时文件夹内,真正的工程文件需要等信息写入模板后再生成;
这里需要注意的是,模板写入时遵循ejs规范

</>复制代码

  1. const memFs = require("mem-fs");
  2. const editor = require("mem-fs-editor");
  3. // 这里需要mem-fs进行内存优化
  4. const store = memFs.create();
  5. this.memFsEditor = editor.create(store);
  6. // 这里source表示源文件,dest表示目标文件,data表示需要写入的数据
  7. this.memFsEditor.copyTpl(
  8. source,
  9. dest,
  10. data
  11. );

在调用copyTpl时,data字段中的key-value将被写入到模板中,举个栗子:

</>复制代码

  1. // 模板文件中,字段是这样的
  2. {
  3. name: "<%= projectName %>"
  4. }
  5. // data就要这样去写
  6. {
  7. projectName: "this is your project name"
  8. }
第五步,进行git init和npm install

这两步的核心都是使用nodejs提供的child_process中exec方法去执行命令来实现,exec能帮助我们在命令行中执行shell命令,exec函数有对应的回调方法来让我们判断命令执行是否成功,核心代码如下:

</>复制代码

  1. exec("npm install", (error, stdout, stderr) => {
  2. if (error) {
  3. // 出错了
  4. } else {
  5. // 成功了
  6. }
  7. })

是不是很简单呢,想了解更多的操作可以搜索官方文档查看哈,这里就不详解了。

调试和发布

到这里,我们的cli已经实现的差不多了,这里我们总结一下如何测试和发布吧

</>复制代码

  1. npm link // 本地调试
  2. npm publish // 发布

通过npm link命令,即可以在命令行工具测试你的cli了,注意在package.jsonbin字段中定义好入口命令和文件

</>复制代码

  1. // package.json
  2. {
  3. "bin": {
  4. "begin": "bin/begin"
  5. }
  6. }
小结

OK,文章主要总结了编写一个脚手架中init功能的思路以及一些实现的方法,具体一些细节仍有优化的空间,欢迎大家讨论!
文章的具体代码可以参考我的仓库begin-cli

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105170.html

相关文章

  • 前端从零开始系列

    摘要:只有动手,你才能真的理解作者的构思的巧妙只有动手,你才能真正掌握一门技术持续更新中项目地址求求求源码系列跟一起学如何写函数库中高级前端面试手写代码无敌秘籍如何用不到行代码写一款属于自己的类库原理讲解实现一个对象遵循规范实战手摸手,带你用撸 Do it yourself!!! 只有动手,你才能真的理解作者的构思的巧妙 只有动手,你才能真正掌握一门技术 持续更新中…… 项目地址 https...

    Youngdze 评论0 收藏0
  • 从零开始搭建Vue组件库——VV-UI

    摘要:各个大厂也相继宣布开源。但是也会存在一些问题,比如每个公司可能需要的业务组件不尽相同,或者我们想自己开发一套属于自己的组件库,来增强对组件的可控性。 前言: 前端组件化是当今热议的话题之一,也是我们在开发单页应用经常会碰到的一个问题,现在我们有了功能非常完善的Element-UI。各个大厂也相继宣布开源XXX-UI。但是也会存在一些问题,比如每个公司可能需要的业务组件不尽相同,或者我们...

    BothEyes1993 评论0 收藏0
  • 从零开始搭建Vue组件库——VV-UI

    摘要:各个大厂也相继宣布开源。但是也会存在一些问题,比如每个公司可能需要的业务组件不尽相同,或者我们想自己开发一套属于自己的组件库,来增强对组件的可控性。 前言: 前端组件化是当今热议的话题之一,也是我们在开发单页应用经常会碰到的一个问题,现在我们有了功能非常完善的Element-UI。各个大厂也相继宣布开源XXX-UI。但是也会存在一些问题,比如每个公司可能需要的业务组件不尽相同,或者我们...

    wthee 评论0 收藏0
  • 为什么我不推荐你使用vue-cli创建手架

    摘要:后来经过排查你会发现是由于目前还没有版本。可以使用该方式解决。这就是我为什么不推荐你使用创建脚手架的原因此文的受众是想要进阶中级的初级前端人员。 最近在知乎看到一个问题,原问题如下: 很奇怪,为什么现在能找到自己手动创建vue脚手架的文章非常少,而且大家似乎对webpack4的热情并不高,对于想基于vue2.0+webpack4搭建一个脚手架的我来说资料真是少得可怜。难道现在一般的做...

    trigkit4 评论0 收藏0
  • 从零构建前后分离web项目》实战 -5分钟快速构建炒鸡规范VUE项目骨架

    摘要:可以使用或来安装我用来重新尝试一次对速度表示不理想的可以尝试淘宝的不要过度依赖中可以写成放哪都行,可以写成可以写成看到这个画面,安装完成了。 初步搭建脚手架 Tips 任何不错的开源项目都有 project-cli 脚手架、我们用它生成往往能快速配制出最佳的、理想的脚手架 我通常使用 cli 生成项目骨架再在之基础上进行个人修改。 什么是 CLI 命令行界面(英语:command-li...

    qieangel2013 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<