jdists 前端代碼塊預處理工具

jopen 10年前發布 | 29K 次閱讀 jdists 前端技術

什么是 jdists

項目地址:https://github.com/zswang/jdists

關于命名

j dist s 就是 js 里插入了一個 dist (分發),避免和其他組件命名沖突,同時特殊好記。本工具專注于前端代碼塊(js、css、html)預處理。

起因

一個頁面從開發到上線基本會經歷三個階段:

  • 本機開發調試

    • 打印一些變量和執行狀態、模擬數據接口
    • </ul> </li>

    • 內網測試

      • 跳過某些步驟、使用內網環境
      • </ul> </li>

      • 公網上線

        • 移除調試代碼、使用線上環境。
        • </ul> </li> </ul>

          其實前端代碼和其他語言代碼都需要編譯,目前已經有很多成熟的工具來完成編譯的事情。比如:fis、grunt、gulp,基本都是依賴配置文件,將項目代碼進行編譯到相應版本。

          問題

          • 代碼和配置文件是分離的,這樣開發維護起來不夠直觀。
          • 配置文件通常是基于 JSON,還是不夠直觀。
          • 調試代碼容易遺忘,有導致線上事故的風險。
          • </ul>

            思考

            那有沒有一種方法能將部分編譯邏輯寫在代碼中,就像 C 語言預編譯宏定義,代碼本身就包含了編譯邏輯不依賴配置文件就能執行:

            #include "headfile"

            ifdef DEBUG

            fprintf("variant=%d", variant);

            endif</pre></code>

            這樣不僅利于維護也方便在本機開發時調試,那么接下來需求來了!

            需求

            • 學習成本要很低。(使用 html 標記,這個大家再熟悉不過)
            • 支持 html、css、js 文件格式。
            • 本機開發調試時不依賴編譯器。(編譯邏輯寫在注釋中)
            • 不僅能 include 一個文件,還能 include 一個文件中的片段(代碼塊)。
            • 能引入當前文件的代碼塊。
            • 能夠替換代碼塊的內容。
            • 能 include 二進制文件,變為 base64 字符串,方便轉成 dataUri。
            • 自動合并 css 或 js 文件,能夠輸出合并文件并能打 md5 戳。
            • 能夠處理 注釋模板,避免被壓縮工具移除
            • </ul>
              var render = jhtmls.render(function () {
              /*!
              <div title="#{title}">#{content}</div>
              */});

              • 能夠擴展替換規則。
              • </ul>

                設計思路

                解決好如何定義代碼塊,其他問題基本就迎刃而解了。

                用什么方式來定義代碼塊?

                利用注釋 + html 標記,并且又能和普通注釋區分。

                • 在 html 中:
                • </ul>
                  <!--debug-->
                  <div>測試版本</div>
                  <!--/debug-->

                  • 在 js 中:
                  • </ul>
                    /*<debug>*/
                    console.log('測試版本');
                    /*</debug>*/

                    • 在 css 中:
                    • </ul>
                      .version {
                        font-size: 12px;
                      /*<debug>*/
                        color: red;
                      /*</debug>*/
                      }

                      一些代碼未必默認啟用,所以支持如下方式

                      • 在 html 中:
                      • </ul>
                        <!--release
                        <div>線上版本</div>
                        /release-->

                        • 在 js 中:
                        • </ul>
                          /*<release
                          console.log('測試版本');
                          /release>*/

                          • 在 css 中:
                          • </ul>
                            .version {
                              font-size: 12px;
                            /*<release
                              color: red;
                            /release>*/
                            }

                            廢棄的方式

                            <!--debug begin-->
                            <div>測試版本</div>
                            <!--debug end-->

                            • 使用 being / end 的方式,主要的問題是容易遺忘,該前綴還是后綴
                            • </ul>

                              基本概念

                              </tr> </thead>

                              </tr>

                              </tr>

                              </tr>

                              </tr> </tbody> </table>

                              標準代碼塊

                              名稱 含義 例子 備注
                              file 文件 1.js,1.png 包括二進制文件
                              block 代碼塊
                              只能是文本文件
                              block::tag 標簽 <a>
                              block::attribute 代碼塊屬性 <a encoding="md5">

                              </tr> </thead>

                              </tr>

                              </tr>

                              </tr> </tbody> </table>

                              代碼屬性(attribute)

                              tag 功能 示例
                              include 引入文件或代碼塊 <!--include file="all.js" /-->
                              replace 將當前代碼塊替換成文件或代碼塊
                              remove 將當前代碼移除

                              </tr> </thead>

                              </tr>

                              </tr>

                              </tr>

                              </tr>

                              </tr>

                              </tr> </tbody> </table>

                              編碼(encoding)

                              • original:原文
                              • string:作為字符串
                              • base64:base64 輸出
                              • md5:內容 MD5 戳(小寫)
                              • concat:合并本地 js 或 css 并可以知道輸出
                              • </ul>

                                可以通過 jdists.setEncoding(encoding, processor) 擴展

                                使用限制

                                • 代碼塊不能交叉,可以嵌套
                                • 代碼塊引用不能出現循環
                                • </ul>

                                  實戰

                                  開始使用

                                  • 依賴 npm 環境

                                    </li>

                                  • 安裝 $npm install jdists -g

                                    </li>

                                  • 命令格式 $jdists input1 [input2] [-output output] [-remove debug,test]

                                    </li>

                                  • 命令參數

                                    </li> </ul>

                              屬性名 含義 例子 備注
                              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 文件名

                              </tr> </thead>

                              </tr>

                              </tr>

                              </tr>

                              </tr> </tbody> </table>

                              處理 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.jsdist/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>/ }();</pre></code>

                              這樣就可以用靜態頁面開發 UI 組件了。

                              參考實例:https://github.com/zswang/jfpss/blob/master/src/tools.jdists

                              后續

                              參數 簡寫 功能 備注
                              -output -o 指定輸出文件 默認輸出到控制臺
                              -remove -r 指定移除的代碼塊 默認 "debug,test"
                              -trigger -t 指定觸發器 默認 "release"
                              -version -v 打印當前版本
sesese色