😔 咱也不知道咱也不敢問啊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; } } } }
這是我理解中的「腳手架」,但願其餘小夥伴也評論一下本身理解的腳手架。
😢 已經近一年沒有作過技術分享了,天天在掘金裏潛水,偶爾發點沸點,不敢在首頁發內容,總以爲本身技術不足,怕大佬噴,自尊心受到創傷。
最後分享一下個人「腳手架」,這個項目在我面試中也起到了不錯的效果: