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

news2024/11/23 8:59:54

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" />
    <meta
      name="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 without
        JavaScript 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 support
    base: '',
    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 preload
    config.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#L171
        fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
        include: 'initial'
      }
    ]);

    // when there are many pages, it will cause too many meaningless requests
    config.plugins.delete('prefetch');

    // set svg-sprite-loader
    config.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 package
            priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
          },
          commons: {
            name: 'chunk-commons',
            test: resolve('src/components'), // can customize your rules
            minChunks: 3, //  minimum common number
            priority: 5,
            reuseExistingChunk: true
          }
        }
      });
      // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
      config.optimization.runtimeChunk('single');
    });
  }
};

3、主项目和子项目部署在同一台服务器上,其中主应用路由使用history模式,子应用路由使用hash模式,nginx 的配置如下:

locatoin / {
    root /opt/parent;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
}

location /bes-front/ {
    root /opt/parent;
    index index.html index.htm;
    try_files $uri $uri. /index.html;
}

注:使用的下面这种部署方式,主应用代码放在parent目录下,子应用代码放在parent目录下面,其他,子应用的目录应该代码中的名称保持一致,在本示例当中,子应用使用的是bes-front

官网参考链接: 入门教程 - qiankun

4、总结

在部署主应用和子应用时,遇到主应用转发到子应用时,静态资源无法访问的问题,重点是查看子应用publicPath这个配置,这个是静态文件的访问前缀,如果部署到服务器上,子应用的静态资源无法访问到,可以看一下服务器访问的静态资源的前缀是否和代码中配置的一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2202978.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

颠覆传统!团购新玩法带你零风险狂赚社交红利

你是否曾经被某个看似大胆且充满挑战的商业策略深深吸引&#xff0c;最终却惊喜地发现它在短时间内创造了惊人的价值&#xff1f;今天&#xff0c;我们将一起探索一个别出心裁的商业模式&#xff0c;看看它是如何在短短一个月内实现超过600万的利润奇迹。这不仅仅是一次对商业机…

第十一章:规划过程组 (11.1制定项目管理计划--11.5创建WBS)

11.1 制定项目管理计划 • 项目管理计划可以是概括或详细的&#xff0c;每个组成部分的详细程度取决于具体项目的要求 • 项目管理计划应基准化&#xff0c;即至少应规定项目的范围、时间和成本方面的基准以便据此考核项目执行情况和管理项目绩效。 • 在确定基准之前&#xf…

前端开发攻略---分块加载大数据

一、问题 解决当遇到较大的数据请求&#xff0c;当用户网络较差的时候&#xff0c;需要等很久很久才能拿到服务器的响应结果&#xff0c;如果这个响应结果需要再页面上展示的话&#xff0c;会导致页面长时间白屏的问题 二、实现原理 当发送一个请求时&#xff0c;需要等服务器把…

UM-Net: 重新思考用于息肉分割的ICGNet,结合不确定性建模|文献速递-基于多模态-半监督深度学习的病理学诊断与病灶分割

Title 题目 UM-Net: Rethinking ICGNet for polyp segmentation with uncertainty modeling UM-Net: 重新思考用于息肉分割的ICGNet&#xff0c;结合不确定性建模 01 文献速递介绍 结直肠癌&#xff08;CRC&#xff09;是男性中第三大、女性中第二大常见的恶性肿瘤&#x…

python+pytest+request 接口自动化测试

一、环境配置 1.安装python3 brew update brew install pyenv 然后在 .bash_profile 文件中添加 eval “$(pyenv init -)” pyenv install 3.5.3 -v pyenv rehash 安装完成后&#xff0c;更新数据库 pyenv versions 查看目前系统已安装的 Python 版本 pyenv global 3.5…

[实用工具]Docker安装nextcloud实现私有云服务和onlyoffice

Nextcloud是一款开源的云存储和协作平台&#xff0c;允许用户在自己的服务器上存储和访问文件&#xff0c;同时提供强大的协作工具。它可以替代商业云存储服务&#xff0c;让用户拥有完全控制和自主管理自己的数据。 Nextcloud支持文件上传和下载&#xff0c;可以通过Web界面、…

Android实现RecyclerView宽度变化动画

效果图 实现思路就是定义一个属性动画&#xff0c;在动画监听器中不断修改RecyclerView的宽度 valueAnimator ValueAnimator.ofInt(begin, recyclerView.getWidth() * 2);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {Overridepublic void …

EasyAnimate

https://github.com/aigc-apps/EasyAnimate/blob/main/README_zh-CN.mdhttps://github.com/aigc-apps/EasyAnimate/blob/main/README_zh-CN.md EasyAnimate v4是一个用于生成高分辨率和长视频的端到端解决方案。我们可以训练基于转换器的扩散生成器,训练用于处理长视频的VAE,…

