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

时间:2021-05-26

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

一、目标

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


如上图,可以看到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大型项目之分模块运行/打包的实现的文章就介绍到这了,更多相关vue分模块打包内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章