构建一个简单的模板布局系统
上文我们说到,利用模板引擎&模板文件,我们可以控制HTML的内容,但这种控制总体来说还是比较有限的,而且很大程度受限于你对该模板引擎的熟悉程度,那么,有没有更简单的方法呢?
有!我们可以就用我们最熟悉的js来肆意组装、拼接出我们想要的HTML!
首先来看一个上文提到的例子:
这个例子是给html-webpack-plugin
指定一个名为index.ejs
的ejs模板文件,来达到生成HTML页面文件的目的,从我们可以看出,除了默认支持的ejs外,其实还可以使用其它模板引擎(例如jade
、handlebars
、underscore
),支持的方法是在webpack配置文件中配置好相应的loader即可。
先来看看我是如何给html-webpack-plugin
指定一个js作为模板的:
这是用来生成alert/index页的HtmlWebpackPlugin配置
在原项目中是循环批量new HtmlWebpackPlugin的,此处为了更容易理解,特别针对alert/index页做了修改
*/
new HtmlWebpackPlugin({
filename: `alert/index/page.html`,
template: path.resolve(dirVars.pagesDir, `./alert/index/html.js`), // 指定为一个js文件而非普通的模板文件
chunks: ['alert/index', 'commons'], // 自动加载上index/login的入口文件以及公共chunk
xhtml: true, // 需要符合xhtml的标准
});
下面来介绍这个作为模板接口的js文件:
从代码里我们可以看出,模板接口的作用实际上就是整理好当前页面独有的内容,然后交与layout作进一步的渲染;另一方面,模板接口直接把layout最终返回的结果(完整的HTML文档)给export出来,供html-webpack-plugin
生成HTML文件使用。
<!-- 选自webpack-seed/pages/alert/index/content.ejs -->
<div id="page-wrapper">
<div class="container-fluid" >
<!-- ...... -->
</div>
接着我们来看看整套模板布局系统的核心——layout。layout的主要功能就是接收各个页面独有的参数(比如说页面名称),并将这些参数传入各个公共组件生成各组件的HTML,然后根据layout本身的模板文件将各组件的HTML以及页面实际内容的HTML拼接在一起,最终形成一个完整的HTML页面文档。
<!-- 选自webpack-seed/src/public-resource/layout/layout/html.ejs -->
<%= header %>
<div id="wrapper">
<%= topNav %>
<%= sideMenu %>
<%= content %>
</div>
<%= footer %>
整个页面的公共部分,被我以区域的形式切分成一个一个的组件,下面以页头组件作为例子进行解释:
页头组件控制的范围基本上就是整个<head>
以及<body>
的头部。
不要小看这<body>
的头部,由于webpack在使用extract-text-webpack-plugin
生成CSS文件并自动加载时,会把<link>
放在<head>
的最后,而众所周知,实现IE8下Media Queries特性的respond.js
是需要放在css后面来加载的,因此,我们就只能把respond.js
放到<body>
的头部来加载了。
由于我的脚手架项目还是比较简单的,所以这些公共组件的HTML都是直接根据模板文件来输出的;如果组件本身要处理的逻辑比较多,可以使用跟模板接口一样的思路,利用js文件来拼接。
至于组件本身行为的逻辑(js),可以一并放到各组件的目录里,在公共chunk里调用便是了。本文实际上只关注于如何生成HTML,这里提到这个只是提示一下组件的文件目录结构。
有了这套模板布局系统,我们就可以轻松地生成具有相同布局的多个静态页面了,如何管理页面布局公共部分这一多页应用的痛点也就顺利解决了。