python35_控制台简单计算年薪

控制台简单计算年薪 def calculate_annual_salary(monthly_salaries):"""计算年薪。参数:monthly_salaries: list of float&#xff0c;每个月的工资列表。返回值:float&#xff0c;用户的年薪。"""annual_salary sum(monthly_salaries)return…

论文作者署名排序是怎么界定的?

人人都想在论文的作者名单中占个位子&#xff0c;特别是一作和通讯作者&#xff0c;我也经常会收到一些人的哭诉&#xff0c;说自己明明做了大部分的工作&#xff0c;但却让别人的名字挂在第一作者。 在厘清一作与通讯作者的意义之前&#xff0c;我们先来看看谁可以署名。目前国…

经典蓝牙BLE版本区别:【图文讲解】

蓝牙是一种短距的无线通讯技术&#xff0c;可实现固定设备、移动设备之间的数据交换。一般将蓝牙3.0之前的BR/EDR蓝牙称为传统蓝牙&#xff0c;而将蓝牙4.0规范下的LE蓝牙称为低功耗蓝牙&#xff08;BLE&#xff09;。 1&#xff1a;蓝牙4.0 BLE 4.0版本是3.0版本的升级版本&a…

MySQL 初探:从基础到优化

什么是 MySQL&#xff1f; MySQL 是一个开源的关系型数据库管理系统 (RDBMS)&#xff0c;使用结构化查询语言 (SQL) 进行数据管理。作为最流行的数据库之一&#xff0c;MySQL 被广泛应用于各类网站和应用中&#xff0c;从小型应用到大型复杂系统。 MySQL 的特点 开源免费&am…

antdv树形表格 大量tooltip等组件导致页面卡顿问题优化

vue3、ant-design-vue 4.2.3 遇到的问题&#xff1a;页面中有个展示树形数据的表格&#xff0c;默认需要全部展开&#xff0c;有一组数据量较大时页面首次渲染时非常卡顿&#xff0c;发现每次都大概用了7、8秒才完成渲染。表格展开的数据大概300条数据&#xff0c;操作列中有5…

SpringBoot框架下的服装生产管理系统

1 绪论 1.1 研究背景 当今时代是飞速发展的信息时代。在各行各业中离不开信息处理&#xff0c;这正是计算机被广泛应用于信息管理系统的环境。计算机的最大好处在于利用它能够进行信息管理。使用计算机进行信息控制&#xff0c;不仅提高了工作效率&#xff0c;而且大大的提高…

leetcode:反转字符串中的单词III

题目链接 string reverse(string s1) {string s2;string::reverse_iterator rit s1.rbegin();while (rit ! s1.rend()){s2 *rit;rit;}return s2; } class Solution { public:string reverseWords(string s) {string s1; int i 0; int j 0; int length s.length(); for (i …

2024年【金属非金属矿山(地下矿山)安全管理人员】复审考试及金属非金属矿山(地下矿山)安全管理人员在线考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员复审考试考前必练&#xff01;安全生产模拟考试一点通每个月更新金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员在线考试题目及答案&#…

防汛可视化系统:提升应急响应能力

通过图扑可视化系统实时监测水情、雨情和地理数据&#xff0c;辅助防汛决策与调度&#xff0c;提供直观的风险预警信息&#xff0c;从而优化资源分配&#xff0c;提高防汛应急响应效率。

进程通讯方式区别(从不同角度看)

*常用到的不同主机间进程通讯&#xff1a;Socket。比如&#xff1a;host和引擎间socket指令通讯、分派和复判之间指令通讯&#xff1b; *共享内存&#xff1a;在Windows系统中&#xff0c;共享内存的实现通常有以下几种方式&#xff1a; 1.内存映射文件(最常用)&#xff1a;(…

linux上的smb共享文件夹

需求描述 公司的打印机使用扫描功能的时候&#xff0c;需要发送大量文件。然鹅公司的电脑都是加入了AzureAD的&#xff0c;不能在公司电脑上简单设置共享。好在公司有很多阿里云上的服务器&#xff0c;Linux和Windows的都有&#xff0c;所以就来尝试用阿里云的服务器来进行smb…

正点原子学习笔记之汇编LED驱动实验

1 汇编LED原理分析 为什么要写汇编     需要用汇编初始化一些SOC外设     使用汇编初始化DDR、I.MX6U不需要     设置sp指针&#xff0c;一般指向DDR&#xff0c;设置好C语言运行环境 1.1 LED硬件分析 可以看到LED灯一端接高电平&#xff0c;一端连接了GPIO_3上面…