一些廢話(直接看代碼的可跳過)
現在前端圈子框架繁多,不乏一些自主研發或合作開發的公司內部框架,模塊/組件化、框架設計理念、架構分析、底層封裝等去搭建高樓大廈的骨架,爲的就是“維護、複用、二次開發、高效”等理念,濃縮就是兩字好用(toulan)
公司內部研發的框架體系一般都會趨向於圖形化、可視化,不過大多數都會做到最後一步,那就是模塊化的選擇了該結構,該樣式(皮膚)然後想去一鍵生成這個項目的時候,啊?沒這個功能,實現不了,npm/cnpm的一堆依賴結構不是我想要的!那這篇文章就是來解救你了,讓我們來打造屬於自己的項目結構文件依賴(是時候解放你的雙手了)。
技術實現
以下技術實現是基於js、node以及自帶的fs模塊
想要達到的目的
- 只用一句命令行,一個文件來搞定項目結構的創建
- 執行過程可視化,在cmd命令指示符中顯示文件創建的進度
- 需要有生成項目目錄的樹狀圖
- 項目結構任意化
- 代碼可二次開發性
需要的工具
- node
- cmd(命令指示符)
打造一個極簡的項目結構創建(試水篇)
步驟一:進入你想要一鍵生成的文件目錄
1、win+r輸入cmd回車
2、cd進入到該項目目錄(想一建生成目錄的地方)
3、node如何安裝自行百度
步驟二:創建server.js
打開你善用的編輯器直接複製以下代碼
var fs = require("fs")
var mkDir = ['css', 'fonts', 'img', 'module']
/* 創建目錄 */
for (var i = 0; i < mkDir.length; i++) {
fs.mkdir(mkDir[i], function (err) {
if (err) {
return console.error(err);
}
})
}
ctrl+s保存,在cmd中輸入
node server
回頭看一下你的項目結構吧。
如果不出意外的話,項目結構已經變成了這樣
這裏不得不佩服fs的強大,以下附上node fs API地址。
http://nodejs.cn/api/fs.html
步驟三:還沒完,還有讀取文件以及生成文件
上面已經出現了我們想要的項目結構,不過這需求對我們來說還遠遠不足,我們還需要創建js文件以及html文件之類呢。
1)在該目錄下創建index.html
裏面寫書寫以下代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
2)server.js
var fs = require("fs")
/* 讀取index.html文件創建indexx.html文件 */
fs.readFile('index.html', 'utf8', function (err, data) {
if (err) {
return console.error(err);
}
fs.appendFile('indexx.html', data, 'utf8', function (err) {
if (err) {
return console.error(err);
}
});
});
cmd執行
node server
回頭看下項目目錄,是否多了個indexx.html的文件,如果多了就說明成功了,以上的操作是讀取了index.html內的所有文本內容,然後創建了indexx.html的超文本,當然對fs來說,只是修改了後綴名而已。
打造一個自定義幷包含完善的Catalog、Tree、color、Path的項目結構(進階篇)
Tips:以下步驟會分步介紹各個階段的執行過程(最下方含有完整的github項目地址)
解析一:構建server.js代碼過程化
var _methods = {
data: { /*數據存放位置*/
now: 0, /*當前進程計數*/
sum: 0, /*一共進程次數*/
log: '' /*輸出的tree*/
},
_nodeInit: function (mkDir) { /*初始化*/
this._nodeSum(mkDir) /*先得出一共需要的執行次數,以便去判斷異步回來的當前次數*/
this._nodeFor(mkDir) /*進入下個流程 --- 創建*/
},
_nodeFor: function (mkDir) { /*創建*/
/*這兒是執行目錄結構創建的地方
並且每次異步回調後執行
this._nodeTree(++now)
以便去顯示當前創建進度*/
},
_nodeSum: function () { /*計算一共的創建次數*/
/*爲什麼要先獲取總共的創建次數,
因爲fs的函數創建是異步的,
過程中很難判斷全部異步是否已經完成
並且tree的創建也是在這執行的
輸出給this.tree以及this.sum*/
},
_nodeTree: function () { /*當前進度判斷*/
/*如果當前進度===總進度時
則執行之前就已經創建好了的
去console.log(this.tree)出來*/
}
}
var fs = require("fs") /*引入fs*/
var mkDir = [ /*項目結構樹一覽*/
{
name: 'csss', /*文件夾名稱*/
child: [
{
name: 'public.css', /*文件名稱*/
val: '' /*文件內容*/
}, {
name: 'asd',
child: [
{
name: 'asd'
}
]
}
]
}
]
_methods._nodeInit(mkDir)
大致流程如上,這兒有一些技術棧:
1、_nodeSum: 多線程異步的情況下,沒能很好得知是否全部執行完成,所以採用了該方式(定時器不可取)
2、_nodeTree: 樹結構console.log並不是很完美
解析二:_nodeFor:無限子節點異步回調創建目錄結構(核心代碼)
_nodeFor: function (mkDir, path) {
var self = this
for (var i = 0; i < mkDir.length; i++) {
var name = mkDir[i].name
var child = mkDir[i].child
var path_block = path ? (path + '/' + name) : name
if (name.lastIndexOf('.') === -1) { /*判斷文件or文件夾 --- 文件夾*/
(function (path, child, name) { /*防止異步回調後變量被污染*/
fs.mkdir(path, function (err) {
if (err) {
return console.error(err)
}
self._nodeTree(++self.data.now, path, name) /*加載loading*/
if (child) {
self._nodeFor(child, path) /*遞歸*/
}
})
})(path_block, child, name)
} else { /*文件*/
(function (path, val, name) {
fs.appendFile(path_block, val ? val : '', 'utf8', function (err) {
if (err) {
return console.error(err)
}
self._nodeTree(++self.data.now, path, name) /*加載loading*/
})
})(path_block, mkDir[i].val, name)
}
}
}
技術棧:
這段代碼並不是很難理解,但調試起來確實是費勁,畢竟含有遞歸+異步的40行復雜代碼誰也不能保證一次就能寫成功,在node下,無論是debugger還是console.log()在cmd中調試都很難受,這兒推薦個強大的node-debug調試環境,讓你在喜歡的谷歌下調試
技術學習or推薦
node-inspector
調試工具(基於npm安裝):node-inspector
執行流程:
1、安裝 node-inspector
npm install node-inspector -g
2、監聽端口(執行)
node-inspector
3、cmd到你的目錄下執行node debug模式
node –debug-brk server.js
4、打開谷歌瀏覽器,在地址欄輸入以上顯示的地址:http://127.0.0.1:8080/debug?port=5858 就可以進行調試了,成功後會到以下頁面,按F8即可執行到你打斷點處,如果沒打則直接結束。(如果不行請刷新下)
解析三:_nodeSum:計算總執行次數
console.log('\x1B[90m' + 'Downloading Current JS to ' + __dirname + '\x1B[39m')
var self = this
function count (mkDir, j) { /*i爲次數, j爲層級*/
for (var i = 0; i < mkDir.length; i++) {
(function (mkDir, i, j) {
var log = log_j(j)
var name = mkDir[i].name.lastIndexOf('.') === -1 ? mkDir[i].name : ('\x1B[90m' + mkDir[i].name + '\x1B[39m')
self.data.log += log + '--' + name + '\n'
if (mkDir[i].child) {
count(mkDir[i].child, ++j)
}
self.data.sum++
})(mkDir, i, j ? j : 0)
}
}
function log_j (val) {
var log = ''
if (val === 0) return '|'
for (var i = 0; i < val; i++) {
log += ' ' + '|'
}
return '|' + log
}
count(arr)
console.log('\x1B[90m' + 'Altogether contains ' + this.data.sum + 'second Execution process' + '\x1B[90m')
簡述:
這兒是在異步執行_nodeFor之前就先預解析完了樹結構以及總共的執行次數,因爲是同步遞歸思想,只要注意作用域以及避免變量污染即可。
技術棧:
那就是之前提過的,沒有一個好的方法可以監聽到多線程異步的回調是否全部執行完成,如果有的話請在下方評論並且沒有很好看的輸出樹結構,仍然有些瑕疵。
技術學習or推薦
讓你的console.log色彩繽紛
這兒有兩種,一種是node上的寫法,一種是平常網頁調試的寫法(兩者不同)
1、node寫法
console.log('\x1B[90m' + 'Hello, Do you think my color has changed?' + '\x1B[39m')
/* 顏色參考值 */
'bold' : ['\x1B[1m', '\x1B[22m'],
'italic' : ['\x1B[3m', '\x1B[23m'],
'underline' : ['\x1B[4m', '\x1B[24m'],
'inverse' : ['\x1B[7m', '\x1B[27m'],
'strikethrough' : ['\x1B[9m', '\x1B[29m'],
'white' : ['\x1B[37m', '\x1B[39m'],
'grey' : ['\x1B[90m', '\x1B[39m'],
'black' : ['\x1B[30m', '\x1B[39m'],
'blue' : ['\x1B[34m', '\x1B[39m'],
'cyan' : ['\x1B[36m', '\x1B[39m'],
'green' : ['\x1B[32m', '\x1B[39m'],
'magenta' : ['\x1B[35m', '\x1B[39m'],
'red' : ['\x1B[31m', '\x1B[39m'],
'yellow' : ['\x1B[33m', '\x1B[39m'],
'whiteBG' : ['\x1B[47m', '\x1B[49m'],
'greyBG' : ['\x1B[49;5;8m', '\x1B[49m'],
'blackBG' : ['\x1B[40m', '\x1B[49m'],
'blueBG' : ['\x1B[44m', '\x1B[49m'],
'cyanBG' : ['\x1B[46m', '\x1B[49m'],
'greenBG' : ['\x1B[42m', '\x1B[49m'],
'magentaBG' : ['\x1B[45m', '\x1B[49m'],
'redBG' : ['\x1B[41m', '\x1B[49m'],
'yellowBG' : ['\x1B[43m', '\x1B[49m']
2、Web端調試寫法
console.log("%cHello, Do you think my color has changed?", "color: green")
這個一看就懂了。
解析四:_nodeTree:當前值與sum的比較輸出打造猶如cnpm的實時進度
_nodeTree: function (now, path, name) { /*異步過程界面化*/
console.log('[' + now + '/' + this.data.sum + ']\x1B[90m ' + name + '\x1B[39m' + '\x1B[32m' + ' installed ' + '\x1B[39m' + 'at ' + path)
if (now === this.data.sum) { /*噹噹前進度 === sum時*/
console.log('\x1B[32m' + 'All package installed ' + this.data.sum + ' project installed from ' + __dirname + '\x1B[39m')
console.log('\x1B[35m' + 'Project catalogue:' + '\x1B[39m')
console.log(this.data.log + '------------------------------------')
console.log(",'''╭⌒╮⌒╮.',''',,',.'',,','',.\n" +
" ╱◥██◣''o',''',,',.''.'',,',.\n" +
"|田|田田│ '',,',.',''',,',.''\n" +
"╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬" + '\n------------------------------------')
console.log('\x1B[35m' + 'MAKE:o︻そ╆OVE▅▅▅▆▇◤\nBLOG:http://blog.csdn.net/mcky_love\nGITHUB:https://github.com/gs3170981' + '\x1B[39m')
}
}
簡述:
這兒執行的就是實時顯示當前進度以及全部執行完成後的tree與我個人的信息(#^.^#)
實時當前進度:
結束後的tree
與個人信息
解析五:mkDir:調參的數組寫法
/*------------------------注意事項------------------------
1、文件夾名稱不可相同、文件名稱相同的情況下後綴名不可相同
2、文件夾內方可創建child子項目目錄,文件下創建child對象不執行
3、文件夾名稱不可包含'.'字符
----------------------------END--------------------------*/
var mkDir = [
{
name: 'csss',
child: [
{
name: 'public.css',
val: 'body{font-size: 12px;}'
}, {
name: 'publicccc',
child: [
{
name: 'asd'
}
]
}
]
}, {
// ......
}
]
簡述:
通俗易懂的格式,不過如注意事項所說,這兒並沒有對‘.’下創建文件夾與不執行的地方進行try提示,需要的朋友可自行git修改。
一個完整的DEMO
github:https://github.com/gs3170981/cnpmDIY(好用的話記得加星哦!)
關於
make:o︻そ╆OVE▅▅▅▆▇◤(清一色天空)
blog:http://blog.csdn.net/mcky_love
結束語
自定義項目結構與自定義的框架完美契合,適用於可視化開發,模塊化合作開發,單人項目開發,多人維護等,這兒就不科普具體用處了,fs幫我們解決了大多數問題,剩下的用途僅限制於你的腦洞!