添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
微前端的概念是从后端的微服务中迁移过来的。将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立运行、独立开发、独立部署

qiankun 是阿里巴巴基于 single-spa 实现的微前端库,是一个开放式微前端架构,支持当前三大前端框架甚至 jq 等其他项目无缝接入。

微前端待解决的问题

  • [x] 微前端主应用与子应用如何构建
  • [x] 主应用资源下发给子应用
  • [x] 各应用间动态通信,实时监听,同步数据
  • [x] 微前端线上部署

微前端主应用与子应用如何构建

构建主应用

  1. 通过 vue-cli 构建一个主应用工程,安装微前端依赖 qiankun yarn add qiankun npm i qiankun
  2. 改造 main.js
// 引入依赖
import Vue from 'vue';
import App from './App.vue';
import store from './store';
import router from './router';
import { i18n } from './plugin';
import {
    registerMicroApps, // 注册子应用
    runAfterFirstMounted, // 第一个子应用加载完毕
    setDefaultMountApp, // 设置默认子应用
    start, // 微服务启动
} from 'qiankun';
// 公共依赖挂载在window上,目的是传递给子应用
window.vue = Vue;
// 渲染主应用, #container为主应用根元素
new Vue({
    i18n,
    store,
    router,
    render: h => h(App)
}).$mount('#container');
 * 路由监听
 * @param {string} routerPrefix 前缀
