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

作者:望舒时间:2026-10-22 11:07:27浏览:302

本文详细讲解如何利用Webpack构建多页面应用(MPA)。内容涵盖通过glob动态生成入口、配置HtmlWebpackPlugin打包多个HTML并添加MD5戳,以及在webpack-dev-server中结合Express实现无后缀的路由访问,解决多页面开发中的常见痛点。

多页面应用构建需求与背景

网络上关于Webpack配置与使用的教程众多,但多数聚焦于单页应用(SPA)。当项目需要打包多个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核心配置

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/下的各个页面路径,即可看到预期的页面效果。

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

作者最新文章