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 相关文章推荐
IE与FireFox的兼容性问题分析
Apr 22 Javascript
List Information About the Binary Files Used by an Application
Jun 11 Javascript
ajax无刷新动态调用股票信息(改良版)
Nov 01 Javascript
JavaScript内核之基本概念
Oct 21 Javascript
suggestion开发小结以及对键盘事件的总结(针对中文输入法状态)
Dec 20 Javascript
javascript(js)的小数点乘法除法问题详解
Mar 07 Javascript
js浏览器本地存储store.js介绍及应用
May 13 Javascript
BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面
Aug 01 Javascript
JavaScript制作简单分页插件
Sep 11 Javascript
详解Vuex管理登录状态
Nov 13 Javascript
浅谈react-router HashRouter和BrowserRouter的使用
Dec 29 Javascript
node koa2 ssr项目搭建的方法步骤
Dec 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函数(简单整理)
2010/04/30 PHP
PHP实现把数字ID转字母ID
2013/08/12 PHP
PHP中如何实现常用邮箱的基本判断
2014/01/07 PHP
php实现按文件名搜索文件的远程文件查找器
2014/05/10 PHP
PHP的关于变量和日期处理的一些面试题目整理
2015/08/10 PHP
php 根据自增id创建唯一编号类
2017/04/06 PHP
PHP简单实现正则匹配省市区的方法
2018/04/13 PHP
PHP笛卡尔积实现算法示例
2018/07/30 PHP
PHP 对象继承原理与简单用法示例
2020/04/21 PHP
JavaScript 打地鼠游戏代码说明
2010/10/12 Javascript
6款经典实用的jQuery小插件及源码(对话框/提示工具等等)
2013/02/04 Javascript
JS的get和set使用示例
2014/02/20 Javascript
如何书写高质量jQuery代码(使用jquery性能问题)
2014/06/30 Javascript
jQuery对于显示和隐藏等常用状态的判断方法
2014/12/13 Javascript
JavaScript实现Java中StringBuffer的方法
2015/02/09 Javascript
jQuery使用before()和after()在元素前后添加内容的方法
2015/03/26 Javascript
D3.js实现饼状图的方法详解
2016/09/21 Javascript
微信小程序 石头剪刀布实例代码
2017/01/04 Javascript
利用Node.js编写跨平台的spawn语句详解
2017/02/12 Javascript
vue.js 实现点击展开收起动画效果
2018/07/07 Javascript
在vue中给列表中的奇数行添加class的实现方法
2018/09/05 Javascript
element-ui上传一张图片后隐藏上传按钮功能
2019/05/22 Javascript
js事件触发操作实例分析
2019/06/21 Javascript
JavaScript实现PC端四格密码输入框功能
2020/02/19 Javascript
vue tab滚动到一定高度,固定在顶部,点击tab切换不同的内容操作
2020/07/22 Javascript
基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能
2021/01/05 Vue.js
Python urlopen 使用小示例
2008/09/06 Python
在Python中使用zlib模块进行数据压缩的教程
2015/06/26 Python
python实现八大排序算法(1)
2017/09/14 Python
Python要如何实现列表排序的几种方法
2020/02/21 Python
Django 5种类型Session使用方法解析
2020/04/29 Python
Numpy实现卷积神经网络(CNN)的示例
2020/10/09 Python
农村面貌改造提升实施方案
2014/03/18 职场文书
工厂车间标语
2014/06/19 职场文书
2015年乡镇食品安全工作总结
2015/10/22 职场文书
使用Cargo工具高效创建Rust项目
2022/08/14 Javascript