vue配置qiankun及打包上线

项目结构

基座:vue3

子应用A:vue3

子应用B: react

子应用C:vue3+vite

项目目录:

配置基座

首先下载qiankun yarn add qiankun # 或者 npm i qiankun -S 所有子应用也要安装,vue-vite项目安装 cnpm install vite-plugin-qiankun

 设置main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { registerMicroApps, start } from 'qiankun';

createApp(App).use(store).use(router).mount('#app')
registerMicroApps([{
    name: 'vueapp',
    entry: '//localhost:3001', // 配置子应用的服务
    container: '#qiankunid',   // 子服务渲染的dom
    activeRule: '/vue/',       // 路由对应的子服务
}, {
    name: 'reactapp',
    entry: '//localhost:3000',
    container: '#qiankunid',
    activeRule: '/react/',

}, {
    name: 'vuevite',
    entry: '//localhost:3002',
    container: '#qiankunid',
    activeRule: '/vuevite/',
}], {
    beforeLoad: [async() => console.log("befor load")],
    beforeMount: [async() => console.log("beforeMount ")],
    afterMount: [async() => console.log("afterMount ")],
});

// 启动 qiankun
start();

App.vue

<template>
    <div class="main">
        <div class="mainLeft">
            <router-link class="meunLi" to="/">首页</router-link>
            <router-link class="meunLi" to="/vue/">vue</router-link>
            <router-link class="meunLi" to="/react/">react</router-link>
            <router-link class="meunLi" to="/vuevite/">vue-vite</router-link>
        </div>
        <div class="mainRight">
            <router-view />
            <div id="qiankunid"></div>
        </div>
    </div>
</template>

<style scoped lang="less">
.main {
    width: 100vw;
    height: 100vh;
    display: flex;
    .mainLeft {
        width: 200px;
        height: 100vh;
    }
    .mainRight {
        flex: 1;
        height: 100vh;
        background: #f2f2f2;
    }

    .meunLi {
        width: 100%;
        height: 40px;
        line-height: 40px;
        padding: 0 20px;
        cursor: pointer;
        display: block;
        border-bottom: 1px solid #ddd;
    }
}
</style>

vue3子应用

配置vue.config.js

const { defineConfig } = require('@vue/cli-service')
const { name } = require('./package');

console.log(name)
module.exports = defineConfig({
    transpileDependencies: true,
    lintOnSave: false,
    devServer: {
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
        //设置代理
        hot: true,
        port: "3001",
        open: true,

    },
    configureWebpack: {
        output: {
            library: name,
            libraryTarget: 'umd', // 把微应用打包成 umd 库格式
            chunkLoadingGlobal: `webpackJsonp_${name}`,
        },
    },
})

配置main.js

import './public-path';
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

let app
    // createApp(App).use(store).use(router).mount('#vue-app')
function render(props = {}) {
    const { container } = props;
    app = createApp(App)
    // 这里为了防止冲突 id修改了
    app.use(store).use(router).mount('#vue-app')

}

// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
    render();
}

export async function bootstrap() {
    console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
    console.log('mount', props);
    render(props);
}
export async function unmount() {

    app.unmount();
}

src下新增public-path.js

if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

配置路由

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const routes = [{
        path: '/',
        name: 'home',
        component: HomeView
    },
    {
        path: '/about',
        name: 'about',
        // route level code-splitting
        // this generates a separate chunk (about.[hash].js) for this route
        // which is lazy-loaded when the route is visited.
        component: () =>
            import ( /* webpackChunkName: "about" */ '../views/AboutView.vue')
    }
]
console.log(window.__POWERED_BY_QIANKUN__)
const router = createRouter({
    history: createWebHistory(window.__POWERED_BY_QIANKUN__ ? "/vue/" : "/"),
    routes
})

export default router

vue-vite子应用

vite下载qiankun 用cnpm install vite-plugin-qiankun

配置vite.config.js 

import {
    defineConfig
} from 'vite'
import vue from '@vitejs/plugin-vue'

import qiankun from "vite-plugin-qiankun"

export default defineConfig({
    base: "http://localhost:3002/",
    plugins: [vue(), qiankun("vuevite", { // 配置qiankun插件
        useDevMode: true
    })],
    server: {
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
        port: '3002',
        cors: true,
        origin: "http://localhost:3002"
    },
   
    
})

  src下新增public-path.js

if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

配置main.js

