在静态页面目录中,同子目录下的页面往往有很多通用的模块。
平常的编码一般是通用的代码直接复制到各个页面,样式写成公用,然后在各个需要的页面引用。
而一个产品在实地运行中往往要经历无数次的迭代,于是页面文档结构和样式也在不断的变化。
独立性的页面比较轻松,一个页面修改就好了,而一些公用的页面模块往往需要在各个页面逐个修改。
这显然是一种极其枯燥的重复性动作!

在此之前我用 C# 写了一个文件批量替换的工具,用于批量替换某个目录下的某个模块代码。
虽然效率提高了一些,但是从方法学角度看绝对不是最好的。

很久之前就想过使用前端模块拼装 html。
ejs 为例,则需要在页面中引入模版解析文件 ejs.js,页面中还需要写一些 ejs 相关的配置代码。而这些东西对于后端套用页面来说是无用的,可能还会造成一些混乱。
还有一种引用方式是使用 nodeJs 调用 ejs 去解析模版文件,这样在预览静态页面时则需要建立 node 服务器。而当前团队中并不是每个人都装有 node 环境。

最近工作闲暇了又想到这个问题,其实要解决的最根本问题就是:

模块化开发页面,开发完成后可以一条指令合并成可直接预览的静态页面。

我早该想到 gulp 了,既然 gulp 是一个基于流的前端构建工具,那么对于这个问题应该是可以解决的。

起初我是这样想的:

  1. 模板中使用相对路径标记模块引用
  2. 读取文件把这些标记还原为路径
  3. 读取这些路径的文件内容插入到模板中
  4. 生成到对应目标目录

这样做等于实现了一套模版解析合并的过程,并不困难。

在探索的过程中,我发现了一个基于 gulp 和 ejs 的插件 gulp-ejs,并按照示例实验后达成了我的想法。
随后新的问题便来了。

每个页面有着不同标题和样式、脚本引用,虽然可以在执行 gulp 任务时指定参数,但是不可能每个页面的参数配置都一样。
难道要为每个页面编写一个任务?你会甘心用这么傻的办法吗?
从设计模式角度讲,这个任务应该是唯一的,但是可以根据一些参数配置达到多态!

之后我改造了 gulp-ejs

  1. 在模板文件同级目录下添加同名的 .json 配置文件
  2. 在其对模板渲染时获取模板路径,再转换后缀为 json,这样就匹配到了对应的配置文件
  3. 解析 json 文件为 json 对象,作为参数传入 ejs 中,这样模版内就可以访问配置文件的数据了
  4. 之后便可以根据配置文件随心所欲的插入当前页面的特定项目

这样标题、样式、脚本,神马都解决了!

就在刚才我又想到了另外一个主意。

如果你觉得每个模板对应一个 json 文件麻烦的话,可以只建立一个配置文件。
假如你有 index 、product 、service 三个模版,那么你的配置文件可以这样写:

{
"index": {
"title": "首页"
},
"product": {
"title": "产品页"
},
"service": {
"title": "服务页"
}
}

那么在 index 模版中输出 title,就可以写成 <%=index.title %> 这种格式。
长久下去配置文件一定会越来越大,而且每个模版中都被注入了整站的配置项,真的好吗?

  • 为了使每个页面只注入当前页面的数据,可以在模版渲染前拿到模版名称,如 index ;
  • 向 ejs 传入的数据就变成了 config["index"]
  • 这样在每个模版中依然可以直接用 <%=title %> 这种格式调用了

不管采取哪种办法,最终的结果是一致的。哪怕是每个模版注入整站配置的做法,也只是在 gulp 任务阶段执行效率低点,并不会上升到影响性能的高度。
不过,我还是倾向于一个页面对应一个配置文件的办法,谁让我是处女座。

以下是对该方案的简单描述。

目录结构

├ templates     模版
├──── _partial      模块
├──────── header.ejs   
├──────── footer.ejs
├──────── nav.ejs
├──────── left.ejs
├──────── right.ejs
├──── index.ejs    布局页
├──── index.json    布局页配置文件
├ html      页面
├──── index.html    生成的静态页面
├ node_modules  node模块
├ gulpfile.js   gulp

工作流程

  1. 模板编码,即 templates/ 目录,一个布局页对应一个同名静态页面,按需引入或编写新的页面模块。在这个阶段可以使用express建立node服务器进行实时页面预览。
  2. 编写配置文件,使用通用的 json 格式,一个页面对应一个同名的配置文件。目前预想的配置信息有: title:页面标题styles:依赖的样式文件路径scripts:依赖的脚本文件路径 ,随时可以根据实际情况添加新的配置。
  3. 执行 gulp 任务,生成页面到 html/ 目录。

未模块化页面的处理

之前未模块化的静态页面,保持原样即可,因为在这个流程中与之前的页面是没有任何冲突关系的。
一些频繁修改的页面,可以按需抽取出模块,进行页面分割。

完整Demo

https://github.com/yscoder/gulp-ejs-demo

写在最后

可能我所做的这些对于国内一些优秀的前端团队来说很土,但是适合的才是最好的!
目前我所在的公司前端的职能还仅限于页面编码、交互实现和一些通用插件开发,起点真的很低。
不过,这也让我有了更多的机会去改革和实践新技术。