欢迎来到代码驿站!

vue

当前位置:首页 > 网页前端 > vue

vue大型项目之分模块运行/打包的实现

时间:2021-06-28 08:24:27|栏目: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,
  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

上一篇:Vue axios全局拦截 get请求、post请求、配置请求的实例代码

栏    目:vue

下一篇:vue-video-player 通过自定义按钮组件实现全屏切换效果【推荐】

本文标题:vue大型项目之分模块运行/打包的实现

本文地址:http://www.codeinn.net/misctech/149231.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有