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

* 有问题欢迎留言交流

相关文章
相关标签/搜索