vue项目架构:多子系统拆分与集成

现状

公司现有一个大型项目分为多个子系统(或叫子模块),现公司产品经理提出要求,各子系统要实现即可独立分包部署,又可以整合为一个整体包。按照以前项目经验及一贯作风,是将每个子系统构建一个git代码仓库管理,部署时无论是独立部署,还是统一出口都可以使用nginx来进行代理而实现。
但是各个子系统的共用组件、依赖、认证等都是一样,分多个git仓库源代码来管理,会存在很多重复工作,并且修改一个组件需要在每个子系统中进行修改。不便于管理及维护。

分析

要实现多子系统互相不干扰,并主系统能集成任意子系统,那么我们考虑就需要对每个子系统有一个独立的入口文件,同时主系统也有自己的入口文件。从而实现可拔插式结构,子系统之间通过统一的token进行交互认证。逻辑结构如下图:


逻辑结构.png

实现

1、使用脚手架构建项目,在src下新建文件夹projects,用于存放主系统及各子系统文件,其中任何一个项目文件都相当于一个小vue,可以进行单独运行。具体如下:

工程目录结构.png

2、任何小vue项目中包含入口文件main.js,以及项目需要的views页面,这里我们将路由进行拆分为index.js,和path.js,目的是便于我们主系统需要子系统路由而进行路由合并。
index.js——主要用于创建路由对象,以及合并需要的路由。
path.js——用于放置项目中需要的具体路由。
以主系统为例:
index.js 文件内容:

import Vue from "vue";
import VueRouter from "vue-router";

//引入主系统路由path.js
import mainRouter from "@/projects/mainSystem/router/path.js"//导入主系统路由文件


//引入其他子系统path.js
import projectARouter from "@/projects/projectA/router/path.js"//导入子系统路由文件


Vue.use(VueRouter);
//合并路由(将需要的路由进行合并)
let routes = new Set([...mainRouter, ...projectARouter ]);

const router = new VueRouter({
    mode: 'hash',
    base: process.env.BASE_URL,
    routes
})
//解决路由导航冗余报错(路由重复)
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
    return originalPush.call(this, location).catch(err => err)
}
export default router

path.js文件内容(主系统自身的路由):

/**
 * 主系统路由地址
 * @returns {Promise<*>|*}
 */
let firstPageIndex=()=>import(/* webpackChunkName: "mainSystem" */ "@/projects/mainSystem/views/index/index.vue")
let mainHome=()=>import(/* webpackChunkName: "mainSystem" */ "@/projects/mainSystem/views/Home")
let mainLayout=()=>import(/* webpackChunkName: "mainSystem" */ "@/components/base/publicLayout")


export default [
    {
        path: "/",
        name: "home",
        component: mainHome
    }, {
        path: '/mainSystem-layout.html/:childSystemCode',
        name: 'mainSystem-layout',
        component: mainLayout,
        children: [
            {
                path: "/mainSystem/index.html",
                name: "/mainSystem/index",
                component: firstPageIndex,
                meta: {
                    isFork: false,
                    hideHeader: false,
                    notPadding: true
                }

            }
        ]
    }
]

3、在根目录下创建config文件夹及projectsConfig.js,用于存放各系统入口配置。

const config = {
    //主系统
    mainSystem: {
        pages: {
            index: {
                entry: "src/projects/mainSystem/main.js",
                template: "public/index.html",
                filename: "index.html"
            }
        },
        devServer: {
            port: 8081, // 端口地址
            open: false, // 是否自动打开浏览器页面
            host: "0.0.0.0", // 指定使用一个 host,默认是 localhost
            https: false, // 使用https提供服务
            disableHostCheck: true,
        }
    },
    //子系统A
    projectA: {
        pages: {
            index: {
                entry: "src/projects/projectA/main.js",
                template: "public/index.html",
                filename: "index.html"
            }
        },
        devServer: {
            port: 8080, // 端口地址
            open: false, // 是否自动打开浏览器页面
            host: "0.0.0.0", // 指定使用一个 host,默认是 localhost
            https: false, // 使用https提供服务
            disableHostCheck: true,
        }
    },
};
module.exports = config;

4、将配置文件projectsConfig.js在vue.config.js引入,通过控制入口文件的路径和输出的路径实现,分模块打包。

//多子系统分模块打包
const config = require("./config/projectsConfig.js");
let projectName = process.env.PROJECT_NAME;

module.exports = {
......
......
......
 // webpack-dev-server 相关配置
    ...config[projectName],
}

5、安装cross-env,在我们执行打包命令的时候,通过cross-env找到我们的入口文件。
npm install --save-dev cross-env

6、修改package.json中脚本。

{
"scripts": {
    "dev:mainSystem": "cross-env PROJECT_NAME=mainSystem vue-cli-service serve",
    "dev:projectA": "cross-env PROJECT_NAME=projectA vue-cli-service serve",
    "build:mainSystem": "cross-env PROJECT_NAME=mainSystem vue-cli-service build",
    "build:projectA": "cross-env PROJECT_NAME=projectA  vue-cli-service build",
  },
}

7、现在可以使用命令分别进行运行 和 打包各系统
运行及打包主系统
npm run dev:mainSystem
npm run build:mainSystem
运行及打包子系统
npm run dev:projectA
npm run build:projectA

注意

1、除入口文件需要配置正确外,任何小vue需要使用的路由必须引入合并。
2、由于路由需要合并使用,所以在各子系统中定义路由最好添加固定的前缀,从而避免路由名冲突。
3、各系统中使用统一认证token进行交互,所以在业务逻辑中,注意token的使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342