vue单页面改造多页面应用的全过程记录

前言

单页面和多页面的区别这里就不细说了。我司业务适合多页面,许多小应用都是通过iframe整体嵌入的形式。

  • 如果项目过于庞大,就会有很不好的体验问题。
  • 拆分多个项目的话,又会有额外的开支,如服务器资源部署等问题。

基于此改造的目标

  • 单独业务逻辑单独一个页面
  • 可实现单命令打包
  • 可单独打包

首先我们准备一个基础的项目

目录结构如下

src目录为我们平时开发的目录,dist为打包后的目录,整体结构如图

1 将当前项目改造成多页面目录

pages下为我们开发的目录文件,改造过程就是将原src下所有目录结构复制到home,index每个页面单独一份 为了提现多页面优势,这里我们选用两款ui框架,以便最后做下打包体积对比

npm i element-ui -S
npm i ant-design-vue -S

在home和index中分别引入

home页面类似,然后我们更改vue.config.js

module.exports = {
  publicPath: './',
  productionSourceMap: false,
  pages: { // vue cli3 自带多页面配置
    index: {
      entry: `src/pages/index/main.js`,
      template: `public/index.html`,
      filename: `index.html`
    },
    home: {
      entry: `src/pages/home/main.js`,
      template: `public/index.html`,
      filename: `home.html`
    }
  },
  devServer: {
    port: 8080
  },
  lintOnSave: false
}

现在我们打包,看一下生成的目录结构

File                                   Size              Gzipped

dist\js\chunk-vendors.239e820f.js      2544.36 KiB       703.20 KiB
  dist\js\index.1716ccad.js              11.33 KiB         4.13 KiB
  dist\js\home.e4410a07.js               7.08 KiB          2.57 KiB
  dist\js\about.ca80b2fc.js              0.76 KiB          0.29 KiB
  dist\css\chunk-vendors.68b49edf.css    666.01 KiB        89.04 KiB
  dist\css\index.5dfa7415.css            0.45 KiB          0.28 KiB
  dist\css\home.d995708f.css             0.44 KiB          0.27 KiB

Images and other types of assets omitted.
  Build at: 2022-05-01T12:26:06.551Z - Hash: 693bf5bdcf72896b - Time: 16240ms

DONE  Build complete. The dist directory is ready to be deployed.
 INFO  Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html

可以看到打包出来的是混在一起的。我们下一步就是将他们拆分开,并且可配置命令单独打包 思路是循环pages下文件夹 我们找出pages下目录中带有main.js的所有文件夹名。当然我们也可以手动写死,每次增加页面的时候,我们单独维护这个数组

const pages = ['home', 'index'] // 在增加页面的时候,手动维护这个数组

当然我们也有方法可以帮我们维护这个数组,可以在我们更新的时候省事一些

// 获取pages下文件夹
const path = require('path')
const glob = require('glob')
// 找到pages所在文件夹 hello-world\src\pages
const PATH_ENTRY = path.resolve(__dirname, '../src/pages')
// 匹配到pages路径下 main.js 的文件
// [
//   'D:/测试项目/hello-world/src/pages/home/main.js',
//   'D:/测试项目/hello-world/src/pages/index/main.js'
// ]
const entryFilePaths = glob.sync(PATH_ENTRY + '/**/main.js')

const buildEntries = []
entryFilePaths.forEach((filePath) => {
  // 找到对应的文件名,index  home
  const FILENAME = filePath.match(/([^/]+)\/main\.js$/)[1]
  buildEntries.push(FILENAME)
})
module.exports = {
  buildEntries
}

buildEntries 既为我们拿到的数组

现在我们继续改造vue.config.js, 我们先通过更改package.json中的命令传参的形式,根据我们传递的参数,单独打包对应的page

"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "build:index": "vue-cli-service build index --no-clean", // 注意no-clean 不能清除文件,不然可能将文件夹下打包的其他page清理掉,如果是每次部署一个page,这就无所谓了
    "build:home": "vue-cli-service build home --no-clean",
    "build:prod": "vue-cli-service build",
    "_build": "node build/build.js",
    "lint": "vue-cli-service lint"
 }

我们如何能拿到 传入的index 或者home参数呢 结果是process.argv这个参数中可以取到,具体可以自行搜索下 process.argv为一个数组,第一项为可执行文件的目录 第二项为当前执行的JavaScript文件路径 剩余的是传递的参数,就如我们传递的index 是在process.argv[3]中 现将vue.config.js改造如下

// 编译配置的多页面
const modules = {}
const isProduction = process.env.NODE_ENV === 'production'
const { buildEntries } = require('./config/getPages')

// 初始化页面参数
function initPageParams(page) {
  modules[ page ] = {
    entry: `src/pages/${page}/main.js`, // page 的入口
    template: `public/index.html`, // 模板来源
    filename: `${page}.html`, // 在 dist/index.html 的输出
  }
}

const page = process.argv[3] || 'index'
// 如果是 开发环境,运行阶段
if (!isProduction) {
  for (const page of buildEntries) {
    initPageParams(page)
  }
} else {
  // 只有在生产打包的时候,单独打包,拆成不用的文件夹
  initPageParams(page)
}

module.exports = {
  publicPath: './',
  outputDir: 'dist',
  assetsDir: isProduction ? page : 'static',
  productionSourceMap: false,
  pages: modules,
  devServer: {
    port: 8080
  },
  lintOnSave: false
}

这时候我们npm run build:index 尝试查看打包结果,可以看到,可以将index对应的文件全部放在index文件目录下,如果我们需要打包home,直接npm run build:home

File                                      Size             Gzipped

dist\index\js\chunk-vendors.c60bfe2f.j    1837.82 KiB      527.87 KiB
  s
  dist\index\js\index.e2aa144d.js           11.28 KiB        4.12 KiB
  dist\index\js\about.2a86a3cb.js           0.43 KiB         0.28 KiB
  dist\index\css\chunk-vendors.ef376986.    456.88 KiB       55.99 KiB
  css
  dist\index\css\index.5dfa7415.css         0.45 KiB         0.28 KiB

Images and other types of assets omitted.
  Build at: 2022-05-03T03:46:54.824Z - Hash: e2d53105a245deab - Time: 12711ms

DONE  Build complete. The dist directory is ready to be deployed.
 INFO  Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html

现在我们已经实现了,单独page单独打包,但我们如果想,一个命令打包所有的page呢。这个时候我们就需要node一个方法来帮助我们实现了 我们在单独建一个js文件代码如下

const fs = require('fs');
const execSync = require('child_process').execSync;
const { buildEntries } = require('../config/getPages');

// 移除目录
function deleteDist(path) {
  let files = [];
  // 判断目录是否存在
  if (fs.existsSync(path)) {
    files = fs.readdirSync(path); // 读取目录
    // @ts-ignore
    files.forEach((file) => {
      const curPath = path + '/' + file; // 拼接目录写文件完整路径
      if (fs.statSync(curPath).isDirectory()) { // 读取文件路径状态 判断是否为文件夹 如果为文件夹,递归
        deleteDist(curPath);
      } else {
        fs.unlinkSync(curPath); // 删除文件
      }
    });
    fs.rmdirSync(path);
  }
}
try {
  const startTime = Date.now();
  process.env.NODE_ENV = 'production';  // 切换环境为生产
  // 执行打包前删除dist目录
  deleteDist('./dist');
  for (const page of buildEntries) {
    // 可以执行我们的命令,第一个参数是命令,第二个参数的意思是输出子进程中的日志
    execSync(`vue-cli-service build ${page} --no-clean`, { stdio: 'inherit' });
  }
  // 重置
  process.env.NODE_ENV = undefined;
  const time = Date.now() - startTime;
  console.log('\033[42;30m ALL DONE \033[0m Build Compiled successfully in ' + `${time / 1000}s`);
} catch (e) {
  console.log('\033[41;30m FAILED \033[0m ' + e);
}

思想就是循环执行打包命令 关键在于execSync方法来替我们执行打包命令,现在我们执行,npm run _build

至此我们的多页面打包基本完成,后续也可以做一些cdn的处理,或者chunks的拆包等优化。小伙伴们自行研究

总结

到此这篇关于vue单页面改造多页面应用的文章就介绍到这了,更多相关vue单页面改造多页面内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue-cli创建项目从单页面到多页面的方法

    对于某些项目来说,单页面不能很好的满足需求,所以需要将vue-cli创建的单页面项目改为多页面项目. 需要修改以下几个文件: 1.下载依赖glob $npm install glob --save-dev 2.修改build下的文件 (1)修改webpack.base.conf.js 添加以下代码: var glob = require('glob'): var entries = getEntry('./src/pages/**/*.js') 将module.exports中的 entry:

  • vue将单页面改造成多页面应用的方法

    问题描述: 手头有一个项目是使用 vue-cli 搭建的单页面应用.项目分为了管理平台和用户查看页面,用户查看页面是很简单的页面,但是在加载过程中,却加载了整个应用的打包代码,量重且影响了响应和体验.我想要的效果是,查看页面只加载查看页面的代码,不包含管理系统的代码,因此着手将单页面应用改造成多页面应用,这里分享下方法. 1.改造文件目录 改造前: 改造后: assets:这里不变,依然放置公用的静态资源文件:components:这里存放应用下所有的vue组件:pages:这里存放我们的多页面

  • vue单页面改造多页面应用的全过程记录

    前言 单页面和多页面的区别这里就不细说了.我司业务适合多页面,许多小应用都是通过iframe整体嵌入的形式. 如果项目过于庞大,就会有很不好的体验问题. 拆分多个项目的话,又会有额外的开支,如服务器资源部署等问题. 基于此改造的目标 单独业务逻辑单独一个页面 可实现单命令打包 可单独打包 首先我们准备一个基础的项目 目录结构如下 src目录为我们平时开发的目录,dist为打包后的目录,整体结构如图 1 将当前项目改造成多页面目录 pages下为我们开发的目录文件,改造过程就是将原src下所有目录

  • vue单页面改造多页面应用详解第1/2页

    单页面和多页面的区别这里就不细说了.我司业务适合多页面,许多小应用都是通过iframe整体嵌入的形式. 如果项目过于庞大,就会有很不好的体验问题. 拆分多个项目的话,又会有额外的开支,如服务器资源部署等问题. 基于此改造的目标 单独业务逻辑单独一个页面 可实现单命令打包 可单独打包 首先我们准备一个基础的项目,目录结构如下 src目录为我们平时开发的目录,dist为打包后的目录,整体结构如图 1 将当前项目改造成多页面目录 pages下为我们开发的目录文件,改造过程就是将原src下所有目录结构复

  • 解决vue单页使用keep-alive页面返回不刷新的问题

    使用vue单页开发项目时遇到一个很恶心的问题:在列表页点击一条数据进入详情页,按返回键返回列表页时页面刷新了,用户体验非常差啊!!!查阅了一下相关问题,使用<keep-alive>解决这个问题,下面是我的使用心得. <keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM. 首先在App.vue页面上有下面一段代码,我们都知道这是页面渲染的地方 <router-view></router-view> 把这段代码改成

  • vue单页应用在页面刷新时保留状态数据的方法

    在Vue单页应用中,如果在某一个具体路由的具体页面下点击刷新,那么刷新后,页面的状态信息可能就会丢失掉.这时候应该怎么处理呢?如果你也有这个疑惑,这篇文章或许能够帮助到你 一.问题 现在产品上有个需求:单页应用走到某个具体的页面,然后点击刷新后,刷新的页面要与刷新前的页面要保持一致. 这时候就需要我们保存刷新之前页面的状态. 二.一种解决方案 在这个Vue单页应用中,王二是用Vuex作为状态管理的,一开始王二的思路是将Vuex里的数据同步更新到localStorage里. 即:一改变vuex里的

  • 详解在不使用ssr的情况下解决Vue单页面SEO问题

    遇到的问题: 近来在写个人博客的时候遇到了大家可能都会遇到的问题 Vue单页面在SEO时显得很无力,尤其是百度不会抓取动态脚本 Vue-Router配合前后端分离无法让meta标签在蜘蛛抓取时动态填充 Vue单页面又是大势所趋,写起来也不止是一个爽,当然也可以选择多页面 但即使是多页面在面对文章和文档时候也不可能说给每篇文章生成个Vue页面 SSR当然能解决这个问题,但是仔细想想SSR不就跟以前的.php页面一样了么 都是预先拉取所有数据然后填充返回给浏览器,需要多消耗服务器资源,而且配置繁琐

  • Nginx 解决WebApi跨域二次请求以及Vue单页面的问题

    一.前言 由于项目是前后端分离,API接口与Web前端 部署在不同站点当中,因此在前文当中WebApi Ajax 跨域请求解决方法(CORS实现)使用跨域处理方式处理而不用Jsonp的方式. 但是在一段时间后,发现一个很奇怪的问题,每次前端发起请求的时候,通过浏览器的开发者工具都能看到在Network下同一个url有两条请求,第一条请求的Method为OPTIONS,第二条请求的Method才是真正的Get或者Post,并且,第一条请求无数据返回,第二条请求才返回正常的数据. 二.原因 第一个O

  • Vue单页面应用保证F5强刷不清空数据的解决方案

    问题描述: Vue单页面用按F5强刷,数据就恢复初始了,这怎么破? 解决方案: store.subscribe((mutation, state) => { sessionStorage.setItem('mobileState', JSON.stringify(state)); }) if (sessionStorage.getItem('mobileState')) { state = JSON.parse(sessionStorage.getItem('mobileState')); }

  • 解决vue单页面应用中动态修改title问题

    详细信息查看:vue-weachat-title 解决问题: 1.Vuejs 单页应用在iOS系统下部分APP的webview中 标题不能通过 document.title = xxx 的方式修改 该插件只为解决该问题而生(兼容安卓) 2.在vue单页面中,通过浏览器分享到QQ.微信等应用中的链接,只有一个首页标题和默认icon图片 已测试:APP 微信 QQ 支付宝 淘宝 安装 npm install vue-wechat-title --save 用法 1.在main.js中引入 impor

  • 解决vue单页面修改样式无法覆盖问题

    当 <style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素. vue组件编译后,会将 template 中的每个元素加入 [data-v-xxxx] 属性来确保 style scoped 仅本组件的元素而不会污染全局. 比如: <style scoped> .example { color: red; } </style> <template> <div class="example">hi<

  • vue form 表单提交后刷新页面的方法

    最近做的项目中,有增删改表格功能,在操作后需要实时更新页面数据.下面可以这样解决. 1.在methods中 定义好一个初始化渲染实例. 例如 lnitializationData(){//初始化页面数据 this.$http.get("/permit/specific", { params: { page: this.localPage, size: this.msg.pagNumber, } }, {emulateJSON: true} ).then((response) =>

随机推荐