基于qiankun微前端实战+部署粗略笔记(跳过原理)

基于qiankun微前端实战+部署粗略笔记(跳过原理)

因业务需要,以下文字纯个人qiankun实战学习笔记,不谈原理只记操作过程,内容难免有纰漏部分,敬请不吝赐教批评指正。

目标场景

预备知识点

技术栈

基座

  • 使用create-react-app初始化项目;
  • 安装

    "^2.4.0"```;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    + 代码地址:[react-app-qiankun-main](https://github.com/niexq/react-app-qiankun-main);
    + 独立仓库,独立部署,独立域名:https://qiankun.xiaoqiang.tech;

    #### react子应用
    + 使用[create-react-app](https://github.com/facebook/create-react-app)初始化项目;
    + 安装```"react-app-rewired": "^2.1.8"```、```"react-router-dom": "^5.2.0"```;
    + 代码地址:[react-app-qiankun-sub](https://github.com/niexq/react-app-qiankun-sub);
    + 独立仓库,独立部署,独立域名:https://react.xiaoqiang.tech;

    #### vue子应用
    + 使用[vue-cli](https://github.com/vuejs/vue-cli)初始化项目,对应```"vue": "^3.0.0"```;
    + 安装```"vue-router": "^4.0.0-beta.11"```;
    + 代码地址:[vue-cli-qiankun-sub](https://github.com/niexq/vue-cli-qiankun-sub);
    + 独立仓库,独立部署,独立域名:https://vue.xiaoqiang.tech;

    ### 快速上手

    #### 基座

    + 1.初始化项目
    ```bash
    npm init react-app react-app-qiankun-main

  • 2.安装

    1
    2
    ```bash
    yarn add qiankun # 或者 npm i qiankun -S

  • 3.目录结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    react-app-qiankun-main
    ├── .env.local // 本地环境
    ├── .env.development.local // 测试环境
    ├── .env.production.local // 生产环境
    ├── README.md
    ├── node_modules
    ├── package.json
    ├── .gitignore
    ├── public
    │ ├── favicon.ico
    │ ├── index.html
    │ └── manifest.json
    └── src
    ├── components
    │ └── Loading.jsx
    ├── store
    │ └── store.js // 主应用的全局状态
    ├── apps.js // 子应用配置
    ├── App.css
    ├── App.js // 基座布局,挂载子应用
    ├── App.test.js
    ├── index.css
    ├── index.js // 主应用中注册微应用
    ├── logo.svg
    ├── reportWebVitals.js
    └── setupTests.js

基座(开撸代码)

  • 新增3个.env文件,主要配置不同环境的对应的域名

    • .env/.env.development.local(此处暂未区分本地和测试的域名,所有环境变量值都保持一致)

      1
      2
      3
      REACT_APP_SUB_REACT=//localhost:2233/react
      REACT_APP_SUB_VUE=//localhost:3344/vue
      PORT=1122
    • .env.production.local (生产环境)

      1
      2
      REACT_APP_SUB_REACT = //qiankun.xiaoqiang.tech/react
      REACT_APP_SUB_VUE = //qiankun.xiaoqiang.tech/vue
  • 修改index.html挂载dom的默认id,防止与子应用id冲突

    1
    2
    // 默认root => main-root
    <div id="main-root"></div>
  • 新增store/store.js,配置主应用的全局状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import { initGlobalState } from 'qiankun';

    const initialState = {
    user: {
    name: 'qiankun'
    }
    };

    const actions = initGlobalState(initialState);

    actions.onGlobalStateChange((state, prev) => {
    for(const key in state) {
    initialState[key] = state[key];
    }
    })

    // 非官方api,https://github.com/umijs/qiankun/pull/729
    actions.getGlobalState = (key) => {
    return key ? initialState[key] : initialState;
    }

    export default actions;
  • 修改src/App.js,主要完成基座页面布局及增加挂载子应用的dom(id=”subapp-viewport”)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function App(props) {
    // ...省略,详细可见源码
    return (
    <>
    <div className="mainapp">
    {/* 标题栏 */}
    <header className="mainapp-header">
    <ul className="mainapp-header-sidemenu">
    {/* 侧边栏 省略,详细可见源码 */}
    </ul>
    </header>
    <div className="mainapp-main">
    {/* 子应用 */}
    <main id="subapp-viewport"></main>
    </div>
    </div>
    </>
    );
    }
  • 增加apps.js,子应用的配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import store from './store/store'
    const microApps = [
    {
    name: 'react',
    entry: process.env.REACT_APP_SUB_REACT,
    activeRule: '/react',
    container: '#subapp-viewport',
    },
    {
    name: 'vue',
    entry: process.env.REACT_APP_SUB_VUE,
    activeRule: '/vue',
    container: '#subapp-viewport',
    },
    ]

    const apps = microApps.map(item => {
    return {
    ...item,
    props: {
    routerBase: item.activeRule,
    getGlobalState: store.getGlobalState,
    }
    }
    })

    export default apps
  • 修改src/index.js,主应用中注册微(子)应用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import { registerMicroApps, start, setDefaultMountApp } from 'qiankun';
    import apps from './apps'

    function render({ appContent, loading }) {
    const container = document.getElementById('main-root');
    ReactDOM.render(
    <React.StrictMode>
    <App loading={loading} content={appContent} />
    </React.StrictMode>,
    container,
    )
    }

    const loader = loading => render({ loading });

    render({ loading: true });

    const microApps = apps.map((app => ({
    ...app,
    loader,
    })))
    registerMicroApps(microApps, {
    beforeLoad: app => {
    console.log('before load app.name=====>>>>>', app.name)
    },
    beforeMount: [
    app => {
    console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name)
    }
    ],
    afterMount: [
    app => {
    console.log('[LifeCycle] after mount %c%s', 'color: green;', app.name)
    }
    ],
    afterUnmount: [
    app => {
    console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name)
    }
    ]
    })

    setDefaultMountApp('/react')

    start();
  • 本地启动

    1
    npm start

react子应用

  • 1.初始化项目

    1
    npm init react-app react-app-qiankun-sub
  • 2.安装

    1
    2
    3
    ```bash
    npm i react-app-rewired --save-dev
    npm i react-router-dom --save

  • 3.目录结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    react-app-qiankun-sub
    ├── .env // 本地环境
    ├── config-overrides.js // 覆盖create-react-app的webpack配置
    ├── README.md
    ├── node_modules
    ├── package.json
    ├── .gitignore
    ├── public
    │ ├── favicon.ico
    │ ├── index.html
    │ └── manifest.json
    └── src
    ├── components
    │ └── LibVersion.jsx
    ├── pages
    │ └── Home.jsx
    ├── public-path.js // __webpack_public_path__
    ├── App.css
    ├── App.js // 子应用布局
    ├── App.test.js
    ├── index.css
    ├── index.js // 子应用入口,挂载dom导出相应的生命周期钩子
    ├── logo.svg
    ├── reportWebVitals.js
    └── setupTests.js

