多系统集成:vue大型项目之分模块运行/打包
本文以vue-cli3+为例,实现多系统集成下的分模块打包。
本文以vue-cli3+为例,实现多系统集成下的分模块打包。分模块打包方式多种多样,下文可适用于多系统之间互不干扰,主系统可集成各子系统,各子系统又可单独运行的业务场景。
一、目标
我们要实现什么?所谓分模块打包,那么各个模块内就必须得有自己独立的入口文件,路由文件。按照这种构想,我在一个新的脚手架src目录下新建了一个projects目录:
如上图,可以看到Aproject、B、C、D四个项目。我在A项目中建了assets,common和views文件夹,其中assets可以再建img和css的文件夹,common内可以放公共组件或者方法,views页面可以放页面,甚至你还可以建一个components文件夹专门用来放组件。
好了,我们的视图目录结构大概就是上面的样子。我们期待的是,我们可以打包这个A模块这个‘小vue’,就像打包一个完整vue的项目一样。那么如何实现这部分呢?
二、打包单个模块
我们知道,在package.json中,有项目启动,打包的命令。
我们可以从这里入手。
这里就不得不提到cross-env这个模块了。
我们之前在设置生产环境,测试环境,开发环境时也会用到这个模块。在这里不详细表述了。
cross-env:npm install --save-dev cross-env
现在我们的思路大概是这样的,当我们执行打包命令的时候,通过cross-env去找到我们的入口文件,然后再打包。
所以我们可以模仿环境变量的写法,在package中写入如下图代码。
代码:
"dev:projectA": "cross-env PROJECT_NAME=projectA vue-cli-service serve",
"dev:projectB": "cross-env PROJECT_NAME=projectB vue-cli-service serve",
"dev:projectC": "cross-env PROJECT_NAME=projectC vue-cli-service serve",
"dev:projectD": "cross-env PROJECT_NAME=projectD vue-cli-service serve",
"build:projectA": "cross-env PROJECT_NAME=projectA vue-cli-service build",
"build:projectB": "cross-env PROJECT_NAME=projectB vue-cli-service build",
"build:projectC": "cross-env PROJECT_NAME=projectC vue-cli-service build",
"build:projectD": "cross-env PROJECT_NAME=projectD vue-cli-service build",
写完了这些,我们就可以着手模仿vue配置小vue的文件了。
- 在main.js中配置如下代码:
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
- 在App.vue中配置如下代码:
<template>
<div id="app">
<router-view />
</div>
</template>
<style lang="less">
</style>
- 在router.js中配置如下代码
import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
Vue.use(Router);
export default new Router({
routes: [
{
path: "/",
name: "home",
component: Home
}
]
});
- 在page文件夹中建立Home.vue,写入如下代码:
<template>
<div>
我是a项目
</div>
</template>
<script>
export default {};
</script>
<style></style>
- 在项目最外层建立config文件夹,在其中新建projectsConfig.js写入:
const config = {
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,
// 设置代理
proxy: {
"/eopenhapi": {
target: "http://open.jdpay.com",
changeOrigin: true
},
"/hapi": {
target: "http://open.jdpay.com",
changeOrigin: true
}
}
}
},
projectB: {},
projectC: {}
};
module.exports = config;
- 把projectsConfig.js并入vue.config.js,vue.config.js中代码如下
const config = require("./config/projectsConfig.js");
let projectName = process.env.PROJECT_NAME;
module.exports = {
...config[projectName],
// pages: conf.pages,
// 基本路径
// baseUrl: './',//vue-cli3.3以下版本使用
publicPath: "./", // vue-cli3.3+新版本使用
// 输出文件目录
outputDir: "dist/" + projectName + "/"
};
写到这里我们就建立一个完整的小vue了。
-
运行命令 cnpm run dev:projectA
-
运行命令 cnpm run build:projectA
效果完美。
三、打包总项目及子系统
一个大型项目必然会有公共模块,这里会写一个导航栏作为公共组件。
- 在projects下建立公共模块的文件夹common,写入前面A项目的目录结构,如图:
- 在package.json中写入运行命令和打包命令。
"dev:common": "cross-env PROJECT_NAME=common vue-cli-service serve",
"build:common": "cross-env PROJECT_NAME=common vue-cli-service build",
-
在Home.vue中写公共导航
这里会使用iview作为ui组件,但也因此有一个问题,我的A,B,C,D四个项目每个项目引入一遍UI框架,那打包出来整个项目将会非常的大,所以我们在子项目必须采用按需引入的方式。(项目中还是下载整个ivew)
写入如下代码:
<template>
<div class="main-content">
<Layout>
<header class="head-box">
<Menu
mode="horizontal"
theme="primary"
active-name="1"
@on-select="menuClick"
>
<div class="layout-logo">Oralinge</div>
<div class="layout-nav">
<div class="layout-nav-content">
<!-- 系统列表 -->
<span v-for="(item, index) in systemList" :key="index">
<MenuItem
:name="item.basepath + '?systemId=' + item.systemId"
@click="go(item)"
>
<Icon type="ios-navigate"></Icon>
{{ item.title }}
</MenuItem>
</span>
</div>
</div>
<div class="layout-right">
<Dropdown>
<!-- 登录姓名 -->
<a href="javascript:void(0)">
{{ user.userName }}
<Icon type="ios-arrow-down"></Icon>
</a>
<!-- 退出登录 -->
<DropdownMenu slot="list">
<DropdownItem name="logout">退出登录</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
</Menu>
</header>
</Layout>
<iframe
:src="systemUrl"
width="100%"
height="100%"
frameborder="0"
class="iframe"
id="bossIframe"
></iframe>
</div>
</template>
<script>
import {
Layout,
Menu,
MenuItem,
Dropdown,
DropdownItem,
DropdownMenu
} from "view-design";
export default {
components: {
Layout,
Menu,
MenuItem,
Dropdown,
DropdownItem,
DropdownMenu
},
data() {
return {
systemUrl: "",
isFullscreen: false,
loading: false,
systemList: [
{
title: "A项目",
basepath: "http://localhost:8080/#/",
systemId: "A"
},
{
title: "B项目",
basepath: "http://localhost:8082/#/",
systemId: "B"
},
{
title: "C项目",
basepath: "http://localhost:8083/#/",
systemId: "c"
},
{
title: "D项目",
basepath: "http://localhost:8084/#/",
systemId: "D"
}
],
user: {}
};
},
mounted() {
this.systemUrl =
this.systemList[0].basepath + "?systemId=" + this.systemList[0].systemId;
},
methods: {
menuClick(name) {
this.systemUrl = name;
}
}
};
</script>
<style lang="less" scoped>
@head-height: 50px;
.main-content {
height: 100%;
padding-top: @head-height;
box-sizing: border-box;
overflow: hidden;
}
.head-box {
width: 100%;
height: @head-height;
line-height: @head-height;
position: fixed;
top: 0;
left: 0;
min-width: 1200px;
.ivu-menu-horizontal {
height: 100%;
line-height: @head-height;
}
.layout-logo {
display: inline-block;
width: 200px;
color: #fff;
font-size: 28px;
text-align: center;
vertical-align: top;
position: absolute;
left: 0;
top: 0;
background-color: #2d8cf0;
z-index: 5;
}
.layout-nav {
display: inline-block;
width: 100%;
height: 100%;
padding-left: 200px;
padding-right: 100px;
box-sizing: border-box;
overflow-x: auto;
z-index: 4;
&-content {
// width: 100%;
overflow: hidden;
height: 100%;
}
}
.layout-right {
padding-right: 20px;
padding-left: 20px;
position: absolute;
right: 0;
top: 0;
background-color: #2d8cf0;
z-index: 5;
a {
color: #fff;
}
}
.ivu-menu-item-active {
font-size: 20px;
}
}
</style>
效果:
B项目使用同样的方法配置文件。
配置后效果如下:
到这里,我们就基本实现了分模块运行以及集体运行了。
下面看一下打包。
在分别运行了B项目和common的打包命令以后,效果正常。
另外,我在这里采用了iframe的方式嵌入了其他项目,是因为引入的方式打包的时候会打包太多。
这样做的好处就是公共项目仅仅作为一个外壳使用,其他项目与其并没有太多的关联,保证了每个项目模块的独立性。
四、demo地址
https://github.com/Oralinge/pointsmodule
以上。
更多推荐
所有评论(0)