import './public-path';
import {
    createApp
} from 'vue'
import router from "./router/index";

import {
    renderWithQiankun,
    qiankunWindow
} from 'vite-plugin-qiankun/dist/helper'
import App from './App.vue'

let app

if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
    app = createApp(App)
    app.use(router)
    app.mount('#vue-vite')
} else {
    renderWithQiankun({
        mount(props) {
            console.log('--mount');
            const { container } = props;
            app = createApp(App);
            app.use(router)
            app.mount(document.getElementById('vue-vite'));
        },
        bootstrap() {
            console.log('--bootstrap');
        },
        update() {
            console.log('--update');
        },
        unmount() {
            console.log('--unmount');
            app.unmount();
        }
    });
}

配置路由

import {
    createRouter,
    createWebHistory
} from 'vue-router'

const routes = [{
        path: '/',
        name: '3v',
        component: () =>
            import ('@/components/3v.vue'),

    }
]
console.log(window.__POWERED_BY_QIANKUN__)
const router = createRouter({
    history: createWebHistory("/vuevite/"),
    routes
})

export default router

react子应用

  src下新增public-path.js

if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

 配置index.js

import "./public-path.js"
import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Routes, Route } from "react-router-dom";

import App from "./App.js";


let root;

function render(props) {
    const { container } = props;
    const dom = document.getElementById("root")
    root = createRoot(dom)
    root.render( <BrowserRouter basename = {
            window.__POWERED_BY_QIANKUN__ ? '/react' : '/'
        }> <App/> </BrowserRouter> );


    }
    if (!window.__POWERED_BY_QIANKUN__) {
        render({});
    }

    export async function bootstrap() {
        console.log('[react16] react app bootstraped');
    }

    export async function mount(props) {
        console.log('[react16] props from main framework', props);
        render(props);
    }

    export async function unmount(props) {
        const { container } = props;
        root.unmount()
    }

配置config-overrides.js

为了不暴露所有的webpack配置,我们用 react-app-rewired 来配置webpack,下载 cnpm i react-app-rewired, 然后修改package.json的启动方法

然后根目录新增config-overrides.js文件

const { name } = require('./package');

module.exports = {
    webpack: (config) => {
        config.output.library = `${name}`;
        config.output.libraryTarget = 'umd';
        config.output.chunkLoadingGlobal = `webpackJsonp_${name}`;
        config.output.globalObject = 'window';

        return config;
    },

    devServer: (_) => {
        const config = _;

        config.headers = {
            'Access-Control-Allow-Origin': '*',
        };
        config.historyApiFallback = true;
        config.hot = false;
        config.watchContentBase = false;
        config.liveReload = false;

        return config;
    },
};

打包上线 

这里用的nginx代理,下面是nginx配置


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    # 开启gzip 功能
    #gzip  on;
    # gzip_static on
    # 基座
    server {
        listen       8084;
        server_name  localhost;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            root   html;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html; 
        }
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
    # react
    server {
        default_type 'text/html';
        charset utf-8;
        listen       3000;
        server_name  localhost;
        # client_header_buffer_size 128k;
        # large_client_header_buffers 4 128k;
        # add_header Set-Cookie loginSessionHttps;
        port_in_redirect off; #防止跳转的时候带了端口号,会导致404
        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        location / {
            root   appreact; #指定访问跟路径文件夹为app1
            index  index.html index.htm;
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
            try_files $uri $uri/ /index.html;
        }


    }
    # vue3
    server {
        default_type 'text/html';
        charset utf-8;
        listen       3001;
        server_name  localhost;
        # client_header_buffer_size 128k;
        # large_client_header_buffers 4 128k;
        # add_header Set-Cookie loginSessionHttps;
        port_in_redirect off; #防止跳转的时候带了端口号,会导致404
        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        location / {
            root   appvue3;
            index  index.html index.htm;
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
            try_files $uri $uri/ /index.html;
        }
    }

    # vite
    server {
        default_type 'text/html';
        charset utf-8;
        listen       3002;
        server_name  localhost;
        # client_header_buffer_size 128k;
        # large_client_header_buffers 4 128k;
        # add_header Set-Cookie loginSessionHttps;
        port_in_redirect off; #防止跳转的时候带了端口号,会导致404
        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        location / {
            root   appvite; 
            index  index.html index.htm;
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
            try_files $uri $uri/ /index.html;
        }


    }
    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

