我的回答
entry中增加多个html入口, 在html-webpack-plugin中设置对应的多个html模板和配置
参考回答
Vue-cli 多页面配置
单页应用(SPA)往往只含有一个主入口文件与index.html,页面间切换通过局部刷新资源来完成。而在多页应用中,我们会为每个html文档文件都指定好一个JS入口,这样一来当页面跳转时用户会获得一个新的html文档,整个页面会重新加载。
vue-cli可以配置vue.config.js的pages选项,实现多页面应用开发
module.exports = {pages: {index: {// page 的入口(必选项,除此之外就是可选项)entry: "src/index/main.js",// 模板来源template: "public/index.html",// 在 dist/index.html 的输出filename: "index.html",// 当使用 title 选项时,// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>title: "Index Page",// 在这个页面中包含的块,默认情况下会包含// 提取出来的通用 chunk 和 vendor chunk。chunks: ["chunk-vendors", "chunk-common", "index"],},// 当使用只有入口的字符串格式时,// 模板会被推导为 `public/subpage.html`// 并且如果找不到的话,就回退到 `public/index.html`。// 输出文件名会被推导为 `subpage.html`。subpage: "src/subpage/main.js",},};
1.1 初始化项目
通过vue-cli脚手架初始化一个默认工程,修改项目目录
├── assets│ └── logo.png├── components│ ├── About.vue│ ├── HelloWorld.vue│ └── Home.vue├── pages│ ├── page1│ │ ├── page1.html│ │ ├── page1.js│ │ └── page1.vue│ └── page2│ ├── page2.html│ ├── page2.js│ └── page2.vue└── style├── common.css└── common.less
vue.config.js是一个可选文件,用户需要自行创建,他会被@vue/cli-service读取。当正确添加配置后,重启一下项目,测试一下项目在改变目录结构后是否正常运行。
1.2 vue.config.js配置
let path = require("path");let glob = require("glob");//配置pages多页面获取当前文件夹下的html和jsfunction getEntry(globPath) {let entries = {},basename,tmp,pathname,appname;glob.sync(globPath).forEach(function (entry) {basename = path.basename(entry, path.extname(entry));// console.log(entry)tmp = entry.split("/").splice(-3);console.log(tmp);pathname = basename; // 正确输出js和html的路径// console.log(pathname)entries[pathname] = {entry: "src/" + tmp[0] + "/" + tmp[1] + "/" + tmp[1] + ".js",template: "src/" + tmp[0] + "/" + tmp[1] + "/" + tmp[2],title: tmp[2],filename: tmp[2],};});return entries;}let pages = getEntry("./src/pages/**?/*.html");console.log(pages);//配置endmodule.exports = {pages,};
1.3 dist打包目录
├── css│ ├── page1.9951d5a1.css│ └── page2.009d0d6f.css├── img│ └── logo.82b9c7a5.png├── js│ ├── chunk-vendors.f061f10e.js│ ├── page1.5a5322e0.js│ └── page2.db57562b.js├── page1.html└── page2.html
1.4 源码部分
@vue/cli-service通过判断是否传入pages参数来生成对应 webpack 配置文件
如果配置了pages选项,则会执行下面步骤: 
- 清除原有entry 对pages字段的每个key做循环
 - 解析每个入口对象的参数entry(必选)、title、template、filename、chunks
 通过entry字段生成 webpack 的entry入口
const multiPageConfig = options.pagesif (!multiPageConfig) {// default, single page setup.htmlOptions.template = fs.existsSync(htmlPath)? htmlPath: defaultHtmlPathwebpackConfig.plugin('html').use(HTMLPlugin, [htmlOptions])if (!isLegacyBundle) {// inject preload/prefetch to HTML...}}else{// multi-page setupwebpackConfig.entryPoints.clear()const pages = Object.keys(multiPageConfig)const normalizePageConfig = c => typeof c === 'string' ? { entry: c } : cpages.forEach(name => {const pageConfig = normalizePageConfig(multiPageConfig[name])const {entry,template = `public/${name}.html`,filename = `${name}.html`,chunks = ['chunk-vendors', 'chunk-common', name]} = pageConfigconst customHtmlOptions = {}for (const key in pageConfig) {if (!['entry', 'template', 'filename', 'chunks'].includes(key)) {customHtmlOptions[key] = pageConfig[key]}}// inject entryconst entries = Array.isArray(entry) ? entry : [entry]webpackConfig.entry(name).merge(entries.map(e => api.resolve(e)))// resolve page index templateconst hasDedicatedTemplate = fs.existsSync(api.resolve(template))const templatePath = hasDedicatedTemplate? template: fs.existsSync(htmlPath)? htmlPath: defaultHtmlPathpublicCopyIgnore.push(api.resolve(templatePath).replace(/\\/g, '/'))// inject html plugin for the pageconst pageHtmlOptions = Object.assign({},htmlOptions,{chunks,template: templatePath,filename: ensureRelative(outputDir, filename)},customHtmlOptions)webpackConfig.plugin(`html-${name}`).use(HTMLPlugin, [pageHtmlOptions])})}
