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


Posted in Javascript onSeptember 21, 2020

本文以vue-cli3+为例,实现多系统集成下的分模块打包。分模块打包方式多种多样,下文可适用于多系统之间互不干扰,主系统可集成各子系统,各子系统又可单独运行的业务场景。

一、目标

我们要实现什么?所谓分模块打包,那么各个模块内就必须得有自己独立的入口文件,路由文件。按照这种构想,我在一个新的脚手架src目录下新建了一个projects目录:

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

如上图,可以看到Aproject、B、C、D四个项目。我在A项目中建了assets,common和views文件夹,其中assets可以再建img和css的文件夹,common内可以放公共组件或者方法,views页面可以放页面,甚至你还可以建一个components文件夹专门用来放组件。

好了,我们的视图目录结构大概就是上面的样子。我们期待的是,我们可以打包这个A模块这个‘小vue',就像打包一个完整vue的项目一样。那么如何实现这部分呢?

二、打包单个模块

我们知道,在package.json中,有项目启动,打包的命令。

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

我们可以从这里入手。

这里就不得不提到cross-env这个模块了。
我们之前在设置生产环境,测试环境,开发环境时也会用到这个模块。在这里不详细表述了。

cross-env:npm install --save-dev cross-env

现在我们的思路大概是这样的,当我们执行打包命令的时候,通过cross-env去找到我们的入口文件,然后再打包。

所以我们可以模仿环境变量的写法,在package中写入如下图代码。

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

代码:

"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

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

运行命令 cnpm run build:projectA

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

效果完美。

三、打包总项目及子系统

一个大型项目必然会有公共模块,这里会写一个导航栏作为公共组件。

在projects下建立公共模块的文件夹common,写入前面A项目的目录结构,如图:

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

在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>

效果:

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

B项目使用同样的方法配置文件。
配置后效果如下:

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

到这里,我们就基本实现了分模块运行以及集体运行了。

下面看一下打包。

在分别运行了B项目和common的打包命令以后,效果正常。

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

另外,我在这里采用了iframe的方式嵌入了其他项目,是因为引入的方式打包的时候会打包太多。

这样做的好处就是公共项目仅仅作为一个外壳使用,其他项目与其并没有太多的关联,保证了每个项目模块的独立性。

四、demo地址

https://github.com/Oralinge/pointsmodule

到此这篇关于vue大型项目之分模块运行/打包的实现的文章就介绍到这了,更多相关vue分模块打包内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
网站导致浏览器崩溃的原因总结(多款浏览器) 推荐
Apr 15 Javascript
js日历功能对象
Jan 12 Javascript
javascript按位非运算符的使用方法
Nov 14 Javascript
js 去掉空格实例 Trim() LTrim() RTrim()
Jan 07 Javascript
node.js应用后台守护进程管理器Forever安装和使用实例
Jun 01 Javascript
javascript和jquery实现设置和移除文本框默认值效果代码
Jan 13 Javascript
JS实现新浪微博效果带遮罩层的弹出框代码
Oct 12 Javascript
AngularJS实现ajax请求的方法
Nov 22 Javascript
node.js学习之断言assert的使用示例
Sep 28 Javascript
详解angularjs跨页面传参遇到的一些问题
Nov 01 Javascript
JavaScript 斐波那契数列 倒序输出 输出100以内的质数代码实例
Sep 11 Javascript
浅析vue-router实现原理及两种模式
Feb 11 Javascript
Vue+Element ui 根据后台返回数据设置动态表头操作
Sep 21 #Javascript
JS实现小米轮播图
Sep 21 #Javascript
vue 里面的 $forceUpdate() 强制实例重新渲染操作
Sep 21 #Javascript
vue组件入门知识全梳理
Sep 21 #Javascript
Ajax获取node服务器数据的完整步骤
Sep 20 #Javascript
微信小程序获取当前时间及星期几的实例代码
Sep 20 #Javascript
vue操作dom元素的3种方法示例
Sep 20 #Javascript
You might like
php SQL之where语句生成器
2009/03/24 PHP
PHP获取网址的顶级域名函数代码
2012/09/24 PHP
Yii查询生成器(Query Builder)用法实例教程
2014/09/04 PHP
php+ajax实现无刷新分页的方法
2014/11/04 PHP
在Laravel 的 Blade 模版中实现定义变量
2019/10/14 PHP
Laravel 集成微信用户登录和绑定的实现
2019/12/27 PHP
javascript 四则运算精度修正函数代码
2010/05/31 Javascript
JavaScript Chart 插件整理
2010/06/18 Javascript
由JavaScript中call()方法引发的对面向对象继承机制call的思考
2011/09/12 Javascript
一波JavaScript日期判断脚本分享
2016/03/06 Javascript
Javascript实现图片加载从模糊到清晰显示的方法
2016/06/21 Javascript
JS仿hao123导航页面图片轮播效果
2016/09/01 Javascript
Asp.Net之JS生成分页条的方法
2016/11/23 Javascript
AngularJS中$apply方法和$watch方法用法总结
2016/12/13 Javascript
浅谈jQuery中的$.extend方法来扩展JSON对象
2017/02/12 Javascript
解决Vue axios post请求,后台获取不到数据的问题方法
2018/08/11 Javascript
Vue项目服务器部署之子目录部署方法
2019/05/12 Javascript
基于vue实现一个神奇的动态按钮效果
2019/05/15 Javascript
nodejs dgram模块广播+组播的实现示例
2019/11/04 NodeJs
Vue v-bind动态绑定class实例方法
2020/01/15 Javascript
Vue 中如何将函数作为 props 传递给组件的实现代码
2020/05/12 Javascript
Vue路由切换页面不更新问题解决方案
2020/07/10 Javascript
解决vue addRoutes不生效问题
2020/08/04 Javascript
[01:02:25]2014 DOTA2华西杯精英邀请赛5 24 NewBee VS VG
2014/05/25 DOTA
详解Python中heapq模块的用法
2016/06/28 Python
Python3一行代码实现图片文字识别的示例
2018/01/15 Python
对Python中gensim库word2vec的使用详解
2018/05/08 Python
pygame库实现俄罗斯方块小游戏
2019/10/29 Python
基于FME使用Python过程图解
2020/05/13 Python
Python如何实现的二分查找算法
2020/05/27 Python
Python grequests模块使用场景及代码实例
2020/08/10 Python
毕业生自我鉴定
2013/11/05 职场文书
医院护士专业个人的求职信
2013/12/09 职场文书
竞选体育委员演讲稿
2014/04/26 职场文书
导游词之阳朔遇龙河
2019/12/16 职场文书
Python基础之pandas数据合并
2021/04/27 Python