vue大型項目之分模塊運行/打包的實現(xiàn)
本文以vue-cli3+為例,實現(xiàn)多系統(tǒng)集成下的分模塊打包。分模塊打包方式多種多樣,下文可適用于多系統(tǒng)之間互不干擾,主系統(tǒng)可集成各子系統(tǒng),各子系統(tǒng)又可單獨運行的業(yè)務場景。
一、目標
我們要實現(xiàn)什么?所謂分模塊打包,那么各個模塊內就必須得有自己獨立的入口文件,路由文件。按照這種構想,我在一個新的腳手架src目錄下新建了一個projects目錄:
如上圖,可以看到Aproject、B、C、D四個項目。我在A項目中建了assets,common和views文件夾,其中assets可以再建img和css的文件夾,common內可以放公共組件或者方法,views頁面可以放頁面,甚至你還可以建一個components文件夾專門用來放組件。
好了,我們的視圖目錄結構大概就是上面的樣子。我們期待的是,我們可以打包這個A模塊這個‘小vue',就像打包一個完整vue的項目一樣。那么如何實現(xiàn)這部分呢?
二、打包單個模塊
我們知道,在package.json中,有項目啟動,打包的命令。
我們可以從這里入手。
這里就不得不提到cross-env這個模塊了。
我們之前在設置生產環(huán)境,測試環(huán)境,開發(fā)環(huán)境時也會用到這個模塊。在這里不詳細表述了。
cross-env:npm install --save-dev cross-env
現(xiàn)在我們的思路大概是這樣的,當我們執(zhí)行打包命令的時候,通過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項目 </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
效果完美。
三、打包總項目及子系統(tǒng)
一個大型項目必然會有公共模塊,這里會寫一個導航欄作為公共組件。
在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"> <!-- 系統(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項目", 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項目使用同樣的方法配置文件。
配置后效果如下:
到這里,我們就基本實現(xiàn)了分模塊運行以及集體運行了。
下面看一下打包。
在分別運行了B項目和common的打包命令以后,效果正常。
另外,我在這里采用了iframe的方式嵌入了其他項目,是因為引入的方式打包的時候會打包太多。
這樣做的好處就是公共項目僅僅作為一個外殼使用,其他項目與其并沒有太多的關聯(lián),保證了每個項目模塊的獨立性。
四、demo地址
https://github.com/Oralinge/pointsmodule
到此這篇關于vue大型項目之分模塊運行/打包的實現(xiàn)的文章就介紹到這了,更多相關vue分模塊打包內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue3中Composition?API和Options?API的區(qū)別
Vue3的Composition API和Options API是Vue.js框架中的兩種不同的API,本文主要介紹了Vue3中Composition?API和Options?API的區(qū)別,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧2023-06-06使用WebSocket+SpringBoot+Vue搭建簡易網(wǎng)頁聊天室的實現(xiàn)代碼
這篇文章主要介紹了使用WebSocket+SpringBoot+Vue搭建簡易網(wǎng)頁聊天室的實現(xiàn),具體的步驟如下,需要的朋友可以參考下2023-03-03Vue3處理大數(shù)據(jù)量渲染和優(yōu)化的方法小結
在現(xiàn)代Web應用中,隨著用戶數(shù)據(jù)和交互的復雜性增加,如何高效地處理大數(shù)據(jù)量渲染成為了前端開發(fā)的重要環(huán)節(jié),本文將以Vue 3為例,探討如何優(yōu)化大數(shù)據(jù)量渲染,提升應用性能,需要的朋友可以參考下2024-07-07vue項目中請求數(shù)據(jù)特別多導致頁面卡死的解決
這篇文章主要介紹了vue項目中請求數(shù)據(jù)特別多導致頁面卡死的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09