使用 qiankun 搭建微前端应用

什么是qiankun

qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。具体更多内容请参考 qiankun官网

什么是主应用

主应用是一个进程服务,子应用的容器,比如有个id=‘container’ 的 div。微应用的都会挂载到这个div 上。类似 spa 的 id=‘root’ 的dom。

什么是微应用

  • 一个微应用就是一单独的一个项目,有自己的node_modules等。能自己单独运行。
  • 当主应用根据路由匹配到微应用时。微应用就会挂载到 id=‘container’ 的 div 。
  • 类似于spa的 根据路由渲染页面,只是这里的页面不是一个文件,而是一个独立的项目。

预览效果

在这里插入图片描述

创建主应用

  • 初始化项目,使用cra 脚手架
create-react-app qiankun
  • 安装react-router-dom qiankun
npm i react-router-dom qiankun
  • 修改 App.js 和 index.js
// App.js
import './App.css';
import { Link } from 'react-router-dom'
function App() {
  return (
    <div className="App">
      <div style={{ display: 'flex' }}>
        <Link to='/react-app'>
          <button>react 应用</button>
        </Link>
        <Link to='/vue-app'>
          <button>vue 应用</button>
        </Link>
      </div>
      <div id='container'></div>
    </div>
  );
}
export default App;
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { BrowserRouter } from "react-router-dom";
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'vueApp',
    entry: 'http://localhost:8085/ ',
    container: '#container',
    activeRule: '/vue-app',
  },
  {
    name: 'reactApp',
    entry: 'http://localhost:4001/', // 和微应用 启动的路径 一致
    container: '#container',
    activeRule: '/react-app',
  },
]);

// 启动 qiankun
start()
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

最后看到的页面是这样的
在这里插入图片描述

  • 现在点击两个按钮会报错,这是正常的,因为我们的微应用还没有建立。

建立 react 微应用

  • 初始化项目
create-react-app react-app
  • 进入到 react-app 目录
  • 下载 react-app-rewired 、react-router-dom。react-app-rewired 是 在 不使用 ‘eject’ 暴露配置的情况下,能自定义webpack配置 github地址
npm i react-router-dom react-app-rewired

接下来的步骤可以参考,基本和官网配置一致 官方文档

  • 在 src 目录 新建 public-path.js 文件
if (window.__POWERED_BY_QIANKUN__) {
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
  • 修改src 下面的index.js 文件,引入public-path 和 声明 qiankun 的生命周期
import './public-path.js';
import React from 'react';
import { BrowserRouter } from 'react-router-dom'

import ReactDOM from 'react-dom';
import App from './App';


function render(props) {
  const { container } = props;
  ReactDOM.render(
  	//对应上 主应用 的路由
    <BrowserRouter basename={window.__POWERED_BY_QIANKUN__ ? '/react-app' : '/'}>
      <App />
    </BrowserRouter>,
    container ? container.querySelector('#root') : document.querySelector('#root')
  );
}

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;
  ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') : document.querySelector('#root'));
}
  • 更改webpack 的配置,在 react-app 目录下 新建 config-overrides.js
const { name } = require('./package');
module.exports = {
  webpack: (config) => {
    config.output.library = `${name}-[name]`;
    config.output.libraryTarget = 'umd';
    // webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal
    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;
  },
};
  • 修改package.json 里面的启动命令
 "scripts": {
   	"start": "PORT=4001 && react-app-rewired start", // 得修改端口号,避免和主应用的端口号冲突
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
  },
  • 这时候在react-app 目录下直接 npm run start 你会发现react项目就跑起来了。
  • 在去到 qiankun 目录下 ,运行npm run start
  • 打开网页后就 会发现以下的界面,这时react微应用已经跑起来了。
    在这里插入图片描述

vue 微应用

  • 运行脚手架创建项目,会提示你安装vue2 还是 vue3。
  • 选择vue2和vue3 有些许配置不一样,本文下面是vue 3 的配置
  • vue2 配置 参考官网qiankun vue 配置
vue create vue-app
  • 在 src 目录新增 public-path.js
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
  • 下载vue-router
npm install --save vue-router
  • 新建一个pages 文件夹,再创一个index.vue 的页面,内容随便写
  • 再新建一个router 文件夹
// index.js
const routes = [
  {
    path: "/",
    name: "Home",
    component: () => import("../pages/index.vue"),
  },
];
export default routes;
  • 修改main.js 文件
import './public-path';
import { createApp } from 'vue'
import App from './App.vue';
import routes from './router';
import { createRouter, createWebHistory } from 'vue-router'

let app = null
let router = null
function render(props = {}) {
  const { container } = props;
  router = createRouter({
    history: createWebHistory(window.__POWERED_BY_QIANKUN__ ? '/vue-app/' : '/'),
    routes,
  });
  app = createApp(App)
  app.use(router).mount(container ? container.querySelector('#app') : '#app');
}

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

export async function bootstrap() {
  console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
  console.log('[vue] props from main framework', props);
  render(props);
}
export async function unmount() {
  router = null;
  app = null;
}
  • 新建 vue.config.js
const { name } = require('./package');
module.exports = {
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${name}`, // webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal
    },
  },
};
  • 运行 npm run serve 没有报错,项目就运行成功了。
  • 然后去浏览器看 主应用的 就会发现如最开始的 gif 图。
  • 大家会发现每增加一个微应用就会多一个 服务 ,如果每次都在终端运行,特别麻烦。我们可以些个脚本,用node来帮我们启动所有的微应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值