如何使用webpack构建一个简单的多页应用

一直以来我们都已经习惯了mvvm的框架+webpack+es6的项目构建,假如某个环境下的需求,我们使用不了这些框架,又如何保留对于webpack和es6的使用习惯呢?

如同大多数使用mvvm框架那样构建:分好项目结构,抽取公共组件,多页面布局,调整webpack配置文件和相应的业务文件。

项目结构划分

如:

1
2
3
4
5
6
7
8
src 
assets // 静态资源,如:图片、字体、第三方js或者css
components // 公共组件
pages // 业务逻辑
...
package.json // 依赖
webpack.config.js // webpack配置
...
公共组件抽取

需要抽取什么公共组件呢?
无非就是使用频率较多的,如:

  • header:页面头部
  • side:菜单
  • layout:页面布局
  • footer:页脚
布局渲染

1、布局是所有页面的汇聚点,我们以ejs模板举例,在该例子中布局文件为layout.ejs。
如:

1
2
3
4
5
6
<body>
<%= header %>
<%= side %>
<%= content %>
<%= footer%>
</body>

2、渲染是模板拼成一个完成的静态页面,在该例子中为render.js。
如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import header from './header.ejs';
import nav from './nav.ejs';
import layout from './layout.ejs';

export default {
render: ({title, keyword, description, content, menus, footer}) => {
const renderData = {
title,
keyword,
description,
menus,
header: header(),
nav: menus ? nav({menus}) : null,
footer: footer ? footer() : null,
content,
};
return layout(renderData);
}
}
webpack配置

webpack跟单页应用没有太多的差异,主要的差异:

  • 入口配置文件
  • 生成页面配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
'use strict';

var path = require('path');
var webpack = require('webpack');
var autoprefixer = require('autoprefixer');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var glob = require('glob');

function getEntries(globPath) {
var files = glob.sync(globPath),
entries = {};

files.forEach(function (filepath) {
// 取倒数第二层(view下面的文件夹)做包名
var split = filepath.split('/');
var name = split[split.length - 2];

entries[name] = './' + filepath;
});

return entries;
}

var entries = getEntries('src/pages/**/page.js');

module.exports = function makeWebpackConfig() {

var config = {};

config.entry = {}

config.output = {
...
}

config.devtool = ...;

config.module = {
rules: [
...
]
};

config.resolve = {
...
};


/**
* Plugins 配置
*/
config.plugins = [

...

];

Object.keys(entries).forEach(function (name) {
config.entry[name] = entries[name];
var tpl = entries[name].replace('page.js', 'index.js');
// 每个页面生成一个html
var plugin = new HtmlWebpackPlugin({
filename: name + '.html',
template: tpl,
inject: 'body',
chunks: [name],
});

config.plugins.push(plugin);
})


/**
* devServer 配置
*/
config.devServer = {
...
};

/**
*
* 打包例外的第三方库
*/
config.externals = {
...
};


return config;

}()
交互