详解使用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 相关文章推荐
Prototype Hash对象 学习
Jul 19 Javascript
jquery实现对联广告的方法
Feb 05 Javascript
详解Webwork中Action 调用的方法
Feb 02 Javascript
D3.js实现散点图和气泡图的方法详解
Sep 21 Javascript
微信小程序 教程之数据绑定
Oct 18 Javascript
十分钟带你快速了解React16新特性
Nov 10 Javascript
vue js秒转天数小时分钟秒的实例代码
Aug 08 Javascript
解决在vue项目中webpack打包后字体不生效的问题
Sep 01 Javascript
解决axios会发送两次请求,有个OPTIONS请求的问题
Oct 25 Javascript
Vue-cli3项目引入Typescript的实现方法
Oct 18 Javascript
JavaScript onclick事件使用方法详解
May 15 Javascript
vue中控制mock在开发环境使用,在生产环境禁用方式
Apr 06 Vue.js
使用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/06/17 PHP
php使用session二维数组实例
2014/11/06 PHP
php对二维数组进行相关操作(排序、转换、去空白等)
2015/11/04 PHP
php session 写入数据库
2016/02/13 PHP
golang与php实现计算两个经纬度之间距离的方法
2016/07/22 PHP
php实现XML和数组的相互转化功能示例
2017/02/08 PHP
javascript 短路法代码精简
2009/08/20 Javascript
从js向Action传中文参数出现乱码问题的解决方法
2013/12/29 Javascript
JavaScript弹出新窗口并控制窗口移动到指定位置的方法
2015/04/06 Javascript
javascript跨域总结之window.name实现的跨域数据传输
2015/11/01 Javascript
jQuery+CSS3折叠卡片式下拉列表框实现效果
2015/11/02 Javascript
50 个 jQuery 插件可将你的网站带到另外一个高度
2016/04/26 Javascript
JavaScript实现的仿新浪微博原生态输入字数即时检查功能【兼容IE6】
2017/09/26 Javascript
vue-cli 引入jQuery,Bootstrap,popper的方法
2018/09/03 jQuery
微信小程序带动画弹窗组件使用方法详解
2018/11/27 Javascript
vue添加锚点,实现滚动页面时锚点添加相应的class操作
2020/08/10 Javascript
vue 使用原生组件上传图片的实例
2020/09/08 Javascript
python使用正则搜索字符串或文件中的浮点数代码实例
2014/07/11 Python
Python爬取Coursera课程资源的详细过程
2014/11/04 Python
win10下Python3.6安装、配置以及pip安装包教程
2017/10/01 Python
读取本地json文件,解析json(实例讲解)
2017/12/06 Python
python3模拟实现xshell远程执行liunx命令的方法
2019/07/12 Python
Python Subprocess模块原理及实例
2019/08/26 Python
Python笔记之facade模式
2019/11/20 Python
tensorflow转换ckpt为savermodel模型的实现
2020/05/25 Python
OpenCV利用python来实现图像的直方图均衡化
2020/10/21 Python
Python hashlib和hmac模块使用方法解析
2020/12/08 Python
Python脚本调试工具安装过程
2021/01/11 Python
解决pytorch 数据类型报错的问题
2021/03/03 Python
加利福尼亚州威尼斯的女性奢侈品设计师服装和概念店:Mona Moore
2018/09/13 全球购物
医师定期考核实施方案
2014/05/07 职场文书
2014年“世界无车日”活动方案
2014/09/21 职场文书
群众路线党员个人整改措施
2014/10/27 职场文书
2015年机关党建工作总结
2015/05/22 职场文书
护理心得体会范文
2016/01/22 职场文书
党风廉政建设心得体会(2016最新版)
2016/01/22 职场文书