前言
最近小编试着做了做脚手架,再打成npm包,从中遇到了不少问题,下面来总结下。
主要知识点
- package.json
- bin目录
package.json中最重要的是两个部分,main和bin,其他的你可以随意
新建一个目录,然后是输入
npm init
之后在生成的package.json目录中使用bin和main
"main": "./bin/index.js",
"bin": {
"lgrt": "./bin/index.js"
},
bin目录
新建一个bin目录,再建立index.js,记住bin目录下必须有package.json的中bin字段下包含的文件名,上例中就是index.js,然后在第一行写上
#!/usr/bin/env node
剩下的其余事情,npm服务器和本地系统会帮你完成。
额外注意点
- 基础就是上面部分了,同目录下也必须包含package.json中main字段下包含的文件名,不然当你发布到npm上后就会出现问题
- 包名不要重复,即package.json中name不要和已有的包名(包括本地和npm服务器)冲突,前者会导致你本地运行包的时候运行了已有的包,而不是你写的这个包。后者会导致你提交不上去。
开始写脚手架
首先要注意你是在用node写,这个很容易,看看文档,用文档api,配合js你就明白了。这里简单介绍几个包
- commander 命令行交互工具,具体看npm网站上说明
- inquirer和commander类似,但是比commander强大,通常和rxjs连用,具体看npm网站上说明
- fs-extra这个是fs的增强版,并不是必须的。
有了上面这些包,就可以写个简单的脚手架 ,但是想到CRA这类脚手架,也许你想着要从git上copy一个自己已经有的模板下来,那么你需要这个包
- download-git-repo,让你从git上下载包到本地,这样就初步可以完成一个类似CRA脚手架的开箱即用功能了,但是你可以觉得我能不能帮用户在使用脚手架的过程中,直接npm install,把依赖也下载下来呢?答案是可以的。我们可以利用node的child_process这个模块执行npm install,但是这远远不够,我们还要拿到系统中的npm才可以,这个时候我们使用node中的process,process.platform确定系统,如果是win32,那么我们直接获取npm.cmd,如果不是我们获取npm即可。上面我们还没有提到如何获取npm或者npm.cmd路径,看下面那个包。
- which,官网的解释Finds the first instance of a specified executable in the PATH environment variable. Does not cache the results, so hash -r is not needed when the PATH changes.大家自行翻译,如果单词看不懂,请自行google。
到这里基本差不多了,但是还有个问题,比如我下载的模板在github上文件夹名是A,但是用户使用我的脚手架,创建了文件名为B的文件夹,这个时候如果直接下载,目录结构就是B/A/…,
而我们需要B/…,我们想到的方案是能不能下载完,把A中的文件copy到上一层,然后删除B目录。当然还有其他办法,我们把模板文件夹A下载到B目录同级的目录,然后把B目录的文件copy到已经下载好的A目录,再删除B目录,再把A目录改名成B目录。这里都要进行一次删除操作,有点麻烦,但是又不能影响用户体验,所以我们最终的方案是把A模板下载到脚手架相关的npm包下面,我们称为C,然后copy到B目录,这样不用进行删除操作,也不影响用户体验,还能对下载到本地的模板在copy到B目录前进行更改。现在只差一个问题了,如何优雅的把本地修改后的模板C,copy到最终的B目录,我们想到了gulp的copy功能,通过研究gulp部分源码,我们最终通过使用下面两个包完美的完成了任务。
- vinyl-fs和map-stream,具体看npm网站上说明
后记
本文主要都是思路,具体的代码大家可以在npm下载看。
npm i little-ghost-react-ts -g
lgrt c <AppName>
最后再说个npm publish遇到的问题,因为作者安装了nrm,使用了淘宝镜像,所以npm publish时报错了,遇到这类报错先检查是不是登陆,npm login,如果登陆了,那么就输入nrm ls检查下现在的源,如果不是npm源,那就用nrm use npm,再publish即可。
请作者喝咖啡