react子应用(开撸代码)

  • 新增1个.env文件,主要配置本地环境

    此处PORT需要和基座

    1
    2
    ```js
    PORT=2233

  • 修改index.html挂载dom的默认id,防止与基座及其他子应用id冲突

    1
    2
    // 默认root => sub-react-root
    <div id="sub-react-root"></div>
  • 新增src/public-path.jswebpack_public_path

    1
    2
    3
    4
    if (window.__POWERED_BY_QIANKUN__) {
    // eslint-disable-next-line no-undef
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
    }
  • 修改src/App.js,主要完成子应用页面布局(略,见源码)

  • 修改src/index.js,微(子)应用导出相应的生命周期钩子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    import './public-path';
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';

    function getSubRootContainer(container) {
    return container ? container.querySelector('#sub-react-root') : document.querySelector('#sub-react-root');
    }

    function render(props) {
    const { container } = props;
    ReactDOM.render(
    <React.StrictMode>
    <App store={{...props}} />
    </React.StrictMode>,
    getSubRootContainer(container),
    );
    }

    function storeTest(props) {
    props.onGlobalStateChange((value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev), true);
    props.setGlobalState({
    ignore: props.name,
    user: {
    name: props.name,
    },
    });
    }

    if (!window.__POWERED_BY_QIANKUN__) {
    render({});
    }

    export async function bootstrap() {
    console.log('react app bootstraped');
    }

    export async function mount(props) {
    console.log('props from main framework', props);
    storeTest(props);
    render(props);
    }

    export async function unmount(props) {
    const { container } = props;
    ReactDOM.unmountComponentAtNode(getSubRootContainer(container));
    }
  • 增加config-overrides.js,覆盖create-react-app的webpack配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    const { name } = require('./package');
    module.exports = {
    webpack: config => {
    config.output.library = `${name}-[name]`;
    config.output.libraryTarget = 'umd';
    config.output.jsonpFunction = `webpackJsonp_${name}`;
    return config;
    },
    devServer: (configFunction) => {
    return (proxy, allowedHost) => {
    const config = configFunction(proxy, allowedHost);
    config.historyApiFallback = true;
    config.open = false;
    config.hot = false;
    config.watchContentBase = false;
    config.liveReload = false;
    config.headers = {
    'Access-Control-Allow-Origin': '*',
    };
    return config;
    }
    }
    }
  • 修改package.json

    1
    2
    3
    4
    5
    6
    7
    8
    9
    "scripts": {
    - "start": "react-scripts start",
    + "start": "react-app-rewired start",
    - "build": "react-scripts build",
    + "build": "react-app-rewired build",
    - "test": "react-scripts test",
    + "test": "react-app-rewired test",
    "eject": "react-scripts eject"
    },
  • 本地启动

    1
    npm start

vue子应用

  • 1.初始化项目

    1
    2
    npm install -g @vue/cli-service-global
    vue create vue-cli-qiankun-sub
  • 2.安装

    1
    2
    ```bash
    npm i vue-router --save

  • 3.目录结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    vue-cli-qiankun-sub
    ├── .env // 本地环境
    ├── vue.config.js // vue可选的配置文件
    ├── babel.config.js
    ├── README.md
    ├── node_modules
    ├── package.json
    ├── .gitignore
    ├── public
    │ ├── favicon.ico
    │ ├── index.html
    │ └── manifest.json
    └── src
    ├── components
    │ └── HelloWorld.vue
    ├── router
    │ └── index.js
    ├── views
    │ └── Home.vue
    ├── public-path.js // __webpack_public_path__
    ├── App.vue // 子应用布局
    └── main.js // 子应用入口,挂载dom导出相应的生命周期钩子

