微前端用通俗易懂的话来说就是:一个主应用(基座)中可以搭建多个子应用(微应用),这些子应用可以是不同版本,不同前端框架,而且跟主应用的语言无关,主应用仅仅是一个基座。
正常一个项目想要展示另一个项目,通常会用 iframe 进行嵌入,但是相比 iframe,qiankun
等微前端的接入表现形式会更加友好,如果要以 iframe 为基础的,可以尝试使用腾讯的 无界
框架。
创建项目
本文主要以 react + webpack 的接入为主,因为 qiankun
对于 vite 的支持度并不友好,vue3 同样首推 vite,虽然有社区插件 vite-plugin-qiankun
可以接入,但是出现的问题也是很多的,作为企业项目来开发并不是首选(虽然我也想用,但为了更稳定一点还是选择 webpack)。
以 CRA 脚手架创建三个项目,一个主应用基座 app
,两个微应用 micro-app-1
micro-app-2
,也可以自己使用 webpack 搭建
npx create-react-app app --template typescript
其目录结构如下
—— app
—— micro-app-1
—— micro-app-2
qiankun
的接入是需要修改 webpack 的,而 CRA 隐藏了 webpack 配置,可以使用 eject
暴露出所有的配置,也可以采用插件复写 webpack 配置,这里采用 craco
进行复写 webpack 配置。
安装 craco
(每个项目都要装,都要配置 webpack)
npm i @craco/craco -D
package.json 修改 script 命令
{
// ...
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
},
}
项目根目录新建 craco.config.js
,这里只修改项目的启动端口,和关闭允许项目自动打开浏览器,3 个项目是不同的启动端口,关于 qiankun 的配置在下一小节
// craco.config.js
module.exports = {
devServer: {
port: 3000,
open: false,
},
};
接入 qiankun
这一部分可以结合 qiankun 官网 进行阅读.
主应用注册微应用
在主应用 app
的入口文件 index.tsx
中,添加如下内容
// index.tsx
import { registerMicroApps, start } from "qiankun";
registerMicroApps([
{
name: "qiankun-app1", // 给该应用起个名字
entry: "//localhost:1111", // micro-app-1 项目的运行地址
container: "#app1", // micro-app-1 应用挂载的 dom 节点
activeRule: "/micro-app1", // 在主应用访问 /micro-app1 加载子应用
},
{
name: "qiankun-app2",
entry: "//localhost:2222",
container: "#app2",
activeRule: "/micro-app2",
},
]);
// start 内部的 experimentalStyleIsolation 是样式隔离,不需要可直接写 start()
start({ sandbox: { experimentalStyleIsolation: true } });
以上代码是注册了微应用,比如第一个,当访问 micro-app1
路由时,挂载子应用到 #app1
这个 dom 节点上(需提供挂载容器),子应用的运行地址是 localhost:1111
所以需要在主应用中提供子应用的挂载容器,
function App() {
return (
<>
<h2>app</h2>
<Link to="/micro-app1"> to App1 </Link>
<Link to="/micro-app2"> to App2 </Link>
<div id="app1"></div>
<div id="app2"></div>
</>
);
}
这里安装了 react-router-dom
微应用对接主应用
上述步骤,主应用的配置基本完毕,现在需要配置子应用。
- 在 src 目录下新增
public-path.js
,写入内容,并在index.tsx
中引入
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
这段代码是为了在访问子应用的静态资源时,可以加载子应用的静态资源
如图所示,子应用的静态资源直接加载的就是完整路径地址
- 在子应用中写入
qiankun
需要的生命周期,这里以micro-app-1
为例,另一个也一样,完整代码如下
public-path.js
的引入,一定要在 App.tsx
引入之前
import "./public-path";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
const isQiankun = !!window.__POWERED_BY_QIANKUN__;
console.log(isQiankun);
let root: ReactDOM.Root;
// createRoot 挂载函数,有 container 说明是qiankun,,没有则是独立应用
function createRoot(props: Record<string, any>) {
const { container } = props;
root = ReactDOM.createRoot(container ? container.querySelector("#root") : document.querySelector("#root"));
}
// 独立运行,直接调用 createRoot函数 render
if (!isQiankun) {
createRoot({});
// @ts-ignore
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
}
export async function bootstrap() {
// console.log("app1 bootstraped 加载");
}
export async function mount(props: Record<string, any>) {
// console.log("app1 mount 加载,主应用 prop: ", props);
//qiankun环境中渲染
createRoot(props);
// 对两种不同的环境分别给出不同的基础路径,/micro-app1 就是主应用乾坤注册时的 activeRule
root.render(
<BrowserRouter basename={isQiankun ? "/micro-app1" : "/"}>
<App />
</BrowserRouter>
);
}
export async function unmount(_props: any) {
// console.log("app1 unmount 卸载", _props);
root.unmount();
}
这里 window.__POWERED_BY_QIANKUN__
会报 TS 错误,可以直接在 react-app-env.d.ts
中写入
interface Window {
__POWERED_BY_QIANKUN__: any;
__INJECTED_PUBLIC_PATH_BY_QIANKUN__: any;
}
- 写入 webpack 配置
在 craco.config.js
中写入以下内容,此处可结合官方文档查看,其中官方文档中的 watchContentBase
已被移除,不写。
const path = require("path");
const { name } = require("./package.json");
module.exports = {
webpack: {
configure: (config) => {
config.output.library = { name: `${name}-[name]`, type: "umd" };
config.output.chunkLoadingGlobal = `webpackJsonp_${name}`;
config.output.globalObject = "window";
return config;
},
alias: {
"@": path.resolve(__dirname, "src"),
},
},
devServer: {
port: 1111,
open: false,
headers: {
"Access-Control-Allow-Origin": "*",
},
historyApiFallback: true,
hot: true,
liveReload: false,
},
};
修改 webpack 配置后重启项目,此时访问 http://localhost:3000/micro-app1
,以主应用的地址+子应用路由,就可以看到该子应用,另一个子应用配置同理
主应用微应用路由注册
当匹配到主应用路由时,只会渲染主应用的路由,当主应用切换到子应用路由时,才会挂载子应用路由,简单示例图如下
标签:__,前端,qiankun,micro,webpack,应用,app,搭建 From: https://www.cnblogs.com/jsonq/p/18209388