webpack一般是配合单页面应用使用,但并不是所有的web应用都是单页的,有多个页面的情况还是很多的,当然你可以用其它的构建工具来打包,但对于习惯了webpack的你来说,要是能直接在webpack上做少许配置就可以支持多页面的打包构建,岂不乐哉!
准备工作
- webpack已安装
- webpack-dev-server已配置
- js、css、图片、字体等的loader都已配置完毕
多页HTML处理
既然是多页面,也就是说有多个HTML页面需要处理,而且得根据对应的HTML页面,打包对应页面的业务逻辑代码。比如我们最后想要的打包目录结构是这样的:
我们有三个页面,login.html、index.html、crop.html,我们分别打包出对应的css文件login.css、index.css、crop.css,且js也是如此的打包,可以看一下最后输出的index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>index-page</title>
<link href="/css/index.css" rel="stylesheet">
</head>
<body>
<header><nav></nav></header>
<div class="container-fluid index-page">
<div class="ocr-wrapper">
<div class="jumbotron">
<h1>Hello World!</h1>
<p>这是一个多页面的webpack配置demo</p>
</div>
</div>
</div>
<footer class="footer"></footer>
<script type="text/javascript" src="/js/vendors.min.js"></script><script type="text/javascript" src="/js/index.min.js"></script>
</body>
</html>
index.html自动插入对应的index.css、index.min.js和公共库代码vendors.min.js。
为了实现这个目的,我们把我们的src目录作如下组织:
template文件夹中放置html的模板页面,这里配合html-withimg-loader还可以实现模板的拆分:
<!DOCTYPE html>
<html>
<head>
#include("./layout/meta.html")
<title>crop-page</title>
</head>
<body>
#include("./layout/header.html")
<div class="container-fluid">
<div class="ocr-wrapper">
<div class="jumbotron">
<img src="../imgs/picture.jpg" alt="Picture" draggable="false">
</div>
</div>
</div>
#include("./layout/footer.html")
</body>
</html>
view文件夹则放置每个页面的入口文件,在入口文件里加载一些必要的资源:
import $ from 'jquery';
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import '../css/index.css';
$(function () {
console.log('index page');
});
根据我们的目录结构,我们需要一个方法来得到entry和文件的对应关系,我们引入模块blob
,实现如下方法:
// 获取指定路径下的入口文件
function getEntries(globPath) {
var files = glob.sync(globPath),
entries = {};
files.forEach(function(filepath) {
// 取倒数第二层(view下面的文件夹)做包名
if(filepath.match(/\.js$/)){
var split = filepath.split('/');
var fileName = split[split.length - 1];
var name = fileName.substring(0, fileName.length - 3);
entries[name] = './' + filepath;
}
});
return entries;
}
然后dev模式下,我们需要在entry里设置dev-server和hot-reload,所以我们配置里的entry应该是一个数组,同时,我们还得为每一个html页面都插入对应的资源:
var entries = getEntries('src/view/**');
webpackConfig.entry.push('webpack-dev-server/client?http://0.0.0.0:8090');
webpackConfig.entry.push('webpack/hot/only-dev-server');
Object.keys(entries).forEach(function(name) {
// 每个页面生成一个entry,如果需要HotUpdate,在这里修改entry
webpackConfig.entry.push(entries[name]);
// 每个页面生成一个html
var plugin = new HtmlWebpackPlugin({
// 生成出来的html文件名
filename: name + '.html',
// 每个html的模版,这里多个页面使用同一个模版
template: './src/template/'+ name +'.html',
// 自动将引用插入html
inject: true
});
webpackConfig.plugins.push(plugin);
});
prod模式下,我们的entry应该是一个对象,并为每个入口添加注入对应的资源,由此我们得作如下配置:
var entries = getEntries('src/view/**');
Object.keys(entries).forEach(function(name) {
webpackConfig.entry[name] = entries[name];
// 每个页面生成一个html
var plugin = new HtmlWebpackPlugin({
// 生成出来的html文件名
filename: name + '.html',
// 每个html的模版,这里多个页面使用同一个模版
template: './src/template/'+ name +'.html',
// 自动将引用插入html
inject: true,
// 每个html引用的js模块,也可以在这里加上vendor等公用模块
chunks: ['vendors', name]
});
webpackConfig.plugins.push(plugin);
});
webpackConfig.entry['vendors'] = ['jquery', 'bootstrap'];
这样,我们的多页面配置就搞定了,只需在单页的基础上,对entry做一些处理即可,改动并不算太多吧!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。