vue子应用(开撸代码)

  • 新增1个.env文件,主要配置本地环境

    此处PORT需要和基座

    1
    2
    ```js
    PORT=3344

  • 修改index.html挂载dom的默认id,防止与基座及其他子应用id冲突

    1
    2
    // 默认root => sub-vue-root
    <div id="sub-vue-roott"></div>
  • 新增src/public-path.jswebpack_public_path

    1
    2
    3
    4
    if (window.__POWERED_BY_QIANKUN__) {
    // eslint-disable-next-line no-undef
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
    }
  • 修改src/App.vue,主要完成子应用页面布局(略,见源码)

  • 修改src/mian.js,微(子)应用导出相应的生命周期钩子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    import './public-path';
    import { createApp } from 'vue';
    import { createRouter, createWebHistory } from 'vue-router';
    import App from './App.vue';
    import routes from './router';
    import store from './store';

    let router = null;
    let instance = null;
    let history = null;


    function render(props = {}) {
    const { container } = props;
    history = createWebHistory(window.__POWERED_BY_QIANKUN__ ? '/vue' : '/');
    router = createRouter({
    history,
    routes,
    });

    instance = createApp(App);
    instance.use(router);
    instance.use(store);
    instance.mount(container ? container.querySelector('#sub-vue-root') : '#sub-vue-root');
    }

    if (!window.__POWERED_BY_QIANKUN__) {
    render();
    }

    export async function bootstrap() {
    console.log('%c ', 'color: green;', 'vue3.0 app bootstraped');
    }

    function storeTest(props) {
    props.onGlobalStateChange &&
    props.onGlobalStateChange(
    (value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
    true,
    );
    props.setGlobalState &&
    props.setGlobalState({
    ignore: props.name,
    user: {
    name: props.name,
    },
    });
    }

    export async function mount(props) {
    storeTest(props);
    render(props);
    instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange;
    instance.config.globalProperties.$setGlobalState = props.setGlobalState;
    }

    export async function unmount() {
    instance.unmount();
    instance._container.innerHTML = '';
    instance = null;
    router = null;
    history.destroy();
    }
  • 增加vue.config.js配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    const path = require('path');
    const { name } = require('./package');

    function resolve(dir) {
    return path.join(__dirname, dir);
    }

    const port = process.env.PORT;

    module.exports = {
    outputDir: 'dist',
    assetsDir: 'static',
    filenameHashing: true,
    devServer: {
    hot: true,
    disableHostCheck: true,
    port,
    overlay: {
    warnings: false,
    errors: true,
    },
    headers: {
    'Access-Control-Allow-Origin': '*',
    },
    },
    // 自定义webpack配置
    configureWebpack: {
    resolve: {
    alias: {
    '@': resolve('src'),
    },
    },
    output: {
    // 把子应用打包成 umd 库格式
    library: `${name}-[name]`,
    libraryTarget: 'umd',
    jsonpFunction: `webpackJsonp_${name}`,
    },
    },
    };
  • 修改package.json

    1
    2
    3
    "scripts": {
    + "start": "vue-cli-service serve",
    },
  • 本地启动

    1
    npm start

预览

以上操作完后,可以直接通过基座预览,子应用也可独立预览

基座预览

1
http://localhost:1122/

react子应用预览

1
http://localhost:2233/

vue子应用预览

1
http://localhost:3344/

部署

备选方案

  • 1.单域名部署;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 基座:https://qiankun.xiaoqiang.tech
    // react子应用:https://qiankun.xiaoqiang.tech/react
    // vue子应用:https://qiankun.xiaoqiang.tech/vue
    // 编译后服务器存储目录
    react-app-qiankun
    ├── main
    │ └── index.html
    ├── react
    │ └── index.html
    └── vue
    └── index.html
  • 2.多域名独立部署;(当篇笔记选择了多域名部署)

    1
    2
    3
    4
    // 基座:https://qiankun.xiaoqiang.tech
    // 编译后服务器项目独立存储目录
    react-app-qiankun-main
    └── index.html
1
2
3
4
// react子应用:https://react.xiaoqiang.tech
// 编译后服务器项目独立存储目录
react-app-qiankun-sub
└── index.html
1
2
3
4
// vue子应用:https://vue.xiaoqiang.tech
// 编译后服务器项目独立存储目录
react-app-qiankun-main
└── index.html

部署(以下只初略记录部署过程,过于简陋)

  • 前提:已购云服务器,并已安装dockernginxjenkins、3个独立域名及ssl证书

  • 本地编码,github存储代码,分别新建3个公开代码库

    1
    2
    3
    // 基座:react-app-qiankun-main 存储到 https://github.com/niexq/react-app-qiankun-main
    // react子应用:react-app-qiankun-sub 存储到 https://github.com/niexq/react-app-qiankun-sub
    // vue子应用:vue-cli-qiankun-sub 存储到 https://github.com/niexq/vue-cli-qiankun-sub
  • github,jenkins持续集成

1
2
3
4
5
6
7
8
9
// 详细配置步骤略
// github webHooks设置
// jenkins构建部分执行shell
BUILD_ID=dontKillMe
cd /var/jenkins_home/workspace/react-app-qiankun-main
npm install
npm run build
rm -rf /srv/www/react-app-qiankun-main
cp -rf /var/jenkins_home/workspace/react-app-qiankun-main/build /srv/www/react-app-qiankun-main/
  • 使用nginx代理
    nginx.conf
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104

    user root;
    worker_processes 1;

    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;


    events {
    worker_connections 1024;
    }


    http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    #tcp_nopush on;

    keepalive_timeout 65;

    #gzip on;

    #include /etc/nginx/conf.d/*.conf;

    server {
    listen 443;
    server_name qiankun.xiaoqiang.tech; # 你的域名
    ssl on;
    root www/react-app-qiankun-main; # 前台文件存放文件夹,可改成别的
    index index.html index.htm; # 上面配置的文件夹里面的index.html
    ssl_certificate cert/5543142_qiankun.xiaoqiang.tech.pem; #将domain name.pem替换成您证书的文件名。
    ssl_certificate_key cert/5543142_qiankun.xiaoqiang.tech.key; #将domain name.key替换成您证书的密钥文件名。
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    location / {
    # 用于配合 browserHistory使用
    try_files $uri $uri/ /index.html;
    # root /srv/www/react-app-qiankun-main;
    # index index.html index.htm;
    }
    }

    server {
    listen 443;
    server_name react.xiaoqiang.tech; # 你的域名
    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';
    if ($request_method = 'OPTIONS') {
    return 204;
    }
    ssl on;
    root www/react-app-qiankun-sub; # 前台文件存放文件夹,可改成别的
    index index.html index.htm; # 上面配置的文件夹里面的index.html
    ssl_certificate cert/4325684_react.xiaoqiang.tech.pem; #将domain name.pem替换成您证书的文件名。
    ssl_certificate_key cert/4325684_react.xiaoqiang.tech.key; #将domain name.key替换成您证书的密钥文件名。
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    location / {
    # 用于配合 browserHistory使用
    try_files $uri $uri/ /index.html;
    # root /srv/www/react-app-qiankun-sub;
    # index index.html index.htm;
    }
    }

    server {
    listen 443;
    server_name vue.xiaoqiang.tech; # 你的域名
    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';
    if ($request_method = 'OPTIONS') {
    return 204;
    }
    ssl on;
    root www/vue-cli-qiankun-sub; # 前台文件存放文件夹,可改成别的
    index index.html index.htm; # 上面配置的文件夹里面的index.html
    ssl_certificate cert/5556275_vue.xiaoqiang.tech.pem; #将domain name.pem替换成您证书的文件名。
    ssl_certificate_key cert/5556275_vue.xiaoqiang.tech.key; #将domain name.key替换成您证书的密钥文件名。
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    location / {
    # 用于配合 browserHistory使用
    try_files $uri $uri/ /index.html;
    # root /srv/www/vue-cli-qiankun-sub;
    # index index.html index.htm;
    }
    }
    }

docker运行nginx命令,重点关注

挂载目录```
1
2
```bash
docker run --name nginx -p 80:80 -p 443:443 -v /root/nginx/config/nginx.conf:/etc/nginx/nginx.conf -v /root/nginx/cert:/etc/nginx/cert -v /root/nginx/logs:/var/log/nginx -v /srv/www/react-app-qiankun-main:/etc/nginx/www/react-app-qiankun-main -v /srv/www/react-app-qiankun-sub:/etc/nginx/www/react-app-qiankun-sub -v /srv/www/vue-cli-qiankun-sub:/etc/nginx/www/vue-cli-qiankun-sub --restart=always -d nginx:stable

总结

没有总结,遇到的问题太多,笔记总结的太杂,后期再整理分享

线上预览地址:https://qiankun.xiaoqiang.tech

子应用线上也可独立预览

react子应用预览:https://react.xiaoqiang.tech

vue子应用预览:https://vue.xiaoqiang.tech

参考链接

qiankun

qiankun-example

qiankun 微前端方案实践及总结

0%