請問如何學習nodejs並且達到能開發類似fis,spm的水平 有好的教程嗎?

最近看到出現了不少前段工具框架,但是有些並不能滿足我的需要,比如我想在fis中開發一個插件,實現類似模版繼承的功能,但是我只想針對html。所以我想學習下nodejs的開發,網上搜索了部分教程,但是沒有具體實例,讓我摸不著頭腦。

我在npm裡面看spm,fis等的包里都是xxx.tgz的文件和一個package的一個文件夾,我甚至都不知道這個是怎麼做出來的,求各路大神指導,視頻,教程都行,謝謝


學習再好的 Node.js 也開發不出 fis 和 spm,雖然 @伊諾 說 fis 代碼少。

fis 和 spm 是解決前端工程化的工具,包含了很多成熟(當然也有不成熟的)架構思想。這些思想才是 fis 和 spm 的精髓。掌握了這些,不用 Node.js 用其他語言也可以開發出它們來。


比較贊同 @寸志 的說法,但對於初學者談思想有可能會更加增加困惑性,我只想說其實題主可以把它想的很簡單,而且有一定規律可循。

源碼分析

首先我們來分析下spm,對於spm其實從開始到現在已經有好幾個版本,最近主推的是目前最新基於webpack的版本,下面我們開始分析下:

1. 一切從package.json開始

package.json是npm包管理器的配置文件,spm也利用了這個文件進行包管理,簡單點就是這是個json文件,spm也將自己的配置以json的格式保存在此文件中。參考:https://docs.npmjs.com/files/package.json和docs/package.json.md at master · spmjs/docs · GitHub

對於spm最重要的就是dependencies和bin,一個列出了所有的依賴,一個是主入口文件。

"dependencies": {
"archy": "~1.0.0",
"babel-core": "~4.7.16",
"chokidar": "~1.0.3",
"co": "~4.6.0",
"colorful": "~2.1.0",
"commander": "~2.5.0",
"crequire": "~1.5.3",
"debug": "^2.1.1",
"empty-dir": "~0.1.0",
"exeq": "~2.0.0",
"extend": "~2.0.0",
"father": "~1.0.0",
"fs-extra": "~0.13.0",
"fs-symlink": "1.1.0",
"fstream": "~1.0.3",
"fstream-ignore": "~1.0.2",
"glob": "~5.0.12",
"gnode": "~0.1.1",
"gulp-template": "~1.1.1",
"inherits": "~1.0.0",
"inquirer": "~0.8.0",
"internal-ip": "~1.0.0",
"istanbul": "~0.3.5",
"istanbul-instrumenter-loader": "~0.1.2",
"mocha-phantomjs": "3.5.6",
"nico-spm": "~0.5.2",
"phantomjs": "~1.9.1",
"react-tools": "~0.12.2",
"request": "~2.51.0",
"rimraf": "~2.2.8",
"scripts-hook": "~0.1.3",
"semver": "~4.1.0",
"spm-client": "~0.4.0",
"spm-log": "~0.1.1",
"spm-webpack": "~0.7.0",
"spm-webpack-server": "~0.7.0",
"spmrc": "~1.2.0",
"tar": "~1.0.3",
"test-console": "~0.7.1",
"through2": "~2.0.0",
"uniq": "~1.0.1",
"vinyl-fs": "~0.3.13",
"whoami": "~0.0.3",
"win-spawn": "~2.0.0"
},
"bin": {
"spm": "bin/spm"
}

當我們看到如此多的dependencies先不要急著嚇尿,其實真相只有一個:"spm-webpack": "~0.7.0"。題主有可能會問你怎麼知道呢?好吧放秘訣:看主入口文件,根據84行可以看出如果執行spm build其實就是執行bin/spm-build。

// 文件:bin/spm中84行開始
function executable(subcmd) {
var file = join(__dirname, "spm-" + subcmd);
if (exists(file)) {
return file;
}
}

然後我們打開bin/spm-build文件,忽然間發現了真相,原來真正重要的是spm-webpack,這時我們可以跳到它的源碼了:spmjs/spm-webpack · GitHub

require("spm-webpack/cli");

2. 需要知道盡量多的Node.js庫(npm天天逛)

首先我們繼續,進入:spmjs/spm-webpack · GitHub,先看package.json,從dependencies中可以看出出現最多的就是xxx-loader,這時題主可能會想why?因為我提前Google了下,知道了webpack,知道了loader(可參見:how to write a loader)

好吧進入正題,

  • 文件spm-webpack/cli.js at master · spmjs/spm-webpack · GitHub,第87行知道依賴了lib/build文件

  • 然後我們進入此文件spm-webpack/build.js at master · spmjs/spm-webpack · GitHub,第38行:

var compiler = webpack(webpackOpts);

看到這裡其實已經沒有多看的必要了,大體可以猜出作者意圖了:

webpack是現成的,我需要寫個工具來按照我的思路將loader和配置合理的組裝在一塊,最終的結果就是產生一個webpackOpts

3. 多Coding!多Coding!多Coding!

寫過Node.js庫的coder或多或少的聽過TJ,他是如此高產,但問其如何時(TJ Holowaychuk是怎樣學習編程的? - 前端外刊評論 - 知乎專欄),大神也不過是:just read other people"s code and always wonder how things work

=================這是分割線======================

如何開始

首先讓我們看看題主說的:實現類似模版繼承的功能

人生苦短先別急著寫

題主有可能想:恩,一個模板繼承的功能,開始寫吧,我們有兩種方案,一種可以簡單的通過正則表達式直接替換內容;另一種我需要解析html,根據AST找到替換的內容然後進行分析替換...

