构建一个简单的模板布局系统

    上文我们说到,利用模板引擎&模板文件,我们可以控制HTML的内容,但这种控制总体来说还是比较有限的,而且很大程度受限于你对该模板引擎的熟悉程度,那么,有没有更简单的方法呢?

    有!我们可以就用我们最熟悉的js来肆意组装、拼接出我们想要的HTML!

    首先来看一个上文提到的例子:

    这个例子是给html-webpack-plugin指定一个名为index.ejs的ejs模板文件,来达到生成HTML页面文件的目的,从我们可以看出,除了默认支持的ejs外,其实还可以使用其它模板引擎(例如jadehandlebarsunderscore),支持的方法是在webpack配置文件中配置好相应的loader即可。

    先来看看我是如何给html-webpack-plugin指定一个js作为模板的:

    1. 这是用来生成alert/index页的HtmlWebpackPlugin配置
    2. 在原项目中是循环批量new HtmlWebpackPlugin的,此处为了更容易理解,特别针对alert/index页做了修改
    3. */
    4. new HtmlWebpackPlugin({
    5. filename: `alert/index/page.html`,
    6. template: path.resolve(dirVars.pagesDir, `./alert/index/html.js`), // 指定为一个js文件而非普通的模板文件
    7. chunks: ['alert/index', 'commons'], // 自动加载上index/login的入口文件以及公共chunk
    8. xhtml: true, // 需要符合xhtml的标准
    9. });

    下面来介绍这个作为模板接口的js文件:

    从代码里我们可以看出,模板接口的作用实际上就是整理好当前页面独有的内容,然后交与layout作进一步的渲染;另一方面,模板接口直接把layout最终返回的结果(完整的HTML文档)给export出来,供html-webpack-plugin生成HTML文件使用。

    1. <!-- 选自webpack-seed/pages/alert/index/content.ejs -->
    2. <div id="page-wrapper">
    3. <div class="container-fluid" >
    4. <!-- ...... -->
    5. </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,这里提到这个只是提示一下组件的文件目录结构。

    有了这套模板布局系统,我们就可以轻松地生成具有相同布局的多个静态页面了,如何管理页面布局公共部分这一多页应用的痛点也就顺利解决了。