欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 高考 > qiankun 主项目和子项目都是 vue2,部署在不同的服务器上,nginx 配置

qiankun 主项目和子项目都是 vue2,部署在不同的服务器上,nginx 配置

2024/10/25 14:29:25 来源:https://blog.csdn.net/qq_37309987/article/details/142828246  浏览:    关键词:qiankun 主项目和子项目都是 vue2,部署在不同的服务器上,nginx 配置

1、主项目配置

        1.1 micro.vue 组件

<template><div id="container-sub-app"></div>
</template><script>
import { loadMicroApp } from 'qiankun';
import actions from '@/utils/actions.js';export default {name: 'microApp',mixins: [actions],data() {return {microApp: null};},mounted() {const getMicroInfo = this.getMicroInfo();this.microApp = loadMicroApp(getMicroInfo, {singular: true});},beforeDestroy() {console.log('beforeDestroy...');this.microApp.unmount();},methods: {// 手动加载微应用getMicroInfo() {const appIdentifying = this.$route.path.split('/')[1];let data = {};const href = window.location.host;for (let i = 0; i < document.subApps.length; i++) {const element = document.subApps[i];if (element.activeRule.includes(appIdentifying)) {if (typeof element.entry !== 'string') {data = {...element,entry: element.entry[href]? element.entry[href]: Object.values(element.entry)[0]};} else {data = { ...element };}data.props = {token: {userInfo: {userName: '小明',userId: '123',date: new Date().toLocaleString()}}};data.activeRule = [appIdentifying];break;}}return data;}}
};
</script>

   1.2 index.html 引入配置

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><metaname="viewport"content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><link rel="icon" href="<%= BASE_URL %>favicon.ico" /><script src="<%= BASE_URL %>register-apps.js"></script><title><%= webpackConfig.name %></title></head><body><noscript><strong>We're sorry but <%= webpackConfig.name %> doesn't work properly withoutJavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><!-- built files will be auto injected --></body>
</html>

        1.3 register-apps.js 配置

document.subApps = [{name: 'besFront',//entry: '//localhost:8086/bes-front/',// 本地调试entry: '/bes-front/',// 部署到服务器container: '#container-sub-app',activeRule: '/bes-front'}
];

        1.4 路由配置

import Vue from 'vue';
import Router from 'vue-router';Vue.use(Router);import Layout from '@/layout';
import MicroApp from '@/components/microApp';export const constantRoutes = [{path: '/login',component: () => import('@/views/login/index'),hidden: true},{path: '/404',component: () => import('@/views/404'),hidden: true},{path: '/dashboard',component: Layout,redirect: '/dashboard/index',children: [{path: 'index',name: 'Dashboard',component: () => import('@/views/dashboard/index'),meta: { title: 'Dashboard', icon: 'dashboard' }}]},{path: '/',component: Layout,children: [{path: 'bes-front',component: MicroApp// 重点,用于加载子项目}]}// 404 page must be placed at the end !!!// { path: '*', redirect: '/404', hidden: true }
];const createRouter = () =>new Router({mode: 'history', // require service supportbase: '/parent/',// 部署在不同服务器上,主应用加前缀scrollBehavior: () => ({ y: 0 }),routes: constantRoutes});const router = createRouter();// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {const newRouter = createRouter();router.matcher = newRouter.matcher; // reset router
}export default router;

2、子项目配置

        2.1 main.js 配置

// 动态设置 publicPath
import './public-path';
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';Vue.config.productionTip = false;
Vue.use(ElementUI);let instance = null;
function render(props = {}) {console.log('子应用 render props::', props, 'instance====', instance);// sessionStorage.setItem('userInfo', JSON.stringify(props.token.userInfo));const { container } = props;instance = new Vue({router,store,render: (h) => h(App)}).$mount(container ? container.querySelector('#app') : '#app');
}// 独立运行时
/* eslint-disable */
if (!window.__POWERED_BY_QIANKUN__) {render();
}export async function bootstrap() {console.log('子应用 bootstrap ===========================');
}let initialState = null;
export async function mount(props) {console.log('子应用 mount props ===============', props);sessionStorage.setItem('userInfo', JSON.stringify(props.token.userInfo));props.onGlobalStateChange((state, prev) => {// state: 变更后的状态; prev 变更前的状态console.log('子应用获取共享数据 state::', state, 'prev::', prev);// 接收主应用中的共享数据 并将其设置为全局变量Vue.prototype.$initialState = state;});props.setGlobalState({initialState:'子应用中修改主应用中的全局变量,实现住应用子应用间数据的双向双向通信'});render(props);
}
export async function unmount() {console.log('子应用 unmount==========');instance.$destroy();instance.$el.innerHTML = '';instance = null;
}

        2.2  public-path 文件

if (window.__POWERED_BY_QIANKUN__) {/* eslint-disable @typescript-eslint/camelcase */__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

        2.3 vue.config.js 配置

'use strict';
const path = require('path');
const defaultSettings = require('./src/settings.js');
const proxyTable = require('./proxyTable');function resolve(dir) {return path.join(__dirname, dir);
}const name = defaultSettings.title || 'vue Admin Template'; // page title// If your port is set to 80,// use administrator privileges to execute the command line.
// For example, Mac: sudo npm run
// You can change the port by the following methods:
// port = 9528 npm run dev OR npm run dev --port = 9528
const port = process.env.port || process.env.npm_config_port || 9528; // dev port// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {/*** You will need to set publicPath if you plan to deploy your site under a sub path,* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,* then publicPath should be set to "/bar/".* In most cases please use '/' !!!* Detail: https://cli.vuejs.org/config/#publicpath*/publicPath: '/bes-front/',outputDir: 'dist',assetsDir: 'static',lintOnSave: process.env.NODE_ENV === 'development',productionSourceMap: false,devServer: {headers:{"Access-Control-Allow-Origin": "*",},port: port,open: true,proxy: proxyTable,overlay: {warnings: false,errors: true}},configureWebpack: {// provide the app's title in webpack's name field, so that// it can be accessed in index.html to inject the correct title.name: name,output:{library: `besFront`,// 主应用libraryTarget: "umd",// 把微应用打包成 umd 库格式jsonpFunction: `webpackJsonp_besFront`,// webpack5 需要把 jsonpFunction 替换成 chunkLoadingGlobal},resolve: {alias: {'@': resolve('src')}}},chainWebpack(config) {// it can improve the speed of the first screen, it is recommended to turn on preloadconfig.plugin('preload').tap(() => [{rel: 'preload',// to ignore runtime.js// https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-service/lib/config/app.js#L171fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],include: 'initial'}]);// when there are many pages, it will cause too many meaningless requestsconfig.plugins.delete('prefetch');// set svg-sprite-loaderconfig.module.rule('svg').exclude.add(resolve('src/icons')).end();config.module.rule('icons').test(/\.svg$/).include.add(resolve('src/icons')).end().use('svg-sprite-loader').loader('svg-sprite-loader').options({symbolId: 'icon-[name]'}).end();config.when(process.env.NODE_ENV !== 'development', (config) => {config.plugin('ScriptExtHtmlWebpackPlugin').after('html').use('script-ext-html-webpack-plugin', [{// `runtime` must same as runtimeChunk name. default is `runtime`inline: /runtime\..*\.js$/}]).end();config.optimization.splitChunks({chunks: 'all',cacheGroups: {libs: {name: 'chunk-libs',test: /[\\/]node_modules[\\/]/,priority: 10,chunks: 'initial' // only package third parties that are initially dependent},elementUI: {name: 'chunk-elementUI', // split elementUI into a single packagepriority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or apptest: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm},commons: {name: 'chunk-commons',test: resolve('src/components'), // can customize your rulesminChunks: 3, //  minimum common numberpriority: 5,reuseExistingChunk: true}}});// https:// webpack.js.org/configuration/optimization/#optimizationruntimechunkconfig.optimization.runtimeChunk('single');});}
};

         2.3  接口需加前缀区分

const uri = '/child1/api';// 部门新增
export async function departmentAddApi(params) {return $ajax.post(`${uri}/department/add`, params);
}

3、主项目和子项目部署在不同的服务器上,其中主应用路由使用history模式,子应用路由使用hash模式,子应用所有的静态资源及接口统一从主应用进行转发,nginx 配置如下:

主应用 nginx 配置:

locatoin /parent/ {root /opt/parent;index index.html index.htm;try_files $uri $uri/ /index.html;
}location /bes-front/ {proxy_pass http://子应用ip/bes-front/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header REMOTE_HOST $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}location /bes-front/static/ {proxy_pass http://子应用ip/bes-front/static/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header REMOTE_HOST $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}location /child1/ {proxy_pass http://子应用ip/child1/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header REMOTE_HOST $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

注:使用的下面这种部署方式,主应用代码放在主应用服务器的/opt/parent目录下,子应用代码放在子应用服务器的/opt/bes-front目录下面,重点是主应用的路由要加前缀进行区分,其次,子应用的所有接口转发都统一从主应用转发到子应用,因此子应用的接口要增加前缀进行区分

官网参考链接:https://qiankun.umijs.org/zh/cookbook#%E5%9C%BA%E6%99%AF-2%E4%B8%BB%E5%BA%94%E7%94%A8%E5%92%8C%E5%BE%AE%E5%BA%94%E7%94%A8%E9%83%A8%E7%BD%B2%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8-nginx-%E4%BB%A3%E7%90%86%E8%AE%BF%E9%97%AE

4、总结

在部署主应用和子应用时,遇到两个核心问题

1、主应用路由未加前缀,导致主应用转发到子应用时,脱离了qiankun框架直接访问子应用的静态资源,致使的结果是,无法再返回到主应用。

2、如果要求子应用接口都统一从主应用转发,那么子应用接口需要前缀进行区分。

3、最后,静态资源的问题,多半是子应用的 publicPath 配置有关。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com