其實我想說已經有這麼多的前端模板實現了此功能為什麼不拿過來用用呢?然後我們用這種思路設計一下:

  1. 首先找一下實現了模板繼承功能的模板,我找到了swig:Swig - A Node.js and Browser JavaScript Template Engine

  2. 然後我想我設計的庫實現這樣的功能:xxx input.html output.html,其中xxx是我們Node.js庫的名字,input.html是包含模板繼承的html文件,output.html是編譯後的文件。

  3. 這時我們整理下我們需要用到哪些庫

    • swig,這是必須的

    • commander,spm中用到了這個,用來解析我們傳入的命令行參數

    • colorful,spm中用到了這個,可以將我們的命令行輸出變成彩色的,這樣好看點

  4. 然後開始寫package.json

// 初始化一個package.json
npm init
// 安裝依賴
npm i swig --save
npm i commander --save
npm i colorful --save
// 創建入口文件
touch index.js

仿照spm,我們index.js內容如下:

#!/usr/bin/env node

require("colorful").colorful();
var fs = require("fs");
var swig = require("swig");
var program = require("commander");
var pkg = require("./package");

program
.version(pkg.version, "-v, --version")
.usage("& &")
.on("--help", printHelp)
.parse(process.argv);

var inFile = program.args[0];
var outFile = program.args[1];

render(inFile, outFile);

function render(inFile, outFile) {
// 這裡我們將數據存在package.json中
var data = pkg.sdata || {};
var content = swig.renderFile(inFile, data);
fs.writeFileSync(outFile, content);
}

function printHelp() {
console.log(" Example:".to.bold.magenta.color);
console.log();
console.log(" xxx input.html output.html".to.green.color);
console.log();
}

package.json文件內容:

{
"name": "xxx",
"version": "1.0.0",
"description": "xxx template render",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" exit 1"
},
"keywords": [
"template"
],
"author": "helloyou",
"license": "MIT",
"dependencies": {
"colorful": "^2.1.0",
"commander": "^2.8.1",
"swig": "^1.4.2"
},
"bin": {
"xxx": "index.js"
},
"sdata": {
"pagename": "awesome people",
"authors": ["Paul", "Jim", "Jane"]
}
}

新建一個測試文件input.html

&{{ pagename|title }}& & {% for author in authors %}
& {{ author }}
& {% endfor %}
&

然後我們可以執行:

chmod +x index.js
./index.js input.html output.html

當然這裡還有很多缺陷,但是它已經可以簡單的執行了,剩下的就是應該如何設計的問題,比如sdata不應該放在package.json里,比如可以寫成gulp或grunt插件等等,這些都是需要在寫之前要設計好的。所以題主其實寫個工具庫其實真的不是很難,關鍵在於設計的是否合理,後面是很難做到的


額。

其實就類似於,如何學習砌牆以達到蓋出羅馬斗獸場的能力。


了解了fis裡面最重要的,為什麼要產出一個map.json後,寫一個fis並達到可用不過是時間問題罷了。


安利一下近期寫的前端工具 Tam: arrowrowe/tam · GitHub...... 剛一百多 commits 並且 commit 都挺小, 也許適合回溯著看看......

What is Tam?

Use Tam to copy, compress, combine, compile and hash static files for packages with dependencies, providing a resource list for each package.

簡單說就是使用者維護一個 assets.json, 把靜態資源按互相依賴的 package 組織起來, 由 Tam 來處理(複製/壓縮/合併/編譯scss/加哈希)並生成每個 package 所需引用的 js 和 css 列表. Tam 只做這些事情.

主要工作分 prepare, build, link,

1. prepare, 遍歷 assets.json 指定的包, 列出每個包實際依賴的所有其他包, 根據複製/壓縮模式決定包內(不含依賴)文件接下來分別如何處理, 確定未哈希的輸出路徑.

2. build, 按 prepare 的結果逐個處理就行了, 如果要加哈希, 輸出前再改一下路徑.

3. link, 將 build 結果中的完整路徑去掉 assets.json 中指定的 www 路徑, 再把每個包依賴著的文件都加上, 列出每個包實際需要引用的所有 js 和 css 文件.

底層依賴了 CleanCSS, UglifyJS 和 node-sass, 其餘的包裝成命令行和調試信息輸出等等, 直接用了 command-line-args 和 log4js 等良心庫...... 測試用 mocha + chai + sinon + istanbul, 開 eslint 和 ghooks 強制檢查......

具體如何開始, 前輩 @徐振震 寫得很詳細了......


看了下, fis 結構挺簡單的, 代碼量也很少. 所以我估計你的困惑在於不知道 nodejs 項目的代碼是怎麼組織的. nodejs 項目普遍用的是 npm 包管理. 我建議你了解以下兩個:

1. nodejs 的 module 方式: Modules Node.js v0.12.4 Manual Documentation

2. npm 相關: https://docs.npmjs.com/misc/developers

之後應該就比較清晰了, 不會無所適從.


軟體研發,首先是設計,然後才是開發。——《庖丁解牛》


推薦閱讀:

對於前端,有哪些好的chrome插件或應用可以使用?
HTML & CSS 現在還多人用嗎?
react.js在伺服器端渲染有什麼好處?渲染是怎麼個流程?
A && B || C 的效率比 A ? B : C 更高嗎?
angular 和 React 想選擇一個學習,哪個比較好?

TAG:前端開發 | JavaScript | Nodejs |