遇到的问题

问题一:找到不子应用

导致这样的问题有很多,我这里只写了我是怎么解决的

原因1:vue.config.js中 devServer需要加headers,这个是主应用获取子应用时候的跨域响应头

原因2:  子项目没有暴露出qiankun的生命周期 bootstrap mount unmount,包括vite的vite.config.js的配置也要暴露出去。

原因3:  在配置vite.config.js时,要配置base和plugins属性,base属性路径配置的不对,可能和版本有关系,有的是可以成功的。

原因4:  子项目没有启动

问题二:configuration has an unknown property ‘jsonpFunction‘

vue2 用jsonpFunction vue3 用chunkLoadingGlobal

 问题三:全局 __webpack_public_path__  报错

这个是eslint校验 报错,百度给出解决办法是在 package.json里添加全局变量

但是发现没有用,意思我这里直接关闭了 eslint的校验,就没有这个报错了,不建议大家采取我的这个方法,如果大家有更好的方法可以给我留言。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【shell】读取表格文件的数据

碎碎念 shell在处理复杂问题的时候不具备优势&#xff0c;如果业务环境能够使用python的话用python又简单又好用&#xff0c;但是很多云平台的现场可能需要shell脚本文件&#xff08;还好是要求bash&#xff09; 但是现在有一个业务场景就是运维人员会把参数写在excel表格中 …

不同光照下HUD抬头显示器光干扰试验用太阳光模拟器

HUD干扰太阳光模拟器是机载光电系统测试中常见的问题之一。在机载光电系统测试中&#xff0c;太阳光模拟器是一种重要的测试设备&#xff0c;它可以模拟不同光照条件下的机载光电系统性能&#xff0c;为系统优化和调试提供数据支持。然而&#xff0c;当太阳光模拟器与HUD交叉作…

Python之列表中常见的方法

1.创建一个列表 list1 [1, 2, 3, 4] list2 list("1234") print(list1, list2) print(list1 list2) # 以上创建的两个列表是等价的,都是[1, 2, 3, 4] 2.添加新元素 # 末尾追加 a [1, 2, 3, 4, 5] a.append(6) print(a)# 指定位置的前面插入一个元素 a.insert(2, 1…

Java泛型的继承和通配符

泛型的继承和通配符 继承 两个容器所容纳的类类型是有子类父类的关系的 但是容器之间没有 反证法&#xff1a; 假设做法成立 ArrayList<Object> list1 null;ArrayList<String> list2 - new ArrayList<>();list1list2 list 指向list2的容器实例 list1.add&…

积极参与建设“一带一路”,川宁生物与微构工场达成战略合作

2024年1月12日&#xff0c;北京微构工场生物技术有限公司&#xff08;以下简称“微构工场”&#xff09;与伊犁川宁生物技术股份有限公司&#xff08;“川宁生物”&#xff09;宣布签订战略合作协议&#xff0c;双方将共同出资设立合资公司&#xff0c;加速生物制造产业化落地&…

