详解使用webpack构建多页面应用


Posted in Javascript onDecember 21, 2017

关于webpack的配置和使用,网上已经有许多文章了,大多是在讲单页应用,当我们需要打包多个html时,事情就变得麻烦起来。怎么在webpack-dev-server里使用路由?怎么打包多个html和js chunk并自动更新md5?本文讲的就是如何解决这些问题。

这里假设你对Webpack已经有最基础的了解

需求

来看下我们的需求:

  1. 使用webpack-dev-server做开发时的服务器
  2. 在webpack-dev-server里使用路由,访问/a时候显示a.html,/b显示b.html
  3. 打包成多个html,给其中引用到资源加md5戳

主要目录结构

├── src            
│  └── views         # 每一个文件夹对应一个页面
│    └── a         
│      └── index.js
│    └── b         
│      └── index.js
├── output          # 打包输出的目录
|  └── ...
└── template.html       # 将根据这个模版,生成各个页面的html
└── webpack.config.js
└── dev-server.js       # webpack-dev-server + express

只列出了主要的目录,这里我们根据一个template.html来生成多个页面的html,他们之间只有引用的资源路径不同。当然,你也可以每个页面单独使用一个html模版。

Webpack 配置

这里主要解决两个小问题。

1. 打包多个页面的js文件

读取src/views下的目录,约定每一个目录当成一个页面,打包成一个js chunk。

2. 打包多个html

循环生成多个HtmlWebpackPlugin插件,把每一个插件的chunks各自指向上面打包的js chunk。

// webpack.config.js
var glob = require('glob');

var webpackConfig = {
  /* 一些webpack基础配置 */  
};

// 获取指定路径下的入口文件
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/view/**/index.js');

Object.keys(entries).forEach(function(name) {
  // 每个页面生成一个entry,如果需要HotUpdate,在这里修改entry
  webpackConfig.entry[name] = entries[name];
  
  // 每个页面生成一个html
  var plugin = new HtmlWebpackPlugin({
    // 生成出来的html文件名
    filename: name + '.html',
    // 每个html的模版,这里多个页面使用同一个模版
    template: './template.html',
    // 自动将引用插入html
    inject: true,
    // 每个html引用的js模块,也可以在这里加上vendor等公用模块
    chunks: [name]
  });
  webpackConfig.plugins.push(plugin);
})

路由配置

在多页应用下,我们希望访问的是localhost:8080/a,而不是localhost:8080/a.html。

由于webpack-dev-server只是将文件打包在内存里,所以你没法在express里直接sendfile('output/views/a.html'),因为这个文件实际上还不存在。还好webpack提供了一个outputFileStream,用来输出其内存里的文件,我们可以利用它来做路由。

注意,为了自定义路由,你可能需要引进express或koa之类的库,然后将webpack-dev-server作为中间件处理。

// dev-server.js
var express = require('express')
var webpack = require('webpack')
var webpackConfig = require('./webpack.config')

var app = express();

// webpack编译器
var compiler = webpack(webpackConfig);

// webpack-dev-server中间件
var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
  stats: {
    colors: true,
    chunks: false
  }
});

app.use(devMiddleware)

// 路由
app.get('/:viewname?', function(req, res, next) {
  
  var viewname = req.params.viewname 
    ? req.params.viewname + '.html' 
    : 'index.html';
    
  var filepath = path.join(compiler.outputPath, viewname);
  
  // 使用webpack提供的outputFileSystem
  compiler.outputFileSystem.readFile(filepath, function(err, result) {
    if (err) {
      // something error
      return next(err);
    }
    res.set('content-type', 'text/html');
    res.send(result);
    res.end();
  });
});

module.exports = app.listen(8080, function(err) {
  if (err) {
    // do something
    return;
  }
  
  console.log('Listening at http://localhost:' + port + '\n')
})

最后,在package.json里定义下启动命令:

// package.json
{
  scripts: {
    "dev": "node ./dev-server.js"  
  }
}

