在一个 Vue-cli 项目中支持多个页面

有时候,你想开发很多个具备单页应用性质的页面,一个一个用Vue-cli构建并且分成不同的项目未免太蠢了。

这篇文章用于记录我在给VCenter 前端配置多页面的时候的解决方法。

前言

网络上有很多类似的方法,一般都是讲讲增加Entry,增加HtmlWebpackPlugin的相关配置,每次新增或者删除页面的时候都需要做很多工作。

当然,也有一些文章,给了一些自动化解决方案,但是并不美观,也不方便,比如分页面划分文件夹之类的,然后通过webpack配置中的js自动引入这些文件夹,这种就比较倾向于是用文件夹作为约定。

在本文中,我结合了这两种方法,尝试通过一个配置文件来管理自己的多页面方案。

准备工作

首先我们需要一个Vue-cli构建的项目,具备基本的 /build目录,并且有webpack.dev.conf.js 等配置文件。

然后我们需要知道,每一个webpack项目在构建的时候,会发生什么,同时又需要设置哪些配置。

比如说我们需要在 webpack.base.conf.js中添加所有的 Entry(入口文件),每个页面都需要指定那个页面的 main.js,

然后我们还注意到 HtmlWebpackPlugin这个插件,负责将一个HTML 模板,插入指定的经过 webpack处理的js文件。

最后,我们还需要做一些简单的优化工作,控制台打印出所有页面的链接

操作流程

首先,我们的多页配置是基于一个 js 文件,这个js 文件中保存了一个数组,形如:

const path = require('path')

module.exports = [
    {
        name:"app",
        title:"管理后台",
        FileName:"BackEnd.html", //输出的文件名
        OutputFile:path.resolve(__dirname, '../dist/BackEnd.html'),  //输出位置,这个地方需要填写相对路径
        TemplateFile:"index.html", // 模板文件,不出意外的话多个页面可以共享这个文件,问题不大,这个地方的路径填写相对根目录路径,因为使用的时候,那个配置文件有另外的路径检索方式
        Entry:'./src/BackEnd/main.js', // JS入口,路径为相对根目录路径
    },
    {
        name:"CPU_Grade",
        title:"成绩查询",
        FileName:"CPU_Grade.html",
        OutputFile:path.resolve(__dirname, '../dist/CPU_Grade.html'),
        TemplateFile:"index.html",
        Entry:'./src/CPU_Grade/main.js',
    }
]

在这个文件中,我们为每个页面指定了不同的名称(name),title(网页标题),文件名称,输出位置和入口文件路径。
文件名称和输出位置需要一一对应,在这里我直接使用 path 将路径转化了,免得之后再添加类似的代码

然后我们需要对webpack.dev.conf.js进行配置,在plugins属性中,我们需要添加每个页面不同的HtmlWebpackPlugin
这一步我们通过数组map+解构直接插入进去:

    // https://github.com/ampedandwired/html-webpack-plugin
    ...MultiPage.map((Page)=>{
      return new HtmlWebpackPlugin({
        filename: Page.FileName,
        title:Page.title,
        template: Page.TemplateFile,
        inject: true,
        chunks: [Page.name]
      })
    }),
    // copy custom static assets

别忘了要先引入我们的配置文件const MultiPage = require("./MultiPage");

webpack.prod.conf.js里面,也是依样画葫芦,但是这里需要注意,将vendors,manifest和打包的js代码分别引入,因此应该使用chunks相关的代码,当然,也别忘了先引入配置文件

    //生成多页面配置
    ...MultiPage.map((Page)=>{
      return new HtmlWebpackPlugin({
        filename: Page.OutputFile,
        title:Page.title,
        template: Page.TemplateFile,
        inject: true,
        minify: {
          removeComments: true,
          collapseWhitespace: true,
          removeAttributeQuotes: true
          // more options:
          // https://github.com/kangax/html-minifier#options-quick-reference
        },
        // necessary to consistently work with multiple chunks via CommonsChunkPlugin
        chunksSortMode: 'dependency',
        chunks: ['manifest', 'vendor', Page.name]
      })
    }),

以上两处修改都是将原来的HTMLWebpackPlugin替换掉的

最后,我们需要进入webpack.base.conf.js,添加我们的入口文件

const MultiPage = require("./MultiPage");
// 获取Entry的函数
function getEntry(){
  let entry = {};
  MultiPage.forEach((Page)=>{
    entry[Page.name] = Page.Entry;
  })
  return entry;
}


//然后entry应该修改为 
entry: getEntry(),

到了这一步,如果你的配置文件没有写错,目录也没啥问题的话,应该能正常使用webpack了,但是别急,还有一点点小问题

首先需要到你的index.html中将title替换成

    <title><%= htmlWebpackPlugin.options.title%></title>

这样,插件才能正确插入各个页面的 title

另外,你还可以前往webpack.dev.conf.js,在最底部,有一个启动服务器后的提示,在这里可以将所有的文件路径都填写进去,免得手动敲文件名才能调试。代码如下

compilationSuccessInfo: {
          messages: [
            `Your application is running here: http://localhost:${port}`,
            ...MultiPage.map((Page,index)=>{
              return `Page ${index+1}: http://localhost:${port}/${Page.FileName}`
            })
          ],
        },

是的,没错了,也直接使用解构插入进去即可,你可能注意到了,我把原来的devWebpackConfig.devServer.host修改成了localhost,这是因为我的网页需要移动端访问,因此监听了 0.0.0.0 ,方便手机访问,但是电脑上显然只能使用localhost,因此直接替换了。

如果你也想改监听host的话,可以找到/config/index.js,在dev下面做这个修改

host: '0.0.0.0', // can be overwritten by process.env.HOST #这边改成 0.0.0.0来方便监听局域网访问,方便手机端调试

至此,你就可以正常使用Vue项目来构建多页面了,根据我的配置文件,两个html文件都会输出到dist下,同级并列,并且是由同一个index.html模板生成的。

下面放一个最后的效果图:
snipaste_20190105_182944.png

总结

在配置多页面的时候,找了很多的网站和资料,其实完全不需要,只需要认真看一下各个webpack配置文件,捋清楚每一个文件的作用,并且修改配置文件中的特定值为你的自动配置的函数即可。所以还是要多动脑,少照抄。

希望有朝一日有人遇到这个问题的时候这篇文章能够给他一点启发。