# foxhis-cli **Repository Path**: webcc/foxhis-cli ## Basic Information - **Project Name**: foxhis-cli - **Description**: foxhis-cli 公司项目脚手架(实验产品) - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-12-08 - **Last Updated**: 2021-12-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README foxhis-cli > 前端脚手架命令工具 如何安装 ``` npm install foxhis-cli -g ``` 初始化命令 ``` foxhis-cli init // 直接回车 或者 foxhis-cli i ``` 版本号查看 ``` foxhis-cli -v ``` # 拿来即用 下载以上 git 代码以后 先修改 url git 仓库,这个是你放下载前端框架的仓库地址,换成你自己的 然后,按照下面文档,将此脚手架工具发布 npm 包 修改 npmUrl 地址 就可以按照以上命令进行用啦 ``` /* @dest: 使用配置文件 @Author: tree */ module.exports = { npmUrl: 'https://registry.npmjs.org/xxx-cli', promptTypeList:[{ type: 'list', message: '请选择拉取的模版类型:', name: 'type', choices: [{ name: '前端框架', value: { url: 'http://192.168.3.51/xxx-frame.git', gitName: 'portal-frame', val:'前端框架' } }] }], }; ``` # 脚手架说明文档:前端脚手架 CLI 生成模版命令工具(包括,npm 包的发布,脚手架的搭建,注意事项,优化等) NodeJs 的出现,让前端工程化的理念不断深入,正在向正规军靠近。先是带来了 Gulp、Webpack 等强大的构建工具,随后又出现了 vue-cli 和 create-react-app 等完善的脚手架,提供了完整的项目架构,让我们可以更多的关注业务,而不必在项目基础设施上花费大量时间。 平时我们都只专注在业务上的开发,拿起一套开箱即用的模板项目就直接干。但是,这些现成的脚手架未必就能满足我们的业务需求,也未必是最佳实践,这时我们就可以自己开发一个脚手架,那么我们使用的脚手架里面到底做了什么,如何自己搭建脚手架呢? 以下为正文,文章结构: ![](quiver-image-url/CC22E6C301F6BB7C330C520A9DE29C18.jpg) ## 提问 **1.脚手架需要实现什么?** 答:初始化项目模版能力。 **2.脚手架需要什么功能?** 答:1. 问询功能 2.下载模版(模版与脚手架分离,互不影响)3.写入模版 4.优化(git 初始化,安装依赖等) **3.用什么工具实现?** - commander.js 命令行工具 - chalk 命令行输出样式美化 - Inquirer.js 命令行交互 当然还有,download-git-repo git 仓库代码下载,ora 命令行加载中效果等优化依赖工具,都可以在此基础上,进行丰富。 以下分为两步完成:一,本地创建 cli 脚手架并测试 ;二,发布脚手架 **我们正常的流程是创建本地脚手架,绑定 git 仓库,发布包,从易到难,我们反过来,本文先讲怎么发一个最简单的 npm 包,然后把脚手架搭好了,走一遍发包流程,就 OK 了。** ## 一、发布 npm 包 ### 本地创建项目 首先,我们需要创建一个项目,这里就叫 foxhis-cli, 项目结构如下: ``` - commands // 此文件夹用于放置自定义命令 - utils - index.js // 项目入口 - readme.md ``` 为了测试,我们先在 index.js 放点内容: ``` #!/usr/bin/env node // 必须在文件头添加如上内容指定运行环境为node console.log('hello cli'); ``` 对于一般的 nodejs 项目,我们直接使用 node index.js 就可以了,但是这里是脚手架,肯定不能这样。我们需要把项目发布到 npm,用户进行全局安装,然后就可以直接使用我们自定义的命令,类似 foxhis-cli 这样。 所以,我们需要将我们的项目做下改动,首先在 package.json 中添加如下内容: ``` "bin": { "foxhis-cli": "index.js" }, ``` 这样就可以将 foxhis-cli 定义为一个命令了,但此时仅仅只能在项目中使用,还不能作为全局命令使用,这里我们需要使用 npm link 将其链接到全局命令,执行成功后在你的全局 node_modules 目录下可以找到相应文件。然后输入命令测试一下,如果出现如下内容说明第一步已经成功一大半了: ``` anna@annadeMacBook-Air job % > foxhis-cli hello cli ``` \*如果全局有 bin 相同名字的,会报错,需要把 package.json 里面 bin 起的名字修改一下 ### 发布 npm 包注意事项: 1. npm 官网注册一个 npm 账户,已有账户的可以跳过这一步 2. 使用`npm login`登录,需要输入`username`、`password`、`email` 3. `npm whoami` 检查自己是否成功登陆 4. `npm link`本地调试,上面已经调试的,跳过这一步 5. 使用`npm publish`发布 6. 每次发布 npm 包,都要修改版本号 ``` //npm publish报错 npm notice integrity: sha512-Jkfy0M/VyAkQb[...]B9Ifdw2hF2CGQ== npm notice total files: 7 npm notice npm ERR! code E403 npm ERR! 403 403 Forbidden - PUT http://registry.npmjs.org/portal-foxhis-cli-hourong - Forbidden npm ERR! 403 In most cases, you or one of your dependencies are requesting npm ERR! 403 a package version that is forbidden by your security policy. ``` 我发布包的时候,调整了几次,报错,不是 403 就是 404,那个捉急。 下面总结了几个报错检查清单: - 1. 检查 npm 包的名字跟已有的包名是否重复,要么就改个名字,或者加后缀 - 2. 如果用的是 cnpm 源,要改成 npm,方法见下面说明 registry - 3. 如果还是报 403,你的账号看是不是刚刚注册的,如果是的话,需要进入你的邮箱,验证一下邮箱。 - 4. 版本号是否更新 - 5. 如果以上 3 步修改了,还是报 403 错误,就连接手机 4g 热点再发布一下。 一般发布不了,按照以上 5 点进行检查,可以解决。 **检查第 2 步 npm 源的方法** `查看本地当前使用的registry npm config get registry 切换registry npm config set registry 临时切换registry npm publish --registry 设置完以后,再次查看当前源是否是http://registry.npmjs.org` 注意: 国内目前发布组件时,必须切换为 npmjs,否则 npm publish 也不会成功 \*\*\*\*\*\*\*\*\*\*\*\*\*\* 科普 npm registry 简单来说,npm registry 就相当于一个包注册管理中心。它管理着全世界的开发者们发布上来的各种插件,同时开发者们可以通过 npm install 的方式安装所需要的插件。 npm 官方 registry 为: 国内速度较快的为: \*\*\*\*\*\*\*\*\*\*\*\*\*\* 以上涉及到的关键命令: ``` npm link // 本地调试 npm publish // 发布 npm whoami //查看当前登陆的用户名 ``` 每次更新包需要同步更新版本号,发布的包需要发布 72 小时以后才可以废弃删除。 ## 二、本地脚手架搭建 上文中,我们既然是搭建脚手架,肯定不能只让它输出一段文字吧,我们还需要定义一些命令,用户在命令行输入这些命令和参数,脚手架会做出对应的操作。这里不需要我们自己去解析这些输入的命令和参数,有现成的轮子(commander)可以使用,完全可以满足我们的需要。 1. 安装 commander `npm install chalk commander download-git-repo inquirer ora --save` 2. 创建目录 bin/index.js 3. package.json 里面 bin 改为 ``` "bin": { "foxhis-cli": "bin/index.js" }, ``` 当然目录结构你可以随意定义,package.json 里面 bin 从哪里起,主要文件就放哪儿。 4. 创建 commander init 命令 ``` #!/usr/bin/env node const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); //命令行输出样式美化 const commander = require('commander'); //命令行工具 const inquirer = require('inquirer'); //命令行交互 const checkDire = require('./utils/checkDire.js'); const { exec } = require('child_process'); const { version } = require('../package.json'); const { promptTypeList } = require('./config'); function resolve(dir) { return path.join(__dirname,'..',dir); } //version 版本号 commander.version(version, '-v, --version') .command('init ') .alias("i") .description("输入项目名称,初始化项目模版") .action(async (projectName,cmd) => { await checkDire(path.join(process.cwd(),projectName),projectName); // 检测创建项目文件夹是否存在 inquirer.prompt(promptTypeList).then(result => { //inquirer 交互问答 const {url, gitName, val} = result.type; console.log("您选择的模版类型信息如下:" + val); console.log('项目初始化拷贝获取中...'); if(!url){ console.log(chalk.red(`${val} 该类型暂不支持...`)); process.exit(1); } exec('git clone ' + url, function (error, stdout, stderr) { //git仓库代码下载 if (error !== null) { console.log(chalk.red( `clone fail,${error}` )); return; } fs.rename(gitName, projectName, (err)=>{ if (err) { exec('rm -rf '+gitName, function (err, out) {}); console.log(chalk.red(`The ${projectName} project template already exist`)); } else { console.log(chalk.green(`✔ The ${projectName} project template successfully create(项目模版创建成功)`)); } }); }); }) }); commander.parse(process.argv); ``` 以上代码解析: 1). `checkDire`检查创建项目文件夹是否存在 ``` const fs = require('fs'); const chalk = require('chalk'); const path = require('path'); module.exports = function (dir,name) { let isExists = fs.existsSync(dir); if (isExists) { console.log(chalk.red( `The ${name} project already exists in directory. Please try to use another projectName` )); process.exit(1); //存在则跳出 } }; ``` 2). `commander init` 命令行进入交互问答 3). 交互问答用`inquirer`命令交互工具 - question 数组为交互命令配置,数组中每一个对象都对应一个执行命令时候的一个问题 - type 为该提问的类型,name 为该问题的名字,可以在后面通过 name 拿到该问题的用户输入答案 - message 为问题的提示 - default 则为用户没输入时的默认为其提供一个答案 - validate 方法可以校验用户输入的内容,返回 true 时校验通过,若不正确可以返回对应的字符串提示文案 - transformer 为用户输入问题答案后将对应的答案展示到问题位置,需要有返回值,返回到字符串为展示内容 具体使用文档: 4). 问答结束的回调`prompt`方法中 then 里的参数是一个对象,从配置里面拉取 git 仓库代码。后面你们使用的时候,拉不下来,看不是不是没有仓库代码权限。 ``` module.exports = { npmUrl: 'https://registry.npmjs.org/foxhis-cli', promptTypeList:[{ type: 'list', message: '请选择拉取的模版类型:', name: 'type', choices: [{ name: 'portal前端框架', value: { url: 'http://192.168.3.51/xxx/portal-frame.git', //框架git仓库 gitName: 'portal-frame', val:'portal前端框架' } }] }], }; ``` 5).git clone 下载前端框架。也可以用[download-git-repo](https://github.com/flipxfx/download-git-repo) git 仓库代码下载 以上,就是全部前端脚手架内容,总共四个文件,index.js 是最重要的(引用另外两个配置文件),加上一个 package.json。 执行以下命令发布: ``` npm link // 本地调试 npm publish // 发布 ``` ## 三、如何使用? 在需要用到框架的时候,新建空文件夹,执行: ``` npm install foxhis-cli -g //全局安装foxhis-cli foxhis-cli init //foxhis-cli init test ,test就是你放文件夹的名称,可以自己定义 ``` 这样前端脚手架生成模版命令工具就完成了。如果想更个性化,可以把 npm 包完善一下,包括包的版本说明,readme;丰富脚手架交互问询内容,美化操作提示等。 ![](quiver-image-url/8390BDE99634EECE9084E4D1E1A679B8.jpg) ![](quiver-image-url/62183D4860FEF933061C55CFD3B1F089.png) ## 结语 node.js,本质还是 js,js 熟悉以后,结合 node 依赖和语法,各种试错,调试,需要耐心和细心。 另外,开始做一个实例的时候,构思思路,注意流转顺序。主要以官方文档为主,网上博客文章为辅。 官方的还是靠谱一点,博客各种坑,不是过时了,就是讲的不连贯,没有可执行性。 总的来说,学习也是一个探索的过程,共同进步! 以上【完】 ## 参考: Inquirer.js: npm 包生命周期: