uniapp vuecli项目融合[小记]:将多个项目融合,打包成一个小程序/App,拆分多个H5应用

前言:

        目前两个uniapp vuecli开发的项目【A、B】,新规划的项目C:需要融合项目B 80%的功能模块,同时也需要涵盖项目A的所有功能模块。

应用需求:

        1、新项目C【小程序】可支持切换到应用A/C界面【内部通过初始化、路由跳转实现切换】【因此新项目C考虑基于项目A的工程上开发, git引入项目B

        2、工程A在H5中需要打包成两个应用:A应用、C应用;

实现思路:

        1、A项目工程上开发新应用C,引入B工程的模块/代码:通过git地址,安装依赖的方式引入B项目;

        2、A工程:小程序打包为一个应用[A+C]、H5拆分应用[A/C]:通过pages.json动态改写来实现,通过不同的打包命令来区分;

A工程改造:基于A开发C应用、融合B项目,步骤梳理:
1. 通过git地址,安装依赖的方式引入B项目:package.json
"mobileB": "git+https://git.xxxx/mobileB.git#xxxxxxxxxx"

注:git+<项目B仓库地址>#<git提交commit id>

2. 解决问题:项目B使用了TS,项目A未使用TS,引入后需要转换支持:vue.config.js
module.exports = {/*** 某个依赖项是TypeScript编写的,但是目标环境中并不支持TypeScript,* 那么我们需要在打包前先将其转换为JavaScript代码*/transpileDependencies: ['mobileB'],// ...其他配置
}
3. webpack编译构建过程中,处理mobileB模块导入路径

        引入mobileB后,因为mobileB中的别名等,无法正确被解析,所以需要在编译阶段,进行修改。

        定义一个名为CustomAliasResolverPlugin.js的文件,实现webpack插件类,在webpack编译过程中处理mobileB模块导入路径,确保mobileB中的别名路径都能正确的指向。

class CustomAliasResolverPlugin {constructor() {this.path_mobileB = 'mobileB/src';}apply(compiler) {// 监听了normalModuleFactory事件,在每个普通模块被创建时执行回调函数compiler.hooks.normalModuleFactory.tap('CustomAliasResolverPlugin',(factory) => {// 回调函数接收一个模块工厂实例factory作为参数,并在其上进一步监听 beforeResolve 事件。beforeResolve 是在模块解析之前触发的钩子,此时可以修改模块请求信息factory.hooks.beforeResolve.tapAsync('CustomAliasResolverPlugin',(data, callback) => {// 在 beforeResolve 的回调函数内,从数据对象data中获取当前模块的请求路径request和解析上下文context。const { request, context } = data;// 解析上下文包含指定的基础路径,确保是mobileB下的模块if (context.includes(this.path_mobileB)) {if (request.startsWith('@src')) {data.request = request.replace('@src', `${this.path_mobileB}/src`);} else if (request.startsWith('@service')) {data.request = request.replace('@service', `${this.path_mobileB}/service`);}}callback(null, data);});});}
}module.exports = CustomAliasResolverPlugin;

        CustomAliasResolverPlugin 是一个自定义的webpack插件,要求它在项目构建时会参与到webpack的模块解析阶段,因此我们需要在添加到plugins中,以及解决可能存在的路径问题;

        vue.config.js:

const CustomAliasResolverPlugin = require('./config/CustomAliasResolverPlugin');module.exports = {configureWebpack: {plugins: [new CustomAliasResolverPlugin()]}// ...其他配置
}
4. pages.json动态改写:实现H5应用拆分、小程序整合

        uniapp页面文件的打包是基于pages.json,所以我们需要根据需求,使用nodeJs动态生成对应的pages.json文件。

示例:

common.js:编写需要打包成A、C两个项目的公共页面路由及其他配置

// 小程序的分包
const subPackages = []
const pages = [{path: 'pages/home/home',aliasPath: '/'}
]// 其他配置相关
const otherConfig = {globalStyle: {navigationStyle: 'custom',allowsBounceVertical: 'NO',renderingMode: 'seperated',pageOrientation: 'portrait',rpxCalcMaxDeviceWidth: 540,rpxCalcBaseDeviceWidth: 375},// 需要自动注册的自定义组件easycom: {autoscan: true,custom: {'^ant-tree-(.*)':'@/components/businessComponent/ant-tree/ant-tree-$1.vue','^ant-customize-(.*)':'@/components/businessComponent/ant-customize/ant-customize-$1.vue','^u-(.*)': 'uview-ui/components/u-$1/u-$1.vue','^anmc-(.*)': 'antm-ui/components/common/anmc-$1/anmc-$1.vue','^anmb-(.*)': 'antm-ui/components/business/anmb-$1/anmb-$1.vue'}}
};module.exports = {subPackages,pages,otherConfig
};

ant4Pages.js/erpPages.js: A/C应用的页面路由

module.exports = {pages: [],subPackages: []
}

main.js: 根据条件重写pages.json


const common = require('./common')
const subPackages = common.subPackages || []
const otherConfig = common.otherConfig || {}
const commonPages = common.pages || []const fs = require('fs');
const ant4pages = require('./ant4Pages');
const erppages = require('./erpPages');
const pagesPath = process.env.UNI_INPUT_DIR + '/pages.json';
let pagesJson = {};
// 判断是否H5
if (process.env.UNI_PLATFORM === 'h5') {let subPackagesProxy = subPackages// 判断是否是ERP项目:对应文中说到的C应用【H5】// VUE_APP_NODE_APP_TYPE是命令上自行添加的字段,用来区分if (process.env.VUE_APP_NODE_APP_TYPE === 'erp') {const erpSubPackages = erppages.subPackageserpSubPackages.forEach(item => {const root = subPackagesProxy.find(sub => sub.root === item.root)if (root) {item.pages = [...root.pages,...item.pages]subPackagesProxy = subPackagesProxy.filter(sub => sub.root !== item.root)}})pagesJson = {...erppages,pages: [...commonPages, ...erppages.pages],subPackages: [...subPackagesProxy, ...erpSubPackages],...otherConfig}} else {const antSubPackages = ant4pages.subPackagesantSubPackages.forEach(item => {const root = subPackagesProxy.find(sub => sub.root === item.root)if (root) {item.pages = [...root.pages,...item.pages]subPackagesProxy = subPackagesProxy.filter(sub => sub.root !== item.root)}})pagesJson = {...ant4pages,pages: [...commonPages, ...ant4pages.pages],subPackages: [...subPackagesProxy, ...antSubPackages],...otherConfig}}
} else {// 小程序打包,整合所有的路由配置const subPackagesProxy = subPackageslet antSubPackages = ant4pages.subPackageslet erpSubPackages = erppages.subPackagessubPackagesProxy.forEach(item => {const antRoot = antSubPackages.find(sub => sub.root === item.root)const erpRoot = erpSubPackages.find(sub => sub.root === item.root)if (antRoot) {item.pages = [...antRoot.pages,...item.pages]antSubPackages = antSubPackages.filter(sub => sub.root !== item.root)}if (erpRoot) {item.pages = [...erpRoot.pages,...item.pages]erpSubPackages = erpSubPackages.filter(sub => sub.root !== item.root)}})pagesJson = {pages: [...commonPages, ...ant4pages.pages, ...erppages.pages],subPackages: [...subPackagesProxy, ...antSubPackages, ...erpSubPackages],...otherConfig};
}// 将最终的结果写入pages.json,在项目运行或构建时
fs.writeFileSync(pagesPath, JSON.stringify(pagesJson), {flag: 'w'
});

将src/config/appPages/main.js文件引入vue.config.js中;

        注:直接在vue.congfig.js顶部导入对于pages.json的重写,vue.config.js 文件是 Vue CLI 在构建项目时默认查找并加载的第一个用户自定义配置文件,目前测试没有出现什么异常,如果存在异常,可考虑调整至预处理脚本中,具体根据实际情况而定:

{"scripts": {"prebuild": "node ./src/config/main.js","build": "vue-cli-service build"},
}
5. router拦截处理【参考】

6. vuex整合: mobileB中vuex中的modules,添加到当前主工程的modules中:
import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
import getters from './getters';
import user from './modules/user.js';
// 项目B的store集合,全部抛出来,添加到modules中
import Bstore from 'mobileB/src/store/mainVue.use(Vuex);
export default new Vuex.Store({plugins: [createPersistedState({storage: {// ...},reducer(value) { // 选择性配置持久化return {}}})],modules: {user,...Bstore},getters
});
7. 初始化B项目依赖的一些数据缓存等;

        可以在B项目中提供一个应用初始化的方法,在引用项目中合适的时机调用;以下示例仅供参考:

import { libraryId } from "@service/user";
import { setLocal } from "src/utils/utils";
import { YB_MOBILE_LIBRARY_INFO } from "src/configs/constants";/*** 对外git引用,初始化方法*/
async function appInit(appType: string) {// 存储用户信息、token等// 初始化一些业务数据等等const res: any = await libraryId({});getApp().globalData.appType = appType || 'anterp'setLocal(YB_MOBILE_LIBRARY_INFO, res.res.data.libraryId);
}export default appInit;
8. 项目A/C工程中,使用项目B的组件或页面;

        在路由中对应配置项目B中的路由,对应创建页面文件,将项目B中的文件当作组件引入:【注:目前项目统一使用uni-simple-router路由管理插件,项目B中的路由跳转,只要在项目A/C工程中同样存在该路由,及可跳转】

<script>
import templateDetail from 'mobileB/src/pages/common/templateDetailInfo/index.vue';
export default {components: {templateDetail}
};
</script>
备注

        在实际的项目开发场景中,对需要融合项目架构的技术、实现方案统一性、代码规范等等有较高的要求,同时会遇到很多问题需要处理,如主题样式、不同平台的语法支持等等,本文仅对实现方案进行一个大致梳理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/647814.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

0125-1-vue3初体验

vue3尝鲜体验 初始化 安装vue/clinext&#xff1a; yarn global add vue/clinext # OR npm install -g vue/clinext然后在 Vue 项目运行&#xff1a; vue upgrade --next项目目录 vue3-template ├── index.html // html模板 ├── mock // mock数据 │ └── user.…

qt学习:QListWidget控件+自定义条目项+双击删除+单击获取

目录 图片 头函数 接口 显示案例 方法1 方法2 方法3 方法4 自定义 方法5 在方法4上实现 图片 头函数 #include <QListWidgetItem> 接口 //不怎么常用void addItem(const QString &label)void addItems(const QStringList &labels) //自定义条目项…

Redis客户端之Redisson(二)Redisson分布式锁

一、原理&#xff1a; Redisson并没有通过setNx命令来实现加锁&#xff0c;而是基于 Redis 看⻔狗机制&#xff0c;自己实现了一套分布式锁逻辑。 1、加锁机制&#xff1a; 二、使用方法&#xff1a;

EasyExcel实现下载模板

实体类&#xff1a; package com.aicut.monitor.domain;import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.s…

YOLOv8全网独家首发:Powerful-IoU更好、更快的收敛IoU | 2024年最新IoU

💡💡💡本文独家改进:Powerful-IoU更好、更快的收敛IoU,是一种结合了目标尺寸自适应惩罚因子和基于锚框质量的梯度调节函数的损失函数 💡💡💡MS COCO和PASCAL VOC数据集实现涨点 收录 YOLOv8原创自研 https://blog.csdn.net/m0_63774211/category_12511737.htm…

【新课上架】安装部署系列Ⅲ—Oracle 19c Data Guard部署之两节点RAC部署实战

01 课程介绍 Oracle Real Application Clusters (RAC) 是一种跨多个节点分布数据库的企业级解决方案。它使组织能够通过实现容错和负载平衡来提高可用性和可扩展性&#xff0c;同时提高性能。本课程基于当前主流版本Oracle 19cOEL7.9解析如何搭建2节点RAC对1节点单机的DATA GU…

数学知识第一期 质数

前言 本文是关于质数的一些内容&#xff0c;希望能够对大家有帮助&#xff01;&#xff01;&#xff01; 一、质数的基本内容 定义&#xff1a; 质数又称素数。一个大于1的自然数&#xff0c;除了1和它自身外&#xff0c;不能被其他自然数整除的数叫做质数&#xff1b;否则…

Go Zero微服务个人探究之路(十)实战走通微服务前台请求调用的一套流程model->rpc微服务->apiHTTP调用

前言 Go语言凭借低占用&#xff0c;高并发等优秀特性成为后台编程语言的新星&#xff0c;GoZero框架由七牛云技术副总裁团队编写&#xff0c;目前已经成为Go微服务框架里star数量最多的框架 本文记录讲述笔者一步步走通前台向后台发出请求&#xff0c;后台api调用rpc服务的相…

VR数字展厅,平面静态跨越到3D立体化时代

近些年&#xff0c;VR的概念被越来越多的人提起&#xff0c;较为常见的形式就是VR数字展厅。VR数字展厅的出现&#xff0c;让各地以及各行业的展厅展馆的呈现和宣传都发生了很大的改变和革新&#xff0c;同时也意味着展览传播的方式不再局限于原来的图文、视频&#xff0c;而是…

【Redis】list以及他的应用场景

介绍 &#xff1a;list 即是 链表。链表是一种非常常见的数据结构&#xff0c;特点是易于数据元素的插入和删除并且且可以灵活调整链表长度&#xff0c;但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 LinkedList&#xff0c;但是 C 语言并没有实现…

Spring Boot如何统计一个Bean中方法的调用次数

目录 实现思路 前置条件 实现步骤 首先我们先自定义一个注解 接下来定义一个切面 需要统计方法上使用该注解 测试 实现思路 通过AOP即可实现&#xff0c;通过AOP对Bean进行代理&#xff0c;在每次执行方法前或者后进行几次计数统计。这个主要就是考虑好如何避免并发情况…

JavaScript Proxy 对象、eval函数详解

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ 目录 ✨ 前言 ✨ 正文 Proxy 什么是 Proxy 代理 handlers get 捕获器 se…

Oracle ORA-09925

Error : 30: Read-only file system 造成这个问题的原因大多数是因为非正常关机后导致文件系统受损引起的&#xff0c;在系统重启之后&#xff0c;受损分区就会被Linux自动挂载为只读。 解决办法之一&#xff1a; 重启系统

聚观早报 | 特斯拉公布2023年财报;五菱红1号电池正式发布

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 1月26日消息 特斯拉公布2023年财报 五菱红1号电池正式发布 Redmi Note 13 Pro新春版开售 三星Galaxy S24系列发布…

HCIA——29HTTP、万维网、HTML、PPP、ICMP;万维网的工作过程;HTTP 的特点HTTP 的报文结构的选择、解答

学习目标&#xff1a; 计算机网络 1.掌握计算机网络的基本概念、基本原理和基本方法。 2.掌握计算机网络的体系结构和典型网络协议&#xff0c;了解典型网络设备的组成和特点&#xff0c;理解典型网络设备的工作原理。 3.能够运用计算机网络的基本概念、基本原理和基本方法进行…

在windows上用python版tensorrt推理

文章目录 尝试一&#xff1a;利用torch导出的pth文件&#xff0c;调用torch2trt来进行trt推理1.1 搭建环境1.2 如何trt推理1.3 遇到的问题 尝试二&#xff1a;把onnx模型转为sim版的onnx模型2.1 搭建onnxim环境2.2 使用 onnxsim 尝试三&#xff1a;把onnx-sim转到trt&#xff0…

Python之代码覆盖率框架coverage使用介绍

Python代码覆盖率工具coverage.py其实是一个第三方的包&#xff0c;同时支持Python2和Python3版本。 安装也非常简单&#xff0c;直接运行&#xff1a; pip install coverage 安装完成后&#xff0c;会在Python环境下的\Scripts下看到coverage.exe&#xff1b; 首先我们编写…

【LIBS】交叉编译TCPDUMP

目录 1. 安装编译工具2. 设置环境变量3. 编译libpcap3.1 安装依赖3.2 交叉编译 4. 编译TCPDUMP4.1 克隆仓库与生成构建环境4.2 静态链接LIBPCAP4.3 动态链接LIBPCAP4.4 构建与安装 5. 查看交叉编译结果5.1 文件布局 1. 安装编译工具 sudo apt-get install -y autoconf automak…

架构篇25:高可用存储架构-双机架构

文章目录 主备复制主从复制双机切换主主复制小结存储高可用方案的本质都是通过将数据复制到多个存储设备,通过数据冗余的方式来实现高可用,其复杂性主要体现在如何应对复制延迟和中断导致的数据不一致问题。因此,对任何一个高可用存储方案,我们需要从以下几个方面去进行思考…

爬取第一试卷网高三数学试卷并下载到本地

import requests import re import os filename 试卷\\ if not os.path.exists(filename):os.mkdir(filename) url https://www.shijuan1.com/a/sjsxg3/list_727_1.html headers {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.…