vue大型項(xiàng)目之分模塊運(yùn)行/打包的實(shí)現(xiàn)
本文以vue-cli3+為例,實(shí)現(xiàn)多系統(tǒng)集成下的分模塊打包。分模塊打包方式多種多樣,下文可適用于多系統(tǒng)之間互不干擾,主系統(tǒng)可集成各子系統(tǒng),各子系統(tǒng)又可單獨(dú)運(yùn)行的業(yè)務(wù)場景。
一、目標(biāo)
我們要實(shí)現(xiàn)什么?所謂分模塊打包,那么各個(gè)模塊內(nèi)就必須得有自己獨(dú)立的入口文件,路由文件。按照這種構(gòu)想,我在一個(gè)新的腳手架src目錄下新建了一個(gè)projects目錄:

如上圖,可以看到Aproject、B、C、D四個(gè)項(xiàng)目。我在A項(xiàng)目中建了assets,common和views文件夾,其中assets可以再建img和css的文件夾,common內(nèi)可以放公共組件或者方法,views頁面可以放頁面,甚至你還可以建一個(gè)components文件夾專門用來放組件。
好了,我們的視圖目錄結(jié)構(gòu)大概就是上面的樣子。我們期待的是,我們可以打包這個(gè)A模塊這個(gè)‘小vue',就像打包一個(gè)完整vue的項(xiàng)目一樣。那么如何實(shí)現(xiàn)這部分呢?
二、打包單個(gè)模塊
我們知道,在package.json中,有項(xiàng)目啟動(dòng),打包的命令。

我們可以從這里入手。
這里就不得不提到cross-env這個(gè)模塊了。
我們之前在設(shè)置生產(chǎn)環(huán)境,測試環(huán)境,開發(fā)環(huán)境時(shí)也會(huì)用到這個(gè)模塊。在這里不詳細(xì)表述了。
cross-env:npm install --save-dev cross-env
現(xiàn)在我們的思路大概是這樣的,當(dāng)我們執(zhí)行打包命令的時(shí)候,通過cross-env去找到我們的入口文件,然后再打包。
所以我們可以模仿環(huán)境變量的寫法,在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項(xiàng)目
</div>
</template>
<script>
export default {};
</script>
<style></style>
在項(xiàng)目最外層建立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, // 是否自動(dòng)打開瀏覽器頁面
host: "0.0.0.0", // 指定使用一個(gè) host,默認(rèn)是 localhost
https: false, // 使用https提供服務(wù)
disableHostCheck: true,
// 設(shè)置代理
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 + "/"
};
寫到這里我們就建立一個(gè)完整的小vue了。
運(yùn)行命令 cnpm run dev:projectA

運(yùn)行命令 cnpm run build:projectA

效果完美。
三、打包總項(xiàng)目及子系統(tǒng)
一個(gè)大型項(xiàng)目必然會(huì)有公共模塊,這里會(huì)寫一個(gè)導(dǎo)航欄作為公共組件。
在projects下建立公共模塊的文件夾common,寫入前面A項(xiàng)目的目錄結(jié)構(gòu),如圖:

在package.json中寫入運(yùn)行命令和打包命令。
"dev:common": "cross-env PROJECT_NAME=common vue-cli-service serve", "build:common": "cross-env PROJECT_NAME=common vue-cli-service build",
在Home.vue中寫公共導(dǎo)航
這里會(huì)使用iview作為ui組件,但也因此有一個(gè)問題,我的A,B,C,D四個(gè)項(xiàng)目每個(gè)項(xiàng)目引入一遍UI框架,那打包出來整個(gè)項(xiàng)目將會(huì)非常的大,所以我們在子項(xiàng)目必須采用按需引入的方式。(項(xiàng)目中還是下載整個(gè)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">
<!-- 系統(tǒng)列表 -->
<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)" rel="external nofollow" >
{{ 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項(xiàng)目",
basepath: "http://localhost:8080/#/",
systemId: "A"
},
{
title: "B項(xiàng)目",
basepath: "http://localhost:8082/#/",
systemId: "B"
},
{
title: "C項(xiàng)目",
basepath: "http://localhost:8083/#/",
systemId: "c"
},
{
title: "D項(xiàng)目",
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項(xiàng)目使用同樣的方法配置文件。
配置后效果如下:

到這里,我們就基本實(shí)現(xiàn)了分模塊運(yùn)行以及集體運(yùn)行了。
下面看一下打包。
在分別運(yùn)行了B項(xiàng)目和common的打包命令以后,效果正常。

另外,我在這里采用了iframe的方式嵌入了其他項(xiàng)目,是因?yàn)橐氲姆绞酱虬臅r(shí)候會(huì)打包太多。
這樣做的好處就是公共項(xiàng)目僅僅作為一個(gè)外殼使用,其他項(xiàng)目與其并沒有太多的關(guān)聯(lián),保證了每個(gè)項(xiàng)目模塊的獨(dú)立性。
四、demo地址
https://github.com/Oralinge/pointsmodule
到此這篇關(guān)于vue大型項(xiàng)目之分模塊運(yùn)行/打包的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)vue分模塊打包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue動(dòng)態(tài)路由路徑重復(fù)及刷新丟失頁面問題的解決
這篇文章主要介紹了Vue動(dòng)態(tài)路由路徑重復(fù)及刷新丟失頁面問題的解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
M1 pro芯片啟動(dòng)Vue項(xiàng)目的方法步驟
本文主要介紹了M1 pro芯片啟動(dòng)Vue項(xiàng)目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
Vue3中Composition?API和Options?API的區(qū)別
Vue3的Composition API和Options API是Vue.js框架中的兩種不同的API,本文主要介紹了Vue3中Composition?API和Options?API的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
使用WebSocket+SpringBoot+Vue搭建簡易網(wǎng)頁聊天室的實(shí)現(xiàn)代碼
這篇文章主要介紹了使用WebSocket+SpringBoot+Vue搭建簡易網(wǎng)頁聊天室的實(shí)現(xiàn),具體的步驟如下,需要的朋友可以參考下2023-03-03
vue常用的數(shù)字孿生可視化的自適應(yīng)方案
這篇文章主要為大家介紹了vue常用的數(shù)字孿生可視化的自適應(yīng)方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Vue3處理大數(shù)據(jù)量渲染和優(yōu)化的方法小結(jié)
在現(xiàn)代Web應(yīng)用中,隨著用戶數(shù)據(jù)和交互的復(fù)雜性增加,如何高效地處理大數(shù)據(jù)量渲染成為了前端開發(fā)的重要環(huán)節(jié),本文將以Vue 3為例,探討如何優(yōu)化大數(shù)據(jù)量渲染,提升應(yīng)用性能,需要的朋友可以參考下2024-07-07
vue項(xiàng)目中請求數(shù)據(jù)特別多導(dǎo)致頁面卡死的解決
這篇文章主要介紹了vue項(xiàng)目中請求數(shù)據(jù)特別多導(dǎo)致頁面卡死的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
vue 權(quán)限認(rèn)證token的實(shí)現(xiàn)方法
這篇文章主要介紹了vue 權(quán)限認(rèn)證token的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07

