preface
The Qiankun microservice integrates multiple systems of different technology stacks (React,Vue,Angular,jQuery) into one system, and each system can be independently deployed and run, which is suitable for large teams and large front-end projects.
Functions:
- React + Vue
- Background Management System (Ant Design Pro) multi-tab page caching practice in qiankun environment
- Dependency sharing – the parent app shares the public packages react,react-dom,moment,antd, etc
- Resource common – common utility util, components, configuration synchronized across multiple projects
Online preview based on Qiankun Microservice:
Click preview
Get the project source code
The project architecture
project | Technology stack | port | Access to the address |
---|---|---|---|
Main project (the main – the react) | Ant Design Pro | 5000 | qiankun.fancystore.cn |
Component (1) app1 – react to | Ant Design Pro | 5001 | app1.fancystore.cn |
Component 2 (app2 – react) | Ant Design Pro | 5002 | app2.fancystore.cn |
Subproject 3 (app3 – vue) | Vue Element Template | 5003 | app3.fancystore.cn |
Qiankun-Common | TypeScript | Github.com/czero1995/q… |
Project reform
1. Main application (base)
1.1 installation qiankun
npm install @umi/qiankun --save
or
yarn add @umi/qiankun --save
Copy the code
1.2 Registering sub-applications
// In config/config.ts add qiankun: {master: {apps: [{name:'app1', entry: process.env.NODE_ENV === 'production' ? '//app1.fancystore.cn' : '//localhost:5001', }, { name:'app2', entry: process.env.NODE_ENV === 'production' ? '//app2.fancystore.cn:' : '//localhost:5002', }, { name:'app3', entry: process.env.NODE_ENV === 'production' ? '//app3.fancystore.cn:' : '//localhost:5003', }, ], sandbox: True, // Whether to enable sandbox prefetch: true, // Whether to enable prefetch feature}}Copy the code
1.3 Modifying the Root Node
// src/pages/document.ejs
id=root-master
Copy the code
1.4 Creating a Sub-Application To load and layout MicroAppLayout
// src/layouts/MicroAppLayout import BasicLayout from '@ant-design/pro-layout'; import { KeepAlive, Provider } from 'react-keep-alive'; import { MicroAppWithMemoHistory } from 'umi'; import allRoutes from '.. /.. /config/routes'; function MicroAppLayout(props) { let targetMicro = '' const transRoutes = (routes, pathname) => { routes.map(item => { if (item.routes) { return transRoutes(item.routes, pathname) } if (item.path === pathname) { targetMicro = item.microName } }) return targetMicro } return <Provider> <KeepAlive name={props.location.pathname}> { targetMicro ? <MicroAppWithMemoHistory name={transRoutes(allRoutes[0].routes, props.location.pathname)} url={props.location.pathname} /> : <BasicLayout></BasicLayout> } </KeepAlive> </Provider> } export default MicroAppLayout;Copy the code
1.5 Create app.ts in the SRC directory. If it is a sub-application, use MicroAppLayout to load it
// src/app.ts
import LoadingComponent from '@/components/PageLoading';
import { dynamic } from 'umi';
const transRoutes = (routes) => {
routes.forEach(item => {
if(item.routes){
return transRoutes(item.routes)
}
if(item.microName){
item.component = dynamic({
loader: (a) => import(/* webpackChunkName: 'layouts__MicroAppLayout' */ '@/layouts/MicroAppLayout'),
loading: LoadingComponent,
})
}
})
}
export function patchRoutes({ routes }) {
transRoutes(routes[0].routes)
}
Copy the code
2. React(Ant Desin Pro)
2.1 installation qiankun
npm install @umi/qiankun --save
or
yarn add @umi/qiankun --save
Copy the code
2.2 Sub-project registration qiankun, join in config/config.ts
qiankun: {
slave: {}
}
Copy the code
2.3 Modifying the root object SRC /pages/document.ejs
id=root-slave
Copy the code
2.4 Create app.ts in the SRC directory and export the lifecycle hooks. The sub-project will need to distinguish between the qiankun environment and the current environment using SRC /layouts/BlankLayout. Use a default template (SRC /layouts/BasicLayout) that can be embedded in the Qiankun environment or deployed independently
Const isQiankun = window.__powered_by_qiankun__ export const qiankun = { console.log('app1 bootstrap', props); }, // Render before triggering async mount(props) {console.log('app1 mount', props); }, // Async unmount(props) is triggered after the application is unmounted {console.log('app1 unmount', props); }}; export async function patchRoutes({routes}) { if(isQiankun){ routes[0]['component'] = require('@/layouts/BlankLayout').default } }Copy the code
3. Child application Vue(Vue-element-template)
3.1 Add in configureWebpack under vue.config.js
Library: '${name}-[name] ', libraryTarget: 'umd', jsonpFunction: `webpackJsonp_${name}`, }Copy the code
3.2 Add devServer in vue.config.js:
headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Headers": "*"}Copy the code
3.3 Exposed life cycle of Qiankun in Main.js:
let install = null;
function render(props) {
install = new Vue({
router,
store,
render: h => h(App)
}).$mount('#app3')
}
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
} else {
render();
}
export async function bootstrap(props) {
}
export async function mount(props) {
render(props);
}
export async function unmount(props) {
install.$destroy();
install = null
}
Copy the code
Project summary
-
There are two ways for the main application to load sub-applications: routing bindings and using
components. If you want to support Ant Design Pro multiple tabs, you need to use
because dynamic display inserts tabs, Binding dead-end causes qiankun to fail to load the corresponding page. -
Ant Design Pro TAB, click the tabs to show different application page will lead to be destroyed, content data is initialized and lost, in the SRC/layouts/MicroAppLayout under:
The main application of the react-keep-Alive package must use MicroApp with MemoHistory. If you use MicroApp, there is no effect.Copy the code
-
Qiankun environment page jump 404
In the Qiankun environment, all route changes would trigger the monitoring of routes in Qiankun, requiring judgment on the environment: Export const qiankunJump = (URL :string, params = null) =>{window.__powered_by_qiankun__? history.pushState(params,name,url): umiHistory.push(url) } qiankunJump('/xxx')Copy the code
-
Cannot read property ‘createContext’ of Undefind
Externals: {'react': 'window.react ', 'react-dom': {'react':' window.react ', 'react-dom': 'window.ReactDOM', } => externals: { react: 'React', 'react-dom': 'ReactDOM', }Copy the code
Project optimization
1. Rely on sharing
If the main sub-app uses the same library or package (react,react-dom,moment, etc.), it can be imported using externals to reduce the waste of loading duplicate packages. The next time he uses it, he'll get it from the global variable first. This will allow you to reuse your content, Just make sure both the Url of the link simply const fetchScript = scriptUrl = > scriptCache [scriptUrl] | | (scriptCache [scriptUrl] = fetch(scriptUrl).then(response => response.text())); So as long as the subproject is configured with webpack externals and these public dependencies are on the same server, it can realize the on-demand introduction of the subproject's public dependencies. After one project uses the file, the other project does not load it repeatedly and can directly reuse the file.Copy the code
2. Resource sharing
Solving the resource sharing problem can improve the maintainability of projects that would otherwise be difficult to maintain components or tools shared by multiple systems. 1. Commonly used is to release into the NPM package, each project to install the update package. NPM link can be used for local debugging. But repeatedly updating packages is also tedious. Another option is to add "qiankun-common" to the package.json dependency: "Git+https://[email protected]: czero1995 / qiankun - common. Git" using the import {commonUtil} from 'qiankun - common; util.qiankunJump('/xxx')Copy the code
Project start
1. Run main-react NPM install NPM run start 2. App1-react NPM install NPM run start 3. App2-react NPM install NPM run start 4. Go to app3-react NPM install NPM run devCopy the code
Project deployment
-
Subapplication Nginx needs to be equipped with cross-domain request headers:
add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Credentials true; add_header Cache-Control no-cache; Copy the code
-
Nginx enables gzip compression:
gzip on; gzip_min_length 200; gzip_buffers 4 16k; gzip_comp_level 9; gzip_vary on; gzip_disable "MSIE [1-6]\."; gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json; Copy the code