jdists 前端程式碼塊預處理工具
什麼是 jdists
關於命名
j dist s 就是 js
裡插入了一個 dist
(分發),避免和其他元件命名衝突,同時特殊好記。 本工具專注於前端程式碼塊(js、css、html)預處理。
起因
一個頁面從開發到上線基本會經歷三個階段:
- 本機開發除錯
- 列印一些變數和執行狀態、模擬資料介面
- 內網測試
- 跳過某些步驟、使用內網環境
- 公網上線
- 移除除錯程式碼、使用線上環境。
其實前端程式碼和其他語言程式碼都需要編譯,目前已經有很多成熟的工具來完成編譯的事情。 比如:fis、grunt、gulp,基本都是依賴配置檔案,將專案程式碼進行編譯到相應版本。
問題
- 程式碼和配置檔案是分離的,這樣開發維護起來不夠直觀。
- 配置檔案通常是基於 JSON,還是不夠直觀。
- 除錯程式碼容易遺忘,有導致線上事故的風險。
思考
那有沒有一種方法能將部分編譯邏輯寫在程式碼中,就像 C 語言預編譯巨集定義,程式碼本身就包含了編譯邏輯不依賴配置檔案就能執行:
#include "headfile"
#ifdef DEBUG
fprintf("variant=%d", variant);
#endif
這樣不僅利於維護也方便在本機開發時除錯,那麼接下來需求來了!
需求
- 學習成本要很低。(使用 html 標記,這個大家再熟悉不過)
- 支援 html、css、js 檔案格式。
- 本機開發除錯時不依賴編譯器。(編譯邏輯寫在註釋中)
- 不僅能 include 一個檔案,還能 include 一個檔案中的片段(程式碼塊)。
- 能引入當前檔案的程式碼塊。
- 能夠替換程式碼塊的內容。
- 能 include 二進位制檔案,變為 base64 字串,方便轉成 dataUri。
- 自動合併 css 或 js 檔案,能夠輸出合併檔案並能打 md5 戳。
- 能夠處理
註釋模板
,避免被壓縮工具移除
var render = jhtmls.render(function () {
/*!
<div title="#{title}">#{content}</div>
*/});
- 能夠擴充套件替換規則。
設計思路
解決好如何定義程式碼塊,其他問題基本就迎刃而解了。
用什麼方式來定義程式碼塊?
利用註釋 + html 標記,並且又能和普通註釋區分。
- 在 html 中:
<!--debug-->
<div>測試版本</div>
<!--/debug-->
- 在 js 中:
/*<debug>*/
console.log('測試版本');
/*</debug>*/
- 在 css 中:
.version {
font-size: 12px;
/*<debug>*/
color: red;
/*</debug>*/
}
一些程式碼未必預設啟用,所以支援如下方式
- 在 html 中:
<!--release
<div>線上版本</div>
/release-->
- 在 js 中:
/*<release
console.log('測試版本');
/release>*/
- 在 css 中:
.version {
font-size: 12px;
/*<release
color: red;
/release>*/
}
廢棄的方式
<!--debug begin-->
<div>測試版本</div>
<!--debug end-->
- 使用
being
/end
的方式,主要的問題是容易遺忘,該字首還是字尾
基本概念
名稱 | 含義 | 例子 | 備註 |
---|---|---|---|
file | 檔案 | 1.js,1.png | 包括二進位制檔案 |
block | 程式碼塊 | 只能是文字檔案 | |
block::tag | 標籤 |
<a> |
|
block::attribute | 程式碼塊屬性 |
<a encoding="md5"> |
標準程式碼塊
tag | 功能 | 示例 |
---|---|---|
include | 引入檔案或程式碼塊 |
<!--include file="all.js" /--> |
replace | 將當前程式碼塊替換成檔案或程式碼塊 | |
remove | 將當前程式碼移除 |
程式碼屬性(attribute)
屬性名 | 含義 | 例子 | 備註 |
---|---|---|---|
encoding | 編碼 | encoding="base64" | 預設"original",可擴充套件 |
file | 檔名 | file="all.js" | 預設當前檔案 |
type | 型別 | type="comment" | 預設"original","comment":去掉包裹程式碼塊的註釋 |
trigger | 觸發器 | trigger="release,LAN" | 預設"release",存在這些觸發器時才生效 |
js | js 檔案 | js="dist/all.js?" | 輸出的 js 檔名 |
css | css 檔案 | css="dist/all.css?" | 輸出的 css 檔名 |
編碼(encoding)
- original:原文
- string:作為字串
- base64:base64 輸出
- md5:內容 MD5 戳(小寫)
- concat:合併本地 js 或 css 並可以知道輸出
可以通過 jdists.setEncoding(encoding, processor)
擴充套件
使用限制
- 程式碼塊不能交叉,可以巢狀
- 程式碼塊引用不能出現迴圈
實戰
開始使用
-
依賴 npm 環境
-
安裝
$npm install jdists -g
-
命令格式
$jdists input1 [input2] [-output output] [-remove debug,test]
-
命令引數
引數 | 簡寫 | 功能 | 備註 |
---|---|---|---|
-output | -o | 指定輸出檔案 | 預設輸出到控制檯 |
-remove | -r | 指定移除的程式碼塊 | 預設 "debug,test" |
-trigger | -t | 指定觸發器 | 預設 "release" |
-version | -v | 列印當前版本 |
處理 js 中的 註釋模板
假設檔案 js/base.js
內容為:
var render = jhtmls.render(function() {/*!
<ul>
forEach(function(item) {
<li>#{item.title}</li>
});
<ul>
*/});
如上可以省去拼接字串的工作,直觀好維護。但經過帶壓縮後就變成:
var render=jhtmls.render(function(){});
怎麼避免 註釋模板
被替換?
$jdists js/base.js -o dist/js/base.js
生成的檔案是:
var render = jhtmls.render('<ul>\nforEach(function(item) {\n <li>#{item.title}</li>\n});\n<ul>');
jdists 預設會處理 註釋模板
釋出程式碼
假設檔案 js/net.js
內容為:
var ajax = ajax || {};
void function(exports) {
/*<replace
exports.host = 'http://api.baidu.com/1.0/getuser';
/replace>*/
}(ajax);
$jdists js/net.js -o dist/js/net.js
生成的檔案是:
var ajax = ajax || {};
void function(exports) {
exports.host = 'http://api.baidu.com/1.0/getuser';
}(ajax);
還有一種情況,是我們需要先編譯一個區域網版本
假設檔案 js/net.js
內容為:
var ajax = ajax || {};
void function(exports) {
/*<replace trigger="release"
exports.host = 'http://api.baidu.com/1.0/getuser';
/replace>*/
/*<replace trigger="LAN"
exports.host = 'http://http://192.168.1.67:8000/1.0/getuser';
/replace>*/
}(ajax);
$jdists js/net.js -o dist/js/net.js -t LAN
生成的檔案是:
var ajax = ajax || {};
void function(exports) {
/*<replace trigger="release"
exports.host = 'http://api.baidu.com/1.0/getuser';
/replace>*/
exports.host = 'http://192.168.1.67:8000/1.0/getuser';
}(ajax);
指定 trigger 的程式碼塊,會檢查是否命中配置的觸發器,如果沒有命中則不啟用功能。
合併靜態資源
還是依所見即所得
的設計思路,開發期的 html 指明瞭依賴的靜態檔案,如:
index.html
<html>
<head>
<!--replace encoding="concat" js="dist/all.js" css="dist/all.css"-->
<link rel="stylesheet" type="text/css" href="base.css">
<link rel="stylesheet" type="text/css" href="button.css">
<script src="base.js"></script>
<script src="replace.js"></script>
<!--/replace-->
</head>
<body>...</body>
</html>
$jdists index.html -o dist/index.html
生成的檔案是:
<html>
<head>
<script src="dist/all.js"></script>
<link rel="stylesheet" type="text/css" href="dist/all.css">
</head>
<body>...</body>
</html>
同時將本地靜態資源分別合併到 dist/all.js
和 dist/all.css
打包元件
通過 jdists 可以將零散的程式碼和靜態資源,拼湊為一個完整的元件
void function() {
var bar = document.getElementById('jfpss-bar');
if (bar) {
return;
}
/*<include components/jframes/src/jframes.js>*/
;
/*<include components/jhtmls/src/jhtmls.js>*/
;
/*<include src/jfpss.js>*/
createStyle(function() {/*!<!--include src/tools.html style-->*/});
var div = document.createElement('div');
div.innerHTML = function() {/*!<!--include src/tools.html html-->*/};
document.body.appendChild(div);
/*<include src/tools.html js>*/
}();
這樣就可以用靜態頁面開發 UI 元件了。
後續
- 加入自動內聯程式碼。
- 提供 fis、grunt、gulp 外掛。