基于vue-cli的多页配置

  最近因为公司中台项目前端技术栈准备整体迁移到vue上,又开始对vue-cli进行了一次相对深入的研究,为项目搭建一个简单的前端开发框架,虽然目前需求的单页应用,不过还是对基于vue-cli的多页应用的配置进行了了解,这篇文章就是进行相关的总结:

vue-cli的变化

  在公司直接安装vue-cli并初始化vue项目的时候,就发现文档目录还是有些许变化的,尤其是build文件夹里少了两个文件,由下面两个图可见:
旧版的build文件夹
旧版的build文件夹
新版的build文件夹(vue-cli@2.9.2)
新版的build文件夹
  我们知道dev-client.js和dev-server.js文件是之前webpack本地服务热重载hot-reloading,后来想到应该是版本升级之后webpack升级之后使用 webpack-dev-server 进行本地服务的构建了。
  打开package.json文件来看:
旧版 package.json:
旧版 package.json
新版(vue-cli@2.9.2) package.json
新版(vue-cli@2.9.2) package.json
  一看便知,新版 npm run dev 启动的命令与旧版完全不一样了,这也就是为什么新版少了两个文件的原因,新版切换到 webpack-dev-server 来启动本地浏览器。
  同时,新版本地服务 npm start 之后浏览器并没有自动打开,显然是配置被默认关闭了,我们改如何去找呢?
  首先按照命令调用的js去看 webpack.dev.conf.js
webpack.dev.conf.js
  这个config又是哪儿来的呢?
webpack.dev.conf.js
  再去看 config 文件夹下的 index.js 文件:
config/index.js
  在这里把 autoOpenBrowser 置为 true 我们在去启动服务(命令行 npm start),这时候浏览器就会自动打开了。

基于vue-cli的多页应用配置

  因为vue-cli默认的就是单页应用的配置,这里就不在赘述。下面详细说下,搭建的多页应用的过程。

  1. 首先全局安装vue-cli

    1
    npm i vue-cli -g
  2. 创建项目模板:官方提供了六个模板 webpackpwawebpack-simplebrowserifybrowserify-simplesimple ,选择webpack模板

    1
    vue init webpack <project-name>
  3. 在安装过程中会有一些提示:

    • Vue build这个选项选择Runtime + Compiler
      Runtime + Compiler
    • 安装vue-router,ESLint、Karma+Mocha、Nightwatch根据需求选择安装
      其他安装选项
    • 安装好依赖之后,根据提示操作,即可成功启动项目
  4. 现在创建的项目模板是单页面应用,与多页面应用还有些差别,需要做一些调整:

    • 项目目录结构调整
      单页目录
      单页目录
      多页目录
      多页目录
      在开发路径src下增加modules和pages文件夹,分别存放模块和页面
      有关页面的所有文件都放到同一文件夹下就近管理:index.html(页面模板)、main.js(页面入口文件)、App.vue(页面使用的组件,公用组件放到components文件夹下)都移到index文件夹下,并把main.js改为index.js,保证页面的入口js文件和模板文件的名称一致,同时,新建test文件夹(test页面)(多页应用不需要安装vue-router
    • 在build/utils.js中添加entrieshtmlPlugin两个方法:webpack多入口文件和多页面输出

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      'use strict'
      const path = require('path')
      const glob = require('glob')
      const HtmlWebpackPlugin = require('html-webpack-plugin')
      const PAGE_PATH = path.resolve(__dirname, '../src/pages')
      const merge = require('webpack-merge')

      const config = require('../config')
      const ExtractTextPlugin = require('extract-text-webpack-plugin')
      const packageConfig = require('../package.json')

      // 多入口配置
      exports.entries = function () {
      var entryFiles = glob.sync(PAGE_PATH + '/*/*.js')
      var map = {}
      entryFiles.forEach((filePath) => {
      var filename = filePath.substring(filePath.lastIndexOf('/') + 1, filePath.lastIndexOf('.'))
      map[filename] = filePath
      })
      return map
      }

      // 多页面输出配置
      exports.htmlPlugin = function () {
      let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
      let arr = []
      entryHtml.forEach((filePath) => {
      let filename = filePath.substring(filePath.lastIndexOf('/') + 1, filePath.lastIndexOf('.'))
      let conf = {
      template: filePath,
      filename: filename + '.html',
      chunks: [ filename ],
      inject: true
      }
      if (process.env.NODE_ENV === 'production') {
      conf = merge(conf, {
      chunks: [ 'manifest', 'vendor', filename ], //插件对页面入口文件(即js文件)的限定,如果不设置则会把整个项目下的所有入口文件全部引入
      // vendor模块是指提取涉及node_modules中的公共模块
      // manifest模块是对vendor模块做的缓存
      minify: {
      removeComments: true,
      collapseWhitespace: true,
      removeAttributeQuotes: true
      },
      chunksSortMode: 'dependency' // 插件会按照模块的依赖关系依次加载,即:manifest,vendor,本页面入口,其他页面入口
      })
      }
      arr.push(new HtmlWebpackPlugin(conf))
      })
      return arr
      }
      ......
    • 修改build/webpack.base.conf.js的入口配置

      1
      2
      3
      4
      5
      6
      7
      module.exports = {
      context: path.resolve(__dirname, '../'),
      // entry: {
      // app: './src/main.js'
      // },
      entry: utils.entries(),
      ......
    • 修改build/webpack.dev.conf.js和build/webpack.prod.conf.js的多页面配置:把原有的页面模板配置注释或删除,并把多页面配置添加到plugins
      webpack.dev.conf.js:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      plugins: [
      new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
      }),
      new webpack.HotModuleReplacementPlugin(),
      new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
      new webpack.NoEmitOnErrorsPlugin(),
      // https://github.com/ampedandwired/html-webpack-plugin
      // new HtmlWebpackPlugin({
      // filename: 'index.html',
      // template: 'index.html',
      // inject: true
      // }),
      ...utils.htmlPlugin(),

      ......
      ]

      webpack.prod.conf.js:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      plugins: [
      ......
      // generate dist index.html with correct asset hash for caching.
      // you can customize output by editing /index.html
      // see https://github.com/ampedandwired/html-webpack-plugin
      // new HtmlWebpackPlugin({
      // filename: config.build.index,
      // template: 'index.html',
      // 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'
      // }),
      ...utils.htmlPlugin(),
      ......

  至此,多页面应用已经搭建完毕,只需要在pages文件夹创建相应的页面文件即可,如输入 loaclhost:8080/test.html 即打开 test 文件夹对应的页面,以此类推。
  当然,某些业务需求对于url可能需要定制,这时候就需要用到 connect-history-api-fallback api中的 rewrites (详情请点击) 选项,如下图配置,就可以实现输入 loaclhost:8080/test 即打开 test 文件夹对应的页面,以及404页面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
// index: '/test.html', //path.join(config.dev.assetsPublicPath, '/test.html')
// rewrites: [ { from: /.*/, to: path.join(config.dev.assetsPublicPath, '/index.html') } ]
// 路由配置,前后端统一
// 默认 '/' 对应 index.html
rewrites: [
{
from: /^\/test$/,
to: '/test.html'
},
{
from: /.*/,
to: '/404.html'
}
]
},
......