😔 咱也不知道咱也不敢问啊javascript
先查查百度百科里对“脚手架”的定义吧:css
脚手架是为了保证各施工过程顺利进行而搭设的工做平台。
而后搜一下“脚手架”,基本上都是如下几类:html
此时仍是没法肯定什么是“脚手架”,也许我心目中的脚手架应该是 vue/cli 或者 create-react-app 吧,而后我打开他们的文档,可是他们的介绍上并无说这是一款脚手架...前端
😔 我最怕别人看到个人“脚手架”后说这有什么卵用...vue
看了一下我第一次在 Github 上的提交记录 Commits on Feb 13, 2017,我入行三年多,那时应该是我第一次进入前端工程化的时候吧。在此以前我在公司接手的都是一些很简单的项目,直接新建文件夹,随手下载一个jQuery,而后新建 index.html main.js style.css,有没有一样经历的小伙伴们?java
后来作的项目多了,以为每次这么新建项目太麻烦,我新建了一个文件夹,专门存放初始的模板,而后复制粘贴,继续撸。node
再后来,接触到 vue,他能够实如今终端内输入一行指令就能生成模板,这可比我复制粘贴看起来高端多了,为了装逼我开始了研究如何开发本身的“脚手架”。react
当时还真是没有几篇文章把这种操做说的很明白,甚至我并不知道我要作的东西叫什么(脚手架)。webpack
🤓 百科里说的很对个人思路,首要的就是保证个人项目能够顺利进行。ios
从零搭建这种我就不说了,毕竟一搜一堆,基本上就是推荐几个库,例如 commander、inquirer、ora 等等。分享一些在个人脚手架开发时遇到的一些问题和需求,分享想给你们。
首先推荐工具库:
semver,版本对比。
request,发送请求,固然你也能够用 axios。
const semver = require('semver'); const request = require('request');
若是你的脚手架想分享给别人用,这步最好不要避免,由于若是你用了一些现代化的 ES 语法,好比说 async await,老版本跑不起来的。
function checkNodeVersion (wanted) { // process.version 能够获取当前的 node 版本 if (!semver.satisfies(process.version, wanted)) { console.log('Node版本不支持巴拉巴拉'); // 退出进程 process.exit(1); } }
正如上面所说,你若是分享给别人用,在你修改了一些 bug 后,但愿其余人用最新的版本,那就应该提示他。
function checkPackageVersion(url) { return new Promise((resolve, reject) => { request(url, function (error, response, body) { if (!error && response.statusCode === 200){ let version = JSON.parse(body).version; if (semver.lte(version, requiredVersion)) { resolve(); } else { console.log('须要更新你的包巴拉巴拉'); process.exit(1); } } else { console.log('发送请求失败巴拉巴拉'); resolve(); } }); }); }
参数 url 固然传入 npm 的连接 https://registry.npmjs.org/[你的包名]/latest
若是不作这层判断,你新生成的项目极可能会覆盖你已有的项目,别问我为啥想到这么作 😭
function hasFolder(name) { return new Promise (resolve => { fs.exists(name, exists => { if (exists) { console.log('已经存在相同目录巴拉巴拉'); process.exit(1); } else { resolve(); } }); }); };
这里加了一层 Promise 是由于 Node 去检测是否存在文件夹是个异步操做,也须要耗时,这么作比较保险。
当你输入完命令后,好像进入了新的页面同样,看起来很舒服。
function clearConsole(color, str) { if (process.stdout.isTTY && store.cmd !== 'test') { const blank = '\n'.repeat(process.stdout.rows); console.log(blank); readline.cursorTo(process.stdout, 0, 0); readline.clearScreenDown(process.stdout); } }
不少关于若是构建脚手架里提到一个工具 download-git-repo,在 github 或其余仓库中下载模板。我并非很喜欢这种操做,一、耗时,让脚手架构建速度更慢了,在没有网络的状况下没法构建。二、在 git 仓库中还须要新建项目模板,感受把一个项目分离成了两个,不方便管理。
因此我打算直接从全局目录下将模板文件夹拷贝到当前路径下:
使用一个工具 fs-extra,node.js 新手最好不要试图用原生接口拷贝一个文件夹。
const src = path.resolve(__dirname, '../template');
const dest = path.resolve(process.cwd(), store.dirname);
两个概念:
全局环境路径:
const src = path.resolve(__dirname, '你的模板文件夹相对路径')
当前环境路径:
const dest = path.resolve(process.cwd(), '你建立项目的名称');
fs.copy(src, dest).then(() => /* 巴拉巴拉 */);
如今用 yarn 的人愈来愈多,并且确实效率很高,若是安装过 yarn 就让它做为默认包管理器去自动安装依赖吧。
function packageManagement() { try { child_process.execSync('yarnpkg --version', { stdio: 'ignore' }); return 'yarn'; } catch (e) { return 'npm'; } }
这里用到 Node.js 中的 child_process.spawn 方法
这里举个例子,想要执行 npm install webpack -D
const ls = spawn('npm', ['isntall', 'webpack', '-D'], {shell: true}); ls.on('close', (code) => /* 巴拉巴拉 */)
这里推荐安装的包带有版本号,若是直接安装会安装最新版,可能会致使不兼容。
ProgressPlugin,用于监听编译进度。
plugins: [ new webpack.ProgressPlugin(function(percentage) { // percentage 进度 0-1 }) ]
这里配合前面说到的清空控制台,能够实现更好的体验。
这里指的是经过 webpack 启动的 devServer。
host 配置为 0.0.0.0
经过下面的函数获取到本机的 IP 地址,这样就能够在同网下使用移动设备作测试了。
function getIPAdress() { let interfaces = require('os').networkInterfaces(); // eslint-disable-next-line guard-for-in for (let devName in interfaces) { let iface = interfaces[devName]; for (let i = 0; i < iface.length; i++) { let alias = iface[i]; if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) { return alias.address; } } } }
这是我理解中的“脚手架”,但愿其余小伙伴也评论一下本身理解的脚手架。
😢 已经近一年没有作过技术分享了,天天在掘金里潜水,偶尔发点沸点,不敢在首页发内容,总以为本身技术不足,怕大佬喷,自尊心受到创伤。
最后分享一下个人“脚手架”,这个项目在我面试中也起到了不错的效果: