標籤:

新世紀福音腳手架

知乎專欄的編輯器非常不科學,很難用,所以我一般在本地寫了 Markdown 在博客渲染成 HTML 後再帶格式複製過來,為了更好的閱讀體驗你可以訪問本文的本體 新世紀福音腳手架。

好的作品不在於其形式,重要的是內容,我的很多音樂作品都是沒有名字的,然而沒有名字的東西無法商業流通,所以你才會看到我那些沒有特殊意義、單純靠滾鍵盤得到的名字。 —— 澤野弘之曾經這樣說過(其實並沒有)。

這篇文章也是這個道理,想介紹一下我在半年前開始做的腳手架工具。給文章起標題也是一件很困難的事,最開始想到的是「史上最優雅的腳手架工具」、「來自未來的腳手架」,不過這些未免顯得太標題黨了,華而不實我自己都很尷尬。最近我剛好做了個新世紀福音戰士標題卡生成器,於是就隨機將幾個關鍵片語合在一起 —— 新世紀福音腳手架,意外地顯得還不錯。

為了不讓你對標題不明所以,簡單地說明了它的來歷,以下才是正文。

腳手架

經常造輪子就會發現腳手架的重要性,這也是為什麼 Yeoman 的發明者之一是 @sindresorhus 的原因。後者已經在 npm 上發布了超過 1000 個模塊,很難後有來者了。

Yeoman 十分健壯,生態繁榮,然而要寫一個 generator 的複雜度和寫普通的代碼幾乎是差不多的,而我在能儘可能減少思考的時候就想減少思考,vue-cli 的思路很好地解決了我想減少思考的訴求,一個 generator 中間生成文件的過程有很多步驟是可以自動解決的。

vue-cli 雖然名字里有 vue 屬性,但是作為任意類型項目的腳手架工具都是可以的,儘管運行 vue init react 這樣的命令會顯得有些奇怪。這也是為什麼我做了 SAO 的原因,一個類似 vue-cli 的腳手架工具。在擁有 vue-cli 的功能的同時,它也能像 Yeoman 一樣用 npm package 作為模板並支持測試。

舉個例子,在運行 sao vue 的時候,如果 template-vue 這個 npm 模塊沒有全局安裝,它會提示你安裝,之後再使用模板根目錄里的配置文件 sao.js 將同目錄里的 template/ 中的文件生成到 process.cwd() 即當前目錄。如果不存在配置文件,那麼只會當成一個普通的目錄,簡單地複製粘貼到當前目錄。

?? template-vue/sao.js:

module.exports = {n // 從用戶獲取一些信息n prompts: {n pwa: {n type: confirm,n message: Add Progressive Web App support,n default: truen }n },n // 如果要發布到 npmn // .gitignore 會自動被 npm 更名為 .npmignoren // 為了避免這種情況需要起個另外的名字n // 然後在生成的時候改名為 .gitignoren move: {n gitignore: .gitignoren },n // 只在用戶確認了 pwa 選項的時候生成 pwa.jsn filters: {n pwa.js: pwan }n}n

上面的這個配置文件滿足了大部分腳手架的需求,即從用戶獲取信息 --> 根據此信息生成需要的文件。而且幾乎與代碼無關,這個配置文件完全是由數據組成的,只不過剛好是以 JS 對象的格式。

SAO 接收的第一個參數可以是:

  • 本地模板路徑,比如 ./my-template /path/to/my-template。
  • GitHub 項目縮略名,比如 egoist/template-vue。
  • npm 模塊名(自動加上 template- 前綴),比如 vue 將會使用 npm 上的 template-vue 這個包。

而第二個參數是可選的,不存在時將會生成文件到工作區目錄(當前目錄),否則將會生成到指定的文件夾中。

測試腳手架

當腳手架變得複雜,你需要系統地測試以便讓其在各種情況下都能生成正確的文件。對於一個腳手架,能從用戶影響到它的變數只有 prompts 這個參數,也就是從用戶獲取的信息。而 SAO 的測試也主要是圍繞這個來的,你可以模擬用戶輸入來檢測生成結果。

?? template-vue/test.js:

import test from avanimport sao from saonntest(generate pwa entry, async t => {n const template = process.cwd() // 模板根目錄n const res = await sao.mockPrompt(template, {n // 模擬的 prompts 數據n // 默認使用 `prompts` 中的默認值n // 在上面的 `sao.js` 中 `pwa` 默認為 `true`n })n t.true(res.fileList.includes(pwa.js))n})nntest(ignore pwa entry, async t => {n const template = process.cwd() // 模板根目錄n const res = await sao.mockPrompt(template, {n pwa: falsen })n t.false(res.fileList.includes(pwa.js))n})n

這裡的 res.fileList 是生成的文件列表,形如:

[n .gitignore,n pwa.js,n src/index.jsn]n

以及 res.files,包含了生成文件的信息:

{n .gitignore: {n contents: Buffer,n stats: {}, // fs.Stats,n path: /absolute/path/to/this/filen },n // ...n}n

最後

分享幾個我自己經常使用的模板:

  • template-nm: 生成一個 npm 模塊,我的所有模塊都是用這個生成的。
  • template-vue: 生成一個幾乎無需配置的 Vue 項目,基於 Poi。
  • awesome-sao: 相關 SAO 資源。

關於更多 SAO 的使用方法和配置文件參數,可以訪問 SAO :P 雖然本文標題是來源於新世紀福音戰士,但 SAO 顯然是來源於 Sword Art Online 的。


推薦閱讀:

npm install 生成的package-lock.json是什麼文件?有什麼用?
為什麼 npm 要為每個項目單獨安裝一遍 node_modules?
小型Web頁打包優化(下)
已經全局安裝過gulp了,為什麼運行gulp命令提示 Local gulp not found ?

TAG:npm | Nodejs | 工具 |