运行 npm run dev,然后在浏览器访问localhost:8080/各个页面,你应该可以看到想要的结果。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于jQuery的一个扩展form序列化到json对象
Dec 09 Javascript
实现网页页面跳转的几种方法(meta标签、js实现、php实现)
May 20 Javascript
js设置控件的隐藏与显示的两种方法
Aug 21 Javascript
javascript中对变量类型的判断方法
Aug 09 Javascript
JavaScript实现点击按钮直接打印
Jan 06 Javascript
javascript如何实现360度全景照片问题汇总
Apr 04 Javascript
ES6新特征数字、数组、字符串
Oct 01 Javascript
js仿微信公众平台打标签功能
Apr 08 Javascript
从setTimeout看js函数执行过程
Dec 19 Javascript
详解Vue一个案例引发「内容分发slot」的最全总结
Dec 02 Javascript
vue移动端屏幕适配详解
Apr 30 Javascript
微信小程序搜索框样式并实现跳转到搜索页面(小程序搜索功能)
Mar 10 Javascript
使用ajax的post同步执行(实现方法)
Dec 21 #Javascript
jQuery Validate插件ajax方式验证输入值的实例
Dec 21 #jQuery
原生js+cookie实现购物车功能的方法分析
Dec 21 #Javascript
JS实现去除数组中重复json的方法示例
Dec 21 #Javascript
解析vue中的$mount
Dec 21 #Javascript
vue中使用refs定位dom出现undefined的解决方法
Dec 21 #Javascript
js中bool值的转换及“&&”、“||”、 “!!”详解
Dec 21 #Javascript
You might like
PHP中=赋值操作符对不同数据类型的不同行为
2011/01/02 PHP
功能强大的PHP POST提交数据类
2016/07/15 PHP
ThinkPHP 3.2.3实现页面静态化功能的方法详解
2017/08/03 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
php实现二叉树中和为某一值的路径方法
2018/10/14 PHP
js 时间函数应用加、减、比较、格式转换的示例代码
2013/08/23 Javascript
jquery仿百度经验滑动切换浏览效果
2015/04/14 Javascript
基于Jquery代码实现支持PC端手机端幻灯片代码
2015/11/17 Javascript
jQuery+jsp实现省市县三级联动效果(附源码)
2015/12/03 Javascript
jQuery页面元素动态添加后绑定事件丢失方法,非 live
2016/06/16 Javascript
JS获取input file绝对路径的方法(推荐)
2016/08/02 Javascript
JavaScript 监控微信浏览器且自带返回按钮时间
2016/11/27 Javascript
canvas的神奇用法
2017/02/03 Javascript
详解npm 配置项registry修改为淘宝镜像
2018/09/07 Javascript
JointJS JavaScript流程图绘制框架解析
2019/08/15 Javascript
vue设置动态请求地址的例子
2019/11/01 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
2019/12/02 Javascript
如何使用JavaScript检测空闲的浏览器选项卡
2020/05/28 Javascript
5个你不知道的JavaScript字符串处理库(小结)
2020/06/01 Javascript
openlayers实现图标拖动获取坐标
2020/09/25 Javascript
[03:16]DOTA2完美大师赛小组赛精彩集锦
2017/11/22 DOTA
使用Python3制作TCP端口扫描器
2017/04/17 Python
python获取依赖包和安装依赖包教程
2020/02/13 Python
Python图像处理库PIL的ImageFilter模块使用介绍
2020/02/26 Python
HTML5 Web 存储详解
2016/09/16 HTML / CSS
社会实践自我鉴定
2013/11/07 职场文书
大学军训感言300字
2014/03/09 职场文书
个人承诺书格式
2014/06/03 职场文书
2014年小学教师工作总结
2014/11/10 职场文书
私用公车造成事故检讨书
2014/11/16 职场文书
2014年社区综治工作总结
2014/11/17 职场文书
2014财产信托协议书范本
2014/11/18 职场文书
2016领导干部廉洁自律心得体会
2016/01/13 职场文书
2019最新公司租房合同(例文)
2019/07/18 职场文书
vue使用echarts实现折线图
2022/03/21 Vue.js
Android移动应用开发指南之六种布局详解
2022/09/23 Java/Android