本教程适合刚接触qiankun的新人,介绍了如何从0构建一个qiankun项目
1、首先创建一个主应用
主应用不限技术栈,react或者vue都可以,只需要提供一个容器DOM,然后注册微应用并start开始
先安装qiankun:
yarn add qiankun // 或者 npm i qiankun -S
我是以react作为主应用的,首先注册微应用并启动。
// 在主应用的src下的index.js 里面注册微应用并启动
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
// import reportWebVitals from './reportWebVitals';
import { registerMicroApps, start } from 'qiankun';
import 'antd/dist/antd.less';
import { BrowserRouter } from 'react-router-dom';
// 注册
registerMicroApps([
{
name: 'vueApp',
entry: '//localhost:8080',
container: '#container',
activeRule: '/app-vue',
},
{
name: 'reactApp',
entry: '//localhost:4000',
container: '#container',
activeRule: '/app-react',
},
]);
// 启动
start();
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
// reportWebVitals();
/**
* 因为后续会加上 react-router-dom, 所以此处后续要记得加上 BrowserRouter
* <BrowserRouter>
* <App />
* </BrowserRouter>
*/
2、然后创建微应用
????????2.1、vue微应用
????????????????我是以vue-cli 3+生成的vue2.x项目为例
创建好之后修改main.js文件
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
/** 文档中将此代码单独放到了一个文件中,此处是直接写在了 main.js 中,两种都可。但是 eslint-disable 需要加上 */
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
let instance = null;
function render(props = {}) {
const { container } = props;
// 文档中使用store,此处没有便删除了。
instance = new Vue({
router,
render: h => h(App),
}).$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() {
instance.$destroy();
instance.$el.innerHTML = "";
instance = null;
}
接着配置router路由
// router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'Home',
component: () => import("./views/Home.vue")
},
{
path: '/about',
name: 'About',
component: () => import("./views/About.vue")
},
];
const router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? "/app-vue/" : "/",
mode: "history",
routes,
})
export default router;
最后修改打包配置文件,创建一个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}`,
},
},
};
????????2.2、react微应用
? ? ? ? ? ? ? ? 我使用的是react 16为例
首先在src目录下创建public-path.js
// public-path.js
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
然后配置index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import './public-path'
import reportWebVitals from './reportWebVitals';
import {BrowserRouter as Router } from 'react-router-dom';
import App from './App';
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
function render(props) {
const { container } = props;
ReactDOM.render(
<React.StrictMode>
<Router basename={window.__POWERED_BY_QIANKUN__ ? '/app-react' : '/'}>
<App />
</Router>
</React.StrictMode>,
container ? container.querySelector('#root') : document.querySelector('#root')
);
}
if (!window.__POWERED_BY_QIANKUN__) {
render({});
}
export async function bootstrap() {
console.log('[react18] react app bootstraped');
}
export async function mount(props) {
console.log('[react18] props from main framework', props);
render(props);
}
export async function unmount(props) {
const {container} = props;
ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') : document.querySelector('#root'));
}
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
接下来就是配置webpack
首先使用?npm i?react-app-rewired? 引入插件
然后在根目录下新建config-overrides.js文件
const { name } = require('./package');
module.exports = {
webpack: (config, env) => {
config.output.library = `${name}-[name]`;
config.output.libraryTarget = 'umd';
config.output.globalObject = 'window';
config.output.chunkLoadingGlobal = `webpackJsonp_${name}`;
return config;
},
devServer: (_) => {
const config = _;
config.headers = {
'Access-Control-Allow-Origin': '*',
};
config.historyApiFallback = true;
config.hot = false;
config.watchContentBase = false;
config.liveReload = false;
config.injectClient = false
return config;
}
}
?最后修改一下package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
},
至此。微应用创建完毕
接下来配置主应用的app.js
import { useState } from 'react';
import { Layout, Menu } from 'antd';
import {
PieChartOutlined,
DesktopOutlined,
ContainerOutlined,
} from '@ant-design/icons';
import './App.css';
import { Link } from 'react-router-dom'
const { Header, Content, Footer, Sider } = Layout;
function getItem(label, key, icon, children, type) {
return {
key,
icon,
children,
label,
type,
};
}
const items = [
getItem((
<Link to="/app-vue">
Vue应用
</Link>
), '1', <PieChartOutlined />),
getItem((
<Link to='/app-react'>
React应用
</Link>
), '2', <DesktopOutlined />),
getItem((
<Link to='/app-angular'>
Angular应用
</Link>
), '3', <ContainerOutlined />),
];
const App = () => {
const [collapsed, setCollapsed] = useState(false);
const onCollapse = collapsed => {
setCollapsed(collapsed);
};
// const toggleCollapsed = () => {
// setCollapsed(!collapsed);
// };
return (
// <div
// style={{
// width: 256,
// }}
// >
// {/* <Button
// type="primary"
// onClick={toggleCollapsed}
// style={{
// marginBottom: 16,
// }}
// >
// {collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
// </Button> */}
// <Menu
// defaultSelectedKeys={['1']}
// defaultOpenKeys={['sub1']}
// mode="inline"
// theme="dark"
// inlineCollapsed={collapsed}
// items={items}
// />
// </div>
<Layout style={{ minHeight: '100vh' }}>
<Sider collapsible collapsed={collapsed} onCollapse={onCollapse}>
<div className='logo' />
<Menu
defaultSelectedKeys={['1']}
mode="inline"
theme="dark"
collapsed="true"
items={items}
/>
{/* <Menu theme='dark' defaultSelectedKeys={['1']} mode='inline'>
<Menu.Item key="1" icon={<PieChartOutlined />}>
<Link to="/app-vue">Vue应用</Link>
</Menu.Item>
<Menu.Item key="2" icon={<DesktopOutlined />}>
<Link to='/app-react'>React应用</Link>
</Menu.Item>
</Menu> */}
</Sider>
<Layout className='site-layout'>
<Header className='site-layout-background' style={{ padding: 0 }} />
<Content style={{ margin: '16px' }}>
<div id='container' className='site-layout-background' style={{ minHeight: 360 }}></div>
</Content>
<Footer style={{ textAlign: 'center' }}>
This Project ?2022 Created by Gorgio)
</Footer>
</Layout>
</Layout>
)
}
export default App;
配置完毕之后记得修改app.css,加上样式代码
#components-layout-demo-side .logo {
height: 32px;
margin: 16px;
background: rgba(255, 255, 255, 0.3);
}
.site-layout .site-layout-background {
background: #fff;
}
最后将主应用跟微应用都启动起来,这时候你会发现react默认的端口号都是3000,这时候就需要手动改一下微应用的端口号,这里就不作修改了,不会的自行百度吧。
启动成功之后会展示出来如下效果
?
至此,恭喜你完成了整个qiankun项目的搭建!!!?
|