美文网首页
微前端的实践

微前端的实践

作者: Doter | 来源:发表于2020-07-26 11:08 被阅读0次

    前端时间打算建立更新下自己的github page,所以先在gitee上进行可实验,
    开始选用qiankun后来使用single-spa

    主应用构建

    1. 使用single-spa或者qiankun搭建主应用都比较简单,只需要配置,只要需要配置子应用即可。
    export const apps: AppConfig[] = [
      {
        name: 'blogs', // app name 需要唯一
        source: {
          scripts: ['/blogs/bundle.js'], //目前只实现js的加载,其打包的方式应该为umd,具体参考子应用的配置
        },
        activeWhen: '/#/blogs', //配置路由,或者自定义返回bool的函数
        container: '#main', //加载子应用的位置
      },
    ];
    

    如上配置,参照官网配置即可。

    1. 然后手动实现一个简单的loader
    export const getAppConfig = (app: AppConfig): RegisterApplicationConfig => {
      return {
        name: app.name,
        app: () => getApp(app),
        activeWhen: app.activeWhen,
        customProps: {
          ...app.customProps,
          container: app.container,
        },
      };
    };
    
    const getApp = async (app: AppConfig): Promise<any> => {
      const {
        source: { scripts, styles },
        name,
      } = app;
      if (exports[name]) return exports[name];
      const srcs = await Promise.all(
        scripts.map((script) => fetch(script).then((res) => res.text()))
      );
      // todo:append styles
      srcs.forEach((script) => {
        eval.call(window, script); // 将配置的js进行执行,获取到export出来的js
      });
      return exports[name];
    };
    

    可能是我使用的qiankun的姿势不对,上面getApp这一步qiankun已经做了,但是我的加载有问题,所以就放弃了改用了single-spa

    window.onload = () => {
      init();// 自定义全局变量
      start();
      apps.forEach((app) => {
        registerApplication(getAppConfig(app));//注册子应用
      });
      // 这里是我自定义的菜单渲染,即通过配置实现
      MenuRender(menu, document.getElementById('app-header'));
    };
    

    这样主应用就算是搭建起来了。

    子应用的构建

    import { createApp } from 'vue';
    import App from './App.vue';
    import './index.scss';
    let app;
    
    /**
     * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
     * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
     */
    export async function bootstrap() {}
    /**
     * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
     */
    export async function mount(props) {
      app = createApp(App);
      app.mount(props.container);
    }
    /**
     * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
     */
    export async function unmount(props) {
      app.unmount(props.container);
    }
    /**
     * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
     */
    export async function update(props) {}
    
    //在本地开发时的配置
    if (!window['__POWERED_BY_QIANKUN__']) {
      const root = document.createElement('div');
      root.setAttribute('id', 'main');
      document.body.append(root);
      const app = createApp(App);
      app.mount('#main');
    }
    

    就是这么简单。

    这里还有一个小插曲:使用vue3-alpha开发的,按照上面我想着createApp然后在mount和unmount的时候直接调用即可,结果发现unmount之后mount失败,后来定位是vue库的问题,然后happy的去提了个issue,并提了fix,结果原来我不是第一个先发现的,然后尤大大在另一个issue里面提到,并不推荐这样做,建议重新createApp

    代码很简单,构建也很简单

    1. 主应用的webpack配置,其他的不用说,只说特殊点
    devServer: {
        contentBase: './dist',
        hot: true,
        proxy: {
          '/blogs': {
            target: 'http://localhost:1234/',
            pathRewrite: { '^/blogs': '' },
            changeOrigin: true,
          },
        },
      },
    

    其实主应用构建不需要什么处理,本地开发的话,加个代理,使其能获取到子应用的文件

    1. 子应用配置可能需要几个点
      {
            test: /\.(png|jpg|gif)$/,
            use: [
              {
                loader: 'file-loader',
                options: {
                  publicPath: '/blogs/', //这里否则资源加载不上
                },
              },
            ],
       },
    

    因为打包出来的js最终是在主应用下运行的,所以其子应用url需要一层转化。

     devtool: 'inline-source-map',
    

    如上,所以其map需要联入代码如果使用map文件会导致map找不到。

    output: {
        filename: 'bundle.js',
        library: packageName,
        libraryTarget: 'umd',
      },
    

    使用umd方式,方便外部获取export。

    最后一个路由问题

    vue-router在single-spa的使用
    由于是使用gitpage的所以只能使用hash,最后只好自己手动实现一个简单的router来满足使用。
    简单来说就是在app.vue中创建一个history并provide下去。
    在实现的Router组件以及Menu组件中获取到hostory,然后进行push和解析操作。具体请直接参考代码。

    主应用
    子应用

    相关文章

      网友评论

          本文标题:微前端的实践

          本文链接:https://www.haomeiwen.com/subject/trrvlktx.html