Webpack in Node:前端模板開發工具TDS

簡介

一個適合小頁面的模板開發工具,基於webpack,支持熱重載,將css、js打包到一個html模板文件中。
這個小工具的適用場景不廣,但設計思路能帶來不小的啓發。javascript

具體可移步:github.com/SP-Lyu/TDS
* 單純看成工做小總結寫了,其實能夠拆出不少細小但有用的文章css

廣告模板工具

TDS實際上是爲了一些小型的廣告模板服務的,當年接手這一塊只能手動生產這些模板,開發維護起來特別麻煩 (沒錯,本人就是靠發小廣告爲生)html

<!-- 常見的廣告模板 -->
<!-- Head -->
<style> /* Style Sheet */ </style>
<div id="{{ADID}}" class="wrapper">
  <img src="{{IMG}}" />
  <img src="{{IMG}}" />
  <img src="{{IMG}}" />
  <div><a href="{{CLICK_URL}}">{{DESC}}</a></div>
  <div class="logo">
    <!-- LOGO logic -->
  </div>
  <script> // monitor // animate logic var id = {{ADID}}; var conf = { showtime: {{TIME}} // ... } // ... </script>
</div>
<!-- Tail -->
複製代碼

在一些搜索場景或者網盟場景下面的廣告前端邏輯,每每具有如下幾個特色:前端

  • 對展示及加載速度要求高
  • 頁面簡單、交互邏輯較少,但公共組件多
  • 迭代速度快,新模板每每能刺激點擊率的提高
  • 後端會維護一套模板填入物料,聯調時先後端相互耦合阻塞

因此對於商業廣告展示的前端開發,有這幾點須要關注:java

  • 優化展示速度,去除沒必要要的請求
  • 組件化開發,批量打包更新
  • 前端須要維護一套模擬數據便於開發、測試

着手優化

根據上述的訴求點,最終產出了一個模板開發工具,以命令行的形式完成模板的開發環境初始化、開發、打包、測試等。
命令大全:node

tpl -s 切換至不一樣的業務線  
tpl -l 查看當前業務線中的模板  
tpl -i <tpl_name> 初始化新模板  
tpl -d <tpl_name> -p <port> [-q] 開發  
tpl -b <tpl_name> [-q] [-u] [-c charset] 打包模板(-u:是否不壓縮HTML文件 -c:轉換至目標編碼)  
tpl -B [-q] [-u] [-c charset] 打包當前業務線中全部模板  
tpl --delete 刪除模板  
複製代碼

下面介紹一下這個工具結合實際應用解決的幾個痛點:webpack

展示及加載速度優化

一般的頁面開發,都是前端只保留一個簡單的html,經過CDN、靜態文件、緩存等方式引入CSS與JS文件,但該方式並不徹底適用於廣告展示的應用場景。 廣告頁面 交互少,邏輯簡單 ,即便將css、js代碼徹底算上,亦不過15K左右大小,按照1MB/s的下載速度,傳輸僅須要15ms便可完成,而通常花在請求上的TTFB時間已大大超過這個值了。因此最耗時的不是資源下載,而是請求自己
因此此處的優化思路應該是:css與js以行內引入的方式打包進模板,減小資源請求數,達到展示速度最快的目的。
TDS中採用了以ejs爲模板,將打包好的css與js以字符串的形式經過webpack引入模板,達到行內引入的目的。 webpack配置:git

{
    // ...
    plagins:[
        new MiniCssExtractPlugin({
            filename: "main.css",
        }),
        new HtmlWebpackPlugin({
            files:{
                "css":[`./main.css`],
                "js":[`./main.js`]
            },
            filename: `test.tpl`,
            inject: false,
            template: `test.ejs`,
            title: tpl
        }),
        new OptimizeCSSAssetsPlugin({})
    ]
    // ...
}
複製代碼

ejs模板引入:github

CSS:
<style type="text/css"><%= compilation.assets[htmlWebpackPlugin.files.css[0]].source() %></style>
JS:
<script><%= compilation.assets[htmlWebpackPlugin.files.js[0]].source() %></script>
複製代碼

組件化開發

組件化的過程當中,要考慮到 模塊可複用 以及 業務間的模塊獨立web

模塊可複用

由於一些動畫邏輯(抽獎、彈窗、輪播等)在多套模板中是公用的,且隨着時間推移,這些邏輯的批量更改的需求若處理很差,會徒增不少開發量。就須要webpack配合上必定的腳本,進行批量打包。
在TDS中,經過Node引入webpack進行打包,並經過commander.js,將Node程序命令化,從而達到批量打包的目的。
能夠移步packer.js中看到詳細的配置引入。
在開發的過程當中,因爲想要把熱重載也加入TDS工具中,調研了一下現有的幾種方法,但最終發現,能夠直接在Node環境下引入webpack-dev-server啓動熱重載。如下是示例:

const webpack = require("webpack");
const WebpackDevServer = require("webpack-dev-server");

const compiler = webpack({
    //webpack conf
});

const s = new WebpackDevServer(,{
    quiet: false,
    contentBase: './'
});

s.listen(8808, '0.0.0.0', function(){});
複製代碼

這種方式的引入,比用webpack-dev-middleware + webpack-hot-middleware簡單多了(但不知道爲啥官方把它藏得那麼深,多是由於應用場景少吧)
官方例子

業務間獨立

不一樣業務需求會存在多個模板,這裏還得考慮一下業務獨立的問題,能更好地將TDS應用於多業務線開發。因爲運用了commander.js將TDS命令化,能夠進行不少定製,例如將開發區塊以業務線進行區分,加入了workspace的概念,能夠執行tpl -s切換工做區間,且以後的一切操做(新增、刪除、打包模板等),都是基於當前工做區間完成的。
每一個業務會有本身的初始化模板,存放至templage_xxx文件夾中,新增以後的模板文件放在src/xxx/下,打包生成的模板則放在out/xxx/下,這樣能保證每一個業務相互獨立不干擾。 這個實現起來也十分簡單,建立一個.user_config文件記錄下當前用戶所處的業務線,以此做爲工做區間進行模板配置的讀取、操做便可。

// .user_config
{
    current_workspace: 'buns'
}
複製代碼

Mock數據構造

一開始開發維護過程當中遇到的最蛋疼的問題就是,前端對於這種模板文件須要本身再去將值回填才能進行調試,對於前期的兼容性、交互、樣式等的測試十分不友好。TDS維護了一套簡單的測試方法:使用HtmlWebpackPlugin打包ejs模板的時候,配置當前的打包選項,能夠區分出當前的開發環境以及須要用到的mock數據:

// webpack配置
new HtmlWebpackPlugin({
    files:{
        "css":['out/.tmp/main.css'],
        "js":['out/.tmp/main.js'],
    },
    // ↓當前環境置爲開發環境
    dev: true,      
    // ↓將文件以字符串數組的方式,寫入mock中
    mocks: get_files(`${tpl_path}/mocks/`),
    // ↓將文件以字符串數組的方式,寫入mock中
    gmocks: get_files(`${tpl_path}/../Gmocks/`),
    filename: tpl + '.html',
    inject: false,
    template: tpl_path + '/' + tpl + '.ejs',
    name: tpl,
    workspace
})
複製代碼

數據源直接能夠經過ejs文件中的htmlWebpackPlugin.options.dev選項區分。

<% const ejs_env = htmlWebpackPlugin.options; %>
<% /*公共頭部*/ %>
<%= ejs_env.dev?ejs_env.gmocks['head.html'] : '' %>
<div id="current_show"></div>
<script> <% if(ejs_env.dev){ %> window.__g_ad_data = { title: '測試數據', img: './src/<%= ejs_env.workspace%>/<%= ejs_env.name%>/static/test.png', url: 'https://google.com' }; <% } else {%> <!-- 後端填寫數據模塊,以Google Ctemplate爲例 --> window.__g_ad_data = { title: '{{TITLE}}', img: '{{IMG}}', url: '{{URL}}' }; <%}%> </script>
<script>// handle window.__g_ad_data</script>
<% /*公共尾部*/ %>
<%= ejs_env.dev ? ejs_env.gmocks['tail.html'] : '' %>
複製代碼

這樣就能在本身開發過程當中維護一套有效的mock數據,打包項目代碼時,直接經過環境的判斷就能達到將後端模板字段打包的目的。
最終打包生成的模板:

<div id="current_show"></div>
<script> <!-- 後端填寫數據模塊,以Google Ctemplate爲例 --> window.__g_ad_data = { title: '{{TITLE}}', img: '{{IMG}}', url: '{{URL}}' }; </script>
<script>// handle window.__g_ad_data</script>
複製代碼

產出

最後的總體產出,因爲加上了js、css、html的打包邏輯,對比以前的模板體積大約降低了30%左右,且去除了css、js的加載邏輯,頁面的總體加載時間(不算圖片)接近於一次http請求的時間。
且對於開發人員來講,先後端的開發能夠完全分離,再也不須要繁瑣的溝通成本。

資料

commander.js
webpack NodeApi
webpack-dev-server NodeApi

* 有問題歡迎留言交流

相關文章
相關標籤/搜索