Skip to content

VUE 清单 - 搭建多页面项目

一、项目搭建(节选核心功能)

  1. build/index.js:配置多页面入口文件信息。
js
// ====== build/index.js
const merge = require('merge')
const { getDirPath } = require('./tools')
const { seoTitleData } = require('./config/seo')

// pages 多入口配置
const EntryPagesInfo = (configs) => {
  let entryDir = getDirPath('src/views')
  let map = {}

  entryDir.forEach((dirPath) => {
    let filename = dirPath.substring(dirPath.lastIndexOf('/') + 1)
    let conf = {
      entry: dirPath + '/index.js', // page 的入口
      publicPath: './', // 路径配置
      template: dirPath + '/index.html', // 模板来源
      title: seoTitleData[filename] || filename, // 标题
      filename: filename + '.html', // 输出文件
      chunks: ['manifest', 'vendor', filename], // 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本
      inject: true // 是否注入资源
    }

    if (configs) {
      conf = merge(conf, configs)
    }

    if (process.env.NODE_ENV === 'production') {
      conf = merge(conf, {
        minify: {
          removeComments: true, // 删除 html 中的注释代码
          collapseWhitespace: false // 删除 html 中的空白符
          // removeAttributeQuotes: true    // 删除 html 元素中属性的引号
        },
        chunksSortMode: 'manual' // 按 manual 的顺序引入
      })
    }
    map[filename] = conf
  })

  return map
}

module.exports = {
  EntryPagesInfo
}
  1. build/tools/index.js: 辅助工具类,主要作用是遍历「src/views」目录下的页面数据信息。
js
// 工具类封装
const path = require('path')
// node的glob模块允许你使用 *等符号, 来写一个glob规则, 像在shell里一样,获取匹配对应规则的文件.
const glob = require('glob')
const BUILD_KEY = require('./buildKey')

// 指向「根目录」
const BASE_DIR = '../../'
/**
 * getDirPath
 * params: dir表示要查找的具体路径, rule 表示一个glob规则
 */
const getDirPath = function (dir) {
  const PAGE_PATH = path.resolve(__dirname, BASE_DIR + dir)
  const rule = BUILD_KEY !== null ? `/${BUILD_KEY}` : '/*'
  // ===== 注意:如果路径是动态的,则必须替换分隔符
  let files = glob.sync(PAGE_PATH + rule).map((i) => i.replace(/\\/g, '/'))
  return files
}

module.exports = {
  getDirPath
}
  1. build/tools/buildKey.js: 打包配置的辅助工具, 「yarn build:test b=about」中 key 就是「about」,它表示打包的明确目标是:测试环境 & about 页面。
js
// 自定义打包参数 b=[项目名]:比如 yarn build:dev b=about 就是“打包【about】页面的【dev】环境”
const buildKey = process.argv.filter((item) => item.indexOf('b=') !== -1)
// 打包【特定】页面的 KEY
let BUILD_KEY = null
if (buildKey && buildKey.length > 0) {
  BUILD_KEY = buildKey[0].split('=')[1]
}
console.log(
  '🚀 ~ file: vue.config.js ~ line 14 ~ BUILD_KEY',
  BUILD_KEY,
  process.env.NODE_ENV,
  process.env.VUE_APP_BASE_URL
)

module.exports = BUILD_KEY
  1. build/config/seo.js: 用来配置 SEO 标题相关的信息。
js
/**
 * 用来定义多页面的SEO配置信息
 */

const seoTitleData = {
  index: '我是首页',
  about: '关于我们',
  user: '用户中心'
}

module.exports = {
  seoTitleData
}
  1. vue.config.js 配置(节选)
js
const path = require('path')
const { defineConfig } = require('@vue/cli-service')
const { EntryPagesInfo } = require('./build')
const BUILD_KEY = require('./build/tools/buildKey')
function resolve(dir) {
  return path.join(__dirname, dir)
}

module.exports = defineConfig({
  transpileDependencies: true,
  // 多页面配置入口
  pages: EntryPagesInfo(),
  assetsDir: 'static',
  // 这行代码很重要: 用来指定打包最终的生成目录
  outputDir:
    BUILD_KEY !== null
      ? `dist_${process.env.NODE_ENV}_${BUILD_KEY}`
      : `dist_${process.env.NODE_ENV}`,
  // 设置别名
  chainWebpack: (config) => {
    config.resolve.alias
      .set('@', resolve('src'))
      .set('@v', resolve('src/views'))
      .set('@c', resolve('src/components'))
      .set('@u', resolve('src/utils'))
      .set('@s', resolve('src/service')) /* 别名配置 */
    config.optimization.runtimeChunk('single')
  }
  // ... 省略
})
  1. package.json 配置
js
"scripts": {
    "serve": "cross-env NODE_ENV=local vue-cli-service serve --mode local",
    "build": " cross-env NODE_ENV=production vue-cli-service build --mode production",
    "build:dev": " cross-env NODE_ENV=development vue-cli-service build --mode development",
    "build:test": " cross-env NODE_ENV=test vue-cli-service build -- mode test",
    "build:prod": " yarn build",
    "build:all": "yarn build && yarn build:dev && yarn build:test",
    "lint": "vue-cli-service lint"
},

二、使用文档手册

A、本项目的搭建背景:

  • 基于 vue 技术栈开发的 H5 单页面,在需求不断累加的情况下,会出现疲于【搭建框架 - 下载依赖 - copy重复逻辑 - 修改页面】等工作;
  • 所以:【多页面打包配置】的出现,就是将【搭建框架 - 下载依赖 - copy重复逻辑】进行统一封装,能有效提升工作效率,并对 H5 有良好的归纳汇总效果。

B、项目介绍:

  • 技术栈: vue3 + axios + element-plus + TS + sass
  • 项目引入 flexible + rem ,能自适应主流设备浏览器(UI 稿以 750px 为基准)。
  • 项目自带三个 demo 页面:index / user / about
    • 本地运行项目后可以通过以下方式查看效果:
    • http://localhost:8080/index
    • http://localhost:8080/user
    • http://localhost:8080/about

C、新建 H5 页面的流程:

  1. 在【views】目录下新建目录 h5-abc, h5-abc 可以随便自定义
  2. h5-abc 目录下,新建三个文件:
    • h5-abc.js:名称需要和 h5-abc 目录名一致;
    • index.html: 可以直接 copy 项目自带 demo 页面,也可自定义
    • App.vue:可以直接 copy 项目自带 demo 页面,也可自定义
  3. 重启项目: yarn serve
    • 通过 http://localhost:8080/h5-abc 即可访问
  4. 部署项目:
    • 页面资源(js / css / images)带有【哈希】标识,打包时仅会改动特定资源
    • 打包完成后生成【dist】目录,如果需要部署【h5-abc】,只需要部署【dist/h5-abc】【dist/static】两个目录即可。

D、【多环境配置】: 本地环境 / 开发环境 / 测试环境 / 生产环境 ......

  • 本地环境(可开 proxy 代理): .env
  • 开发环境: .env.development
  • 测试环境: .env.test
  • 生产环境: .env.production

E、【按需构建打包】功能:

  • 打【开发环境包】:yarn build:dev
  • 打【测试环境包】:yarn build:test
  • 打【正式环境包】:yarn build
  • 打【所有环境包】:yarn build:all
  • 打【特定环境特定包】:yarn build:[环境后缀] b=[项目名]
    • 【环境后缀】:dev / test / prod。【注意:特定包时暂不支持 all】
    • 【项目名】: views 目录下的【单个页面目录名】,比如 index / about / user ......
    • 比如我要打包 about 这个 H5 的测试版本,则运行命令: yarn build:test b=about 即可。

F、还需完善的部分(Todo):

  • 【自动化部署】
  • 【个性化配置】

G、项目 DEMO 截图:

An image

三、项目启动

js
// 1. 安装依赖
$ yarn

// 2. 运行项目
$ yarn serve

注意

下载源码后,启动项目之前需要在本地新建「.env.local」文件,可以直接复制其他 .env 文件并修改后缀名即可。

四、项目源码

DEMO 源码参考:
「VUE 多页面配置」

参考:
Vue CLI 配置