const genActiveRule = (routerPrefix: string) => {
    return (location: Location) => location.pathname.startsWith(routerPrefix);
// 构建子应用, #micro-app为子应用容器
let microApps = [
        name: 'qiankun-test1',
        entry: '//localhost:7001',
        container: '#micro-app',
        activeRule: genActiveRule('/test1')
        name: 'vue-test2',
        entry: '//localhost:7002',
        container: '#micro-app',
        activeRule: genActiveRule('/test2')
// 注册子应用
registerMicroApps(microApps, {
    // 挂载前回调
    beforeLoad: [
        app => {
            console.log('before load', app);
    // 挂载后回调
    beforeMount: [
        app => {
            console.log('before mount', app);
    // 卸载后回调
    afterUnmount: [
        app => {
            console.log('after unload', app);
// 设置默认子应用,参数genActiveRule('/test1')函数内的参数一致
setDefaultMountApp('/test1');
// 第一个子应用加载完毕回调
runAfterFirstMounted(() => {});
// 启动微服务
start();
  App.vue 中,增加一个渲染子应用的容器 
  
<template>
    <div id="root" class="container">
        <header class="header">header</div>
        <!-- 子应用容器 -->
        <div id="micro-app"></div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
@Component({
    name: 'Root'
export default class Root extends Vue {
</script>
vue.config.js
const port = 7000;
module.exports = {
    // publicPath: process.env.VUE_APP_ROOT_PATH || '/',
    devServer: {
        hot: true,
        port,
        disableHostCheck: true,
        headers: {
            'Access-Control-Allow-Origin': '*'
 

注意 主应用设置 publicPath: '/' 会造成子应用配置的 publicPath 失效,导致无限循环刷新页面。

构建子应用

  1. 通过 vue-cli 构建一个子应用工程
  2. 改造 main.js
import VueRouter from 'vue-router';
import App from './App.vue';
import store from './store';
import routes from './router';
import { i18n } from './plugin';
Vue.config.productionTip = false;
// 声明变量管理vue及路由实例
let router = null;
let instance = null;
const __qiankun__ = window.__POWERED_BY_QIANKUN__;
if (window.__POWERED_BY_QIANKUN__) {
    // eslint-disable-next-line
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
// 导出子应用生命周期 挂载前
export async function bootstrap(props) {
    console.log(props)
// 导出子应用生命周期 挂载后
export async function mount(props) {
    // 实例化router
    router = new VueRouter({
        base:  '/', // 也可写子应用路径
        mode: 'history',
        routes // 通过主应用传递的props来获取,可实现动态路由
    // 实例化子应用
    instance = new Vue({
        i18n,
        store,
        router,
        render: h => h(App)
    }).$mount('#app');
// 导出子应用生命周期 卸载后
export async function unmount() {
    instance.$destroy();
    instance = null;
    router = null;
// 单独开发环境
__qiankun__ || mount();
   修改 router.js 中 
  
import { RouteConfig } from 'vue-router';
import Home from '@/views/Home.vue';
const routes: Array<RouteConfig> = [
    path: '/',
    name: 'home',
    component: Home
    path: '/about',
    name: 'about',
    component: () => import('@/views/About.vue')
export default routes;
 

注意:这里导出的是路由数组,而不是 rouer 实例

vue.config.js
const { name } = require('./package');
const path = require('path');
function resolve(dir) {
    return path.resolve(__dirname, dir);
const port = 7001;
const isDev = process.env.NODE_ENV === 'development';
module.exports = {
    publicPath: isDev ? `//localhost:${port}` : '/',
    // 自定义webpack配置
    configureWebpack: config => {
        config.output.library = `${name}-[name]`;
        config.output.libraryTarget = 'umd';
        config.output.jsonpFunction = `webpackJsonp_${name}`;
        // 排除依赖项,不打包vue
        config.externals = {
            vue: 'vue'
    // 对内部的 webpack 配置(比如修改、增加Loader选项)(链式操作)
    chainWebpack: config => {
        // 配置依赖别名
        config.resolve.alias
            .set('vue', resolve('src/config/window/vue'));
    devServer: {
        port,
        hot: true,
        disableHostCheck: true,
        // 开发环境需要配置,解决跨越
        headers: {
            'Access-Control-Allow-Origin': '*'
  src/config/window/vue.ts, 引入 
  window上的 
  vue并导出 
  
const vue = window.vue;
export default vue;
 

主应用资源下发给子应用

实际项目中,父子应用之间会公用一些方法,组件。可以把公共的方法和组件放在主应用中,下发到子应用以供使用

main.js
import CustomComponent from '@/components/custom';
import storage from '@/utils/storage';
import filters from '@/utils/filters';
import * as directives from '@/utils/directives';
// 定义传入子应用的数据
const msg = {
    storage,
    filters,
    directives,
    CustomComponent
// 注册子应用
registerMicroApps([
        name: 'qiankun-test1',
        entry: '//localhost:7001',
        container: '#micro-app',
        activeRule: genActiveRule('/test1'),
        props: msg
  main.js 接受 
  props 
  
export async function bootstrap({ storage, filters, directives, CustomComponent }) {
    // 子应用全局挂载storage
    Vue.prototype.$storage = storage;
    // 注册全局过滤器
    for (const key in filters) {
        Vue.filter(key, (...args: Array<unknown>) => {
            return filters[key](...args);
    // 挂载全局指令
    Object.keys(directives).forEach(key => {
        Vue.directive(key, (directives as { [key: string]: DirectiveOptions })[key]);
    // 注册主应用下发的组件
    Vue.use(CustomComponent);
 

各应用间动态通信, 实时监听, 同步数据

qiankun 官方也提供了 api 去解决这个问题,不过使用起来不是很方便,我使用的是 rxjs 去解决应用间通信的需求
  1. 主应用中安装并引入 rxjs,并实例化
import { Subject } from 'rxjs';
const pager = new Subject();
// 在主应用注册呼机监听器,监听来自其他应用的广播
pager.subscribe(v => {
    console.log(v);
export default pager;
 
  1. 然后在主应用 main.js 中引入呼机,将呼机下发给子应用
import pager from '@/util/pager';
// 注册子应用
registerMicroApps(
          name: 'qiankun-test1',
          entry: '//localhost:7001',
          container: '#micro-app',
          activeRule: genActiveRule('/test1'),
          props: { pager } // 将pager传递给子应用
 
  1. 在子应用中注册呼机
export async function bootstrap({ pager }) {
    // 子应用注册呼机, 监听其他应用的广播
    pager.subscribe((v) => {
        console.log(v);
    // 将呼机挂载在vue实例
    Vue.prototype.$pager = pager;
 
  1. 在各应用中使用呼机动态传递信息
// 在某个应用里调用.next方法呼叫其他应用
this.$pager.next({
    from: 'qiankun-test1',
    data: 'test1 呼叫其他菜鸡'
 

微前端线上部署

以上做了这么多,能够部署到服务器上才算成功。我这里用的是 nginx
server {
    listen          7000;
    server_name     localhost;
    location / {
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
        root /Users/sunweijie/qiankun-app/master/dist/;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
server {
    listen          7001;
    server_name     localhost;
    root            /Users/sunweijie/qiankun-app/subapp-rights/dist/;
    location / {
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
        try_files $uri $uri/ /index.html;
server {
    listen          7002;
    server_name     localhost;
    root            /Users/sunweijie/qiankun-app/subapp-common/dist/;
    location / {
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
        try_files $uri $uri/ /index.html;
   我这里把关键性的几个要点给列举了下,在真正的实践过程中还是会踩到不少坑的,欢迎大家一起来入坑 附上 github 的工程地址:qiankun-container,顺手给楼主点个 star 吧 
                    微前端的概念是从后端的微服务中迁移过来的。将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立运行、独立开发、独立部署qiankun 是阿里巴巴基于 single-spa 实现的微前端库,是一个开放式微前端架构,支持当前三大前端框架甚至 jq 等其他项目无缝接入。微前端待解决的问题[x] 微前端主应用与子应用如何构建[x] 主应用资源下发给子应用[x] 各...
				
Vite + Vue3 + ts 注册登录页面书写 搭配Nodejs + Express + postgresql接口 预览:http://dongnan185.com:8083/videos/vue3.mp4 一共两个包: 一个接口包 连的本地postgresql 表及信息有截图 库自己装 一个vue包 vite+vue3+ts+eleplus 配置了router vuex axios postcss-px-to-viewport界面自适应 env prod环境等 启动:均是 npm i npm start 仅供学习哈 也在慢慢完善中
vue3+ts+vuerouter+pinia+elementplus+ts环境模板搭建及vite打包优化vue3+ts+vuerouter+pinia+elementplus+ts环境模板搭建及vite打包优化vue3+ts+vuerouter+pinia+elementplus+ts环境模板搭建及vite打包优化vue3+ts+vuerouter+pinia+elementplus+ts环境模板搭建及vite打包优化vue3+ts+vuerouter+pinia+elementplus+ts环境模板搭建及vite打包优化vue3+ts+vuerouter+pinia+elementplus+ts环境模板搭建及vite打包优化vue3+ts+vuerouter+pinia+elementplus+ts环境模板搭建及vite打包优化vue3+ts+vuerouter+pinia+elementplus+ts环境模板搭建及vite打包优化vue3+ts+vuerouter+pinia+elementplus+ts环境模板搭建及vite打包优化vue3+ts+vuerouter+pinia
Vue(2.x)老项目由js转换ts指南 其实在网上有不少关于,vue迁入ts的教程,但是很多并不完善,故做此篇 本项目基于 vue-admin-template进行改造 ,它是有ts版本的,因此本文章讨论的是老项目,由vue-cli构建的迁移 如果你的项目是由vue-cli构建的那么转换项目并不需要手动去添加各种配置文件等,因为vue-cli有内置的ts迁入命令进入项目 vue add typescript 如果使用git管理代码,请先保证工作区clear,输入完命令后,终端会自动为你安装 @vue/cl
最近公司有一个需求,需要在项目里面嵌套h5的页面,而且不止有一个嵌套的页面,那么就想办法运用webpack的多入口多出口的打包模式,网上查了很多资料,也有多入口多出口的案例,github上也有相应源码,我就不做过多讲解了。这里把博客贴出来vue多入口多出口打包,相应的多入口多出口的源码在 这里 。使用的是vue2.x + webpack3.x集成的多入口多出口,感兴趣的小伙伴可以看看。 然而,公司领导要求项目里面集成ts进行开发,对于字段的类型有更好的控制,所以在配合多入口多出口的前提下,还要配合ts进一步做一些调整。我本人开发路子可能前期走的野,反而加上tslint之后,被一堆类型检查,语法
关于vue3,vite和ts如何使用websocket,请遵循以下步骤: 1. 首先,您需要安装 `vue3`, `vite` 和 `websocket`。您可以使用以下命令安装它们: npm install vue@next vite typescript --save-dev npm install ws --save 2. 在您的Vue应用程序中,创建一个WebSocket连接。例如,您可以在Vue组件中使用以下代码: ```typescript import { defineComponent } from 'vue' import WebSocket from 'ws' export default defineComponent({ data () { return { socket: null, message: '' mounted () { this.socket = new WebSocket('ws://localhost:3000') this.socket.onmessage = (event) => { this.message = event.data methods: { sendMessage: function () { this.socket.send(this.message) 3. 在上述代码中,我们使用 `data()` 方法创建了一个变量 `socket` 用于存储WebSocket连接对象,以及变量 `message` 用于存储要发送的消息。 4. 在 `mounted()` 方法中,我们创建了一个WebSocket连接,并将其赋值给 `socket` 变量。 5. 接下来,我们使用 `onmessage` 方法在收到消息时更新 `message` 变量的内容。这个方法将在我们收到来自服务端的消息时自动调用。 6. 最后,我们使用 `sendMessage()` 方法将 `message` 变量中的内容发送到服务端。 希望这可以帮助您开始使用WebSocket在Vue3和Vite中编写应用程序。如果您还有任何问题,请随时问我。