1. 程式人生 > 程式設計 >vue大型專案之分模組執行/打包的實現

vue大型專案之分模組執行/打包的實現

本文以vue-cli3+為例,實現多系統整合下的分模組打包。分模組打包方式多種多樣,下文可適用於多系統之間互不干擾,主系統可整合各子系統,各子系統又可單獨執行的業務場景。

一、目標

我們要實現什麼?所謂分模組打包,那麼各個模組內就必須得有自己獨立的入口檔案,路由檔案。按照這種構想,我在一個新的腳手架src目錄下新建了一個projects目錄:

圖1

如上圖,可以看到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)" 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,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

到此這篇關於vue大型專案之分模組執行/打包的實現的文章就介紹到這了,更多相關vue分模組打包內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!