第N1周:one-hot编码案例

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/rbOOmire8OocQ90QM78DRA) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制](https://mtyjkh.blog.csdn.net/)** 1.one-hot编码概念 想…

误删除文件的恢复

记一次误删除文件&#xff0c;恢复过程 ubuntu系统 vscode 写代码 *rm -r * 删除整个目录git 提交代码的时候&#xff0c;删除无用的build目录&#xff0c;错误操作把上一级目录整个删除了。。。 恢复过程 求助同事大佬 “使用rm -r 删除的东西&#xff0c;不经过回收站&…

远距离相位激光测距传感PHR系列性能及通信接口说明

远距离相位激光测距传感PHR系列包含PHR-120100&#xff08;测距120米&#xff09;、PHR-200100&#xff08;测距200米&#xff09;&#xff0c;广泛适用于隧道检测, 堆垛机定位, 行车定位, 工业窑车定位, 智能物流, 高位拣货车定位, AGV避障, 轮渡减震胎定位, 窑车测距, 炼钢厂…

mybatis基本注解、增删改查、结果集映射、一对一、一对多

mybatis注解 基本注解新增删除修改查询 结果映射注解Results结果映射一对一映射一对多映射 基本注解 新增 功能&#xff1a;Insert完成新增操作&#xff0c;类似配置文件的 元素&#xff1b; 说明&#xff1a;新增时所用的参数取值是接口方法的入参&#xff0c;可以是对象&a…

burp靶场-path traversal

路径遍历 1.路径遍历漏洞 ### 什么是路径遍历 路径遍历也称为目录遍历。这些漏洞使攻击者能够读取正在运行应用程序的服务器上的任意文件。这可能包括&#xff1a; 应用程序代码和数据。 后端系统的凭据。 敏感的操作系统文件。### <img src"/loadImage?filename218…

RDMA编程实践-SEND-RECEICVE原语应用

RDMA编程实践 本文描述了RDMA编程过程中的SEND-RECEIVE双边原语的代码实现。包含多个版本&#xff0c;1、client向server发送消息&#xff0c;server回复client收到消息(ACK)&#xff0c;然后两边断开连接。2、server端循环等待客户端建立连接&#xff0c;client发送一次消息后…

数据库和表的操作

文章目录 前言一、库的操作创建数据库字符集和校验规则操纵数据库查看数据库显示创建语句修改数据库删除数据库备份和恢复数据库还原查看连接情况 二、表的操作创建表查看表结构修改表修改表名添加一列修改某一列属性删除某一列 删除表 前言 一、库的操作 创建数据库 语法&am…

新手必看:腾讯云服务器购买详细图文教程

腾讯云服务器购买流程很简单&#xff0c;有两种购买方式&#xff0c;直接在官方活动上购买比较划算&#xff0c;在云服务器CVM或轻量应用服务器页面自定义购买价格比较贵&#xff0c;但是自定义购买云服务器CPU内存带宽配置选择范围广&#xff0c;活动上购买只能选择固定的活动…

我的NPI项目之设备系统启动(三) -- CDT的一个实例

上面说了这么多&#xff0c;这里就添加一个CDT的使用实例和简单的代码解析。 首先生成cdt_configure.xml配置文件&#xff0c;然后执行如下命令&#xff1a; python cdt_generator.py cdt_configure.xml CDT.bin; 就可以生成对应的CDT.bin文件。同时也会生成, 我们会利用ha…

STM32串口485通信如何控制收发管脚

要有效的控制485的收发管脚&#xff0c;首先要知道485通信发送命令完成的时间&#xff0c;我们执行发送命令结束并不代表硬件已经把数据发出去了&#xff0c;可能1ms以后才真正完成&#xff0c;如果我们控制管脚不当&#xff0c;可能导致数据不能完全发出去。导致串口通信异常。…

Leetcode20-唯一摩尔斯密码词(804)

1、题目 国际摩尔斯密码定义一种标准编码方式&#xff0c;将每个字母对应于一个由一系列点和短线组成的字符串&#xff0c; 比如: ‘a’ 对应 “.-” &#xff0c; ‘b’ 对应 “-…” &#xff0c; ‘c’ 对应 “-.-.” &#xff0c;以此类推。 为了方便&#xff0c;所有 26…

深度学习记录--Train/dev/test sets

为什么需要训练集、验证集(简单交叉验证集)和测试集&#xff1f; 为了创建高效的神经网络&#xff0c;需要不断进行训练(迭代) 一个神经网络的产生 从最开始的想法idea开始&#xff0c;然后付诸于代码code&#xff0c;根据结果验证反过来对一开始的想法idea进行修正&#xf…

LeetCode 429. N 叉树的层序遍历

429. N 叉树的层序遍历 给定一个 N 叉树&#xff0c;返回其节点值的层序遍历。&#xff08;即从左到右&#xff0c;逐层遍历&#xff09;。 树的序列化输入是用层序遍历&#xff0c;每组子节点都由 null 值分隔&#xff08;参见示例&#xff09;。 示例 1&#xff1a; 输入&…

商业世界,从2023到2024

作者&#xff5c;潮汐商业评论 编辑&#xff5c;Ray 变化总在发生&#xff0c;你不去迎接进步的变化&#xff0c;就会等到退步的变化。 —— 查理.芒格 2023, 我们似乎总在不断告别。从“一生自由”的大家黄永玉到“智慧”投资家查理.芒格&#xff0c;再到写出《不能承受的生命…

利用fd子系统实现图案与图片显示方法

//第一&#xff1a;利用fb子系统画圆的方法与实现 //1、头文件信息 #include <sys/ioctl.h> #include <linux/fb.h> #include <stdio.h> #include <sys/types.h> #include <stdio.h> #include <sys/mman.h> #include <sys/types.h>…