vue配置qiankun及打包上线

news2024/11/19 21:28:57

项目结构

基座: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的校验,就没有这个报错了,不建议大家采取我的这个方法,如果大家有更好的方法可以给我留言。

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

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

相关文章

XUbuntu22.04之快速复制绝对路径(二百零五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Java项目:115SSM宿舍管理系统

博主主页&#xff1a;Java旅途 简介&#xff1a;分享计算机知识、学习路线、系统源码及教程 文末获取源码 一、项目介绍 宿舍管理系统基于SpringSpringMVCMybatis开发&#xff0c;系统主要功能如下&#xff1a; 学生管理班级管理宿舍管理卫生管理维修登记访客管理 二、技术框…

向量数据库:Milvus

特性 Milvus由Go(63.4%),Python(17.0%),C(16.6%),Shell(1.3%)等语言开发开发&#xff0c;支持python&#xff0c;go&#xff0c;java接口(C,Rust,c#等语言还在开发中)&#xff0c;支持单机、集群部署&#xff0c;支持CPU、GPU运算。Milvus 中的所有搜索和查询操作都在内存中执行…

Phi-2小语言模型QLoRA微调教程

前言 就在不久前&#xff0c;微软正式发布了一个 27 亿参数的语言模型——Phi-2。这是一种文本到文本的人工智能程序&#xff0c;具有出色的推理和语言理解能力。同时&#xff0c;微软研究院也在官方 X 平台上声称&#xff1a;“Phi-2 的性能优于其他现有的小型语言模型&#…

C# WPF 数据绑定

需求 后台变量发生改变&#xff0c;前端对应的相关属性值也发生改变 实现 接口 INotifyPropertyChanged 用于通知客户端&#xff08;通常绑定客户端&#xff09;属性值已更改。 示例 示例一 官方示例代码如下 using System; using System.Collections.Generic; using Sy…

IoT 物联网 MQTT 协议 5.0 版本新特性

MQTT 是一种基于发布/订阅模式的轻量级消息传输协议&#xff0c;专门为设备资源有限和低带宽、高延迟的不稳定网络环境的物联网场景应用而设计&#xff0c;可以用极少的代码为联网设备提供实时可靠的消息服务。MQTT 协议广泛应用于智能硬件、智慧城市、智慧农业、智慧医疗、新零…

Linux:linux计算机和windows计算机 之间 共享资源

在前面章节已经介绍过&#xff0c;NFS用于Linux系统之间的文件共享&#xff0c;windows 并不知道 NFS &#xff0c;而是使用 CIFS (Common Internet File System) 的协议机制 来 “共享” 文件。在1991年&#xff0c;Andrew Tridgell 通过逆向工程 实现了 CIFS 协议&#xff0c…

GAMES101-Assignment5

一、问题总览 在这次作业中&#xff0c;要实现两个部分&#xff1a;光线的生成和光线与三角的相交。本次代码框架的工作流程为&#xff1a; 从main 函数开始。我们定义场景的参数&#xff0c;添加物体&#xff08;球体或三角形&#xff09;到场景中&#xff0c;并设置其材质&…

【Cadence】sprobe的使用

实验目的&#xff1a;通过sprobe测试电路中某个节点的阻抗 这里通过sprobe测试输入阻抗&#xff0c;可以通过port来验证 设置如下&#xff1a; 说明&#xff1a;Z1代表sprobe往left看&#xff0c;Z2代表sprobe往right看 结果如下&#xff1a; 可以看到ZM1I0.Z2 顺便给出了I…

一篇文章了解做仿真软件的达索系统-达索代理商

达索系统是一家全球领先的仿真软件公司&#xff0c;致力于为客户提供创新和高效的解决方案。该公司的仿真软件被广泛应用于航空航天、汽车、能源、医疗等领域&#xff0c;为客户提供了强大的工程仿真能力。 达索系统的仿真软件具有多个特点&#xff0c;包括高精度、高效率、易用…

CSS 改变鼠标样式(大全)

使用方法&#xff1a; <span style"cursor:auto">Auto</span><span style"cursor:crosshair">Crosshair</span><span style"cursor:default">Default</span><span style"cursor:pointer">P…

高通平台开发系列讲解(USB篇)adb function代码分析

文章目录 一、FFS相关动态打印二、代码入口三、ffs_alloc_inst四、ep0、ep1&ep2的注册五、读写过程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本文主要介绍高通平台USB adb function代码f_fs.c。 一、FFS相关动态打印 目录:msm-4.14/drivers/usb/gadget/fun…

系统存储架构升级分享

一、业务背景 系统业务功能&#xff1a;系统内部进行数据处理及整合, 对外部系统提供结果数据的初始化(写)及查询数据结果服务。 系统网络架构: • 部署架构对切量上线的影响 - 内部管理系统上线对其他系统的读业务无影响 •分布式缓存可进行单独扩容, 与存储及查询功能升级…

蓝牙信标定位原理

定位原理&#xff1a;蓝牙信标的定位原理是基于RSSI蓝牙信号强度来做定位的。 根据应用场景不同&#xff0c;通过RSSI定位原理可分为两种定位方式 一、存在性定位 这种方式通常要求所需定位的区域安装一个蓝牙信标即可&#xff0c;手持终端扫描蓝牙信标信号&#xff0c;扫描…

U盘删除的文件不在回收站如何恢复?教你3个简单方法!

“我在清理u盘的时候误删了一些重要的文件&#xff0c;想将这些文件恢复时才发现它们不在回收站中了。还有办法恢复吗&#xff1f;” 在数字化时代&#xff0c;u盘的作用渐渐显现。很多用户会将重要的数据直接保存在u盘中。但在使用u盘的过程中&#xff0c;不可避免会有数据的丢…

渐变登录页

效果演示 实现了一个简单的登录页面的样式和交互效果。 Code <div class"flex"><div class"login color">Login</div><label class"color">Username :</label><input type"text" class"input&…

第二证券:如何判断主力是在洗盘还是出货?

怎样判别主力是在洗盘仍是出货&#xff1f; 1、依据股票成交量判别 在洗盘时&#xff0c;个股的成交量与前几个生意相比较&#xff0c;呈现缩量的状况&#xff0c;而出货其成交量与前几个生意日相比较呈现放量的走势。 2、依据股票筹码分布判别 洗盘首要是将一些散户起浮筹…

如何创建自己的小程序?零编程一键创建实战指南

当今瞬息万变的数字世界中&#xff0c;拥有一个属于自己的小程序已成为企业与个人展示、服务和互动的重要途径。无需编码知识&#xff0c;通过便捷的云端可视化平台&#xff0c;也可以轻松创建一款符合自身需求且功能丰富的小程序。下面给大家分享如何创建自己的小程序。 1、选…

K8S Secret 一文详解, 全面覆盖 Secret 使用场景 | 全家桶

博客原文 文章目录 Secret介绍Secret 类型kubectl 创建类型 Secret 使用Opaque 类型 Secret 的使用创建1. kubectl create2. yaml 挂载1. 作为环境变量2. 作为文件挂载及设置 POSIX 权限 Secret 绑定 serviceAccount查看 secret TLS Secretyaml 方式创建kubectl 创建 Docker 镜…

windows下全免费手动搭建php8+mysql8开发环境及可视化工具安装

最近PHP项目少了&#xff0c;一直在研究UE5和Golang&#xff0c;但是考虑到政府、国企未来几年国产化的要求&#xff0c;可能又要重拾PHP。于是近日把用了N年的框架重新更新至适合PHP8.2以上的版本&#xff0c;同时也乘着新装机&#xff0c;再次搭建php和mysql开发环境。本文留…