element用腳本自動化構建新組件的實現示例
背景
在公司的項目中,每次碰到新需求的時候,你是不是都還在用新建頁面 => 往頁面中添加內容,如vue模板 => 添加路由。難道不覺得麻煩嗎?如果是的話,不妨試試自動化構建吧,太香瞭~
element-ui的自動化構建是怎麼做的
在開源項目中,特別是UI庫的開發,有太多人協同,每個人的code習慣也都不一樣。並且UI庫中每個組件都還會涉及到多語言、單元測試、路由、組件的readme.md文檔等文件。所以如果每次都慢慢去創建這些則太麻煩瞭,並且多人修改公共文件如路由文件會產生非常多的沖突。所以在開源項目中都會有非常多的腳本,去自動化生成某些文件。
makefile
在element-ui項目根目錄有個makefile文件,每條命令的作用都在註釋中。windows用戶要使用make命令執行腳本得下載。mac用戶不需要。
@# 默認的#註釋會在日志中輸出,@#則不會 @# .PHONY的作用: 在下方的腳本命令中忽略檢查是否與dist、test目錄沖突,也就是說無論如何都會去執行命令 .PHONY: dist test @# 執行make命令時,默認執行help腳本 default: help @# 執行`make build-theme`就是執行`npm run build:theme`腳本, @# : 冒號前面為執行的命令,冒號後面第二行第一個應該為一個tab,tab之後跟腳本命令 @# 也就是說下面的為 'tab+npm npm build: theme' # build all theme @# 上面的build theme註釋可以查看下方的截圖,會在日志中輸出 build-theme: npm run build:theme install: npm install dev: npm run dev @# $()為使用函數 @# $@ 為當前命令本身比如 'make new',$@ 就是 new @# MAKECMDGOALS 特殊變量,該變量記錄瞭命令行參數指定的目標列表,也就是說使用這個變量,我們可以得到命令行的參數 @# 比如我們在創建新組件時,使用腳本`make new wailen` MAKECMDGOALS 就等於 wailen @# filter-out 反過濾函數,過濾掉 $(MAKECMDGOALS) 中所有含有 $@ 的內容 @# 結合new.js的內容,下方腳本的意思也就是創建新組建,傳入組件名稱,組件名稱不得為new,如果組件名稱取為new,可以查看下方截圖 new: node build/bin/new.js $(filter-out $@,$(MAKECMDGOALS)) @# 省略瞭一些腳本,感興趣的可以自行查看源碼 help: @echo " \033[35mmake\033[0m \033[1m命令使用說明\033[0m" @echo " \033[35mmake install\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 安裝依賴" @echo " \033[35mmake new <component-name> [中文名]\033[0m\t--- 創建新組件 package. 例如 'make new button 按鈕'" @echo " \033[35mmake dev\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 開發模式" @echo " \033[35mmake dist\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 編譯項目,生成目標文件" @echo " \033[35mmake deploy\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 部署 demo" @echo " \033[35mmake pub\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 發佈到 npm 上" @echo " \033[35mmake new-lang <lang>\033[0m\t\033[0m\t\033[0m\t--- 為網站添加新語言. 例如 'make new-lang fr'"
# 註釋輸出
過濾new關鍵字,當傳入參數為new時,過濾掉
當然,如果不想使用make直接執行node腳本即可,比如make new 組件名 等同於 node build/bin/new.js 組件名
new.js
new.js為自動化的核心文件。我們先思考一下,創建組件文件無非就是兩個步驟
- 創建文件
- 添加內容
file-save
主要是通過file-save這個包創建文件並添加內容。先來看看api
const fileSave = require('file-save'); const content = "const fs = require('fs');" const callback = () => { console.log('腳本執行') } fileSave('文件路徑') .write('文件內容比如上面的content', 'utf8', callback) // 內容寫入成功會觸發回調 .write('繼續添加content','utf8') .end('\n') // 文件操作結束,以空白行結束
如此便會生成如下文件
更多的文檔可以查看file-save
element-ui中就是先通過一個Files數組對象管理瞭需要創建的filename以及code content。
這樣直接循環Files就能創建對應的文件瞭。
// 創建 package // 組件生成的目錄 const PackagePath = path.resolve(__dirname, '../../packages', componentname); Files.forEach(file => { fileSave(path.join(PackagePath, file.filename)) .write(file.content, 'utf8') .end('\n'); });
引用資源文件的修改
另外,一般創建瞭組件還需要修改相應需要引用組件的地方,比如路由配置文件等。我們同樣可以通過file-save去添加對應的路由。本身file-save會覆蓋之前文件中的內容,也就是刪除過後重新再次生成。所以如果是在原有基礎上做增的操作的話,就需要獲取到原有文件的內容,再在此基礎上拼接新內容。我們可以這樣做:
const fileSave = require('file-save'); const fs = require('fs'); const content = `const fileSave = require('file-save'); ` const oldCode = fs.readFileSync('./demo.js') fileSave('demo.js') .write(oldCode+content, 'utf8') .end('\n')
也就是通過fs模塊讀取到文件的舊內容,再拼接即可。element-ui是這麼做的:
fs.createWriteStream
file-save原理就是通過fs.createWriteStream這個api做瞭一層封裝。
簡單說下使用
const fs = require('fs') //創建可寫流 fs.WriteStream 類的對象,繼承自 <stream.Writable> const writer = fs.createWriteStream('createStream.js', { // 查找該文件,沒有則創建 //默認值為w, 通過調用writer.write方法寫入數據的時候,會直接覆蓋文件所有的內容, // 即會把文件之前的內容全部再刪除,寫入新的數據 flags: 'w' }) //寫入數據到流 writer.write('這個文件的新內容')
file-save的源碼內容可以查看下面的偽代碼。
const savefs = {} savefs._create_dir = function (fp, opts) { mkdirp.sync(fp, opts); } savefs.wstream = function (file) { var ws = fs.createWriteStream(file); this.writer = ws; return this; } savefs.write = function(chunk, encoding, cb) { ... } savefs.end = function(chunk, encoding, cb) { ... } savefs.finish = function(cb) { ... } savefs.error = function(cb) { ... } export { savefs }
當然,其實我們可以直接使用node的fs.writeFile這個API去創建文件,
fs.writeFile('文件路徑','要寫入的內容',['編碼'],'回調函數');
可以發現參數跟file-save一樣
總結
歸根到底,自動化創建組件無非就是兩個核心創建文件 添加內容。通過file-save這個包就可以實現這兩個操作,然後我們再結合自身的業務,配置好生成文件的路徑與內容,以及做好某些公共文件對新文件資源引用的修改即可。有沒有覺得node寫腳本,比寫後端有意思多瞭~
到此這篇關於element用腳本自動化構建新組件的實現示例的文章就介紹到這瞭,更多相關element腳本自動化構建新組件內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- PHP中include和require的使用詳解
- Node.js實戰之Buffer和Stream模塊系統深入剖析詳解
- 詳解PHP中的命名空間
- 關於node編寫文件上傳的接口的坑及解決
- Python openpyxl 無法保存文件的解決方案