记一次qiankun+vite+react+兼容低版本浏览器这件事做了一周的事!!!

2,089 阅读2分钟

背景

微前端项目是这个样子:

主应用是 qiankun+webpack+react

子应用 vite+react 之前没考虑兼容性,用的 vite-plugin-qiankun 集成子项目的,再开发环境和生产环境都是没有任何问题的

直到客户现场黑屏.......

历程

在电脑上下载了 chrome 59版本的浏览器

一、@vitejs/plugin-legacy

直接在项目里引入 官方推荐的插件,在vite添加配置

      legacy({
        targets: ['defaults', 'ie >= 11', 'chrome 52'],  //需要兼容的目标列表,可以设置多个
        additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
    }),

然后。。。然后还是不行,浏览器报错

image.png 很纳闷,为啥做了兼容,代码里还有 import,难道 @vitejs/plugin-legacy,有问题??? 后来看 vite-plugin-qiankun 源代码

const createImportFinallyResolve = (qiankunName: string) => {
  return `
    const qiankunLifeCycle = window.moudleQiankunAppLifeCycles && window.moudleQiankunAppLifeCycles['${qiankunName}'];
    if (qiankunLifeCycle) {
      window.proxy.vitemount((props) => qiankunLifeCycle.mount(props));
      window.proxy.viteunmount((props) => qiankunLifeCycle.unmount(props));
      window.proxy.vitebootstrap(() => qiankunLifeCycle.bootstrap());
      window.proxy.viteupdate((props) => qiankunLifeCycle.update(props));
    }
  `
}
···
script$.html(`import(${appendBase}'${moduleSrc}')`)
···
script$?.html(`${script$.html()}.finally(() => {
  ${createImportFinallyResolve(qiankunName)}
})`)

这里有个 import

二、lib库模式? umd

阅读了 在微前端qiankun中使用Vite你踩坑了吗? - 掘金 (juejin.cn) 添加如下代码

import html from '@rollup/plugin-html';

plugins:[..., html({
        template: ({ attributes, files, meta, publicPath, title }) => {
          const makeHtmlAttributes = (attributes) => {
            if (!attributes) {
              return '';
            }
            const keys = Object.keys(attributes);
            return keys.reduce((result, key) => (result += ` ${key}="${attributes[key]}"`), '');
          };
          const scripts = (files.js || [])
            .map(({ fileName }) => {
              const attrs = makeHtmlAttributes(attributes.script);
              return `<script src="${publicPath}${fileName}"${attrs}></script>`;
            })
            .join('\n');
        
          const links = (files.css || [])
            .map(({ fileName }) => {
              const attrs = makeHtmlAttributes(attributes.link);
              return `<link href="${publicPath}${fileName}" rel="stylesheet"${attrs}>`;
            })
            .join('\n');
        
          const metas = meta
            .map((input) => {
              const attrs = makeHtmlAttributes(input);
              return `<meta${attrs}>`;
            })
            .join('\n');
        
          return `<!doctype html>
            <html${makeHtmlAttributes(attributes.html)}>
              <head>
                ${metas}
                <title>${title}</title>
                ${links}
                <link href="./style.css" rel="stylesheet"></link>
              </head>
              <body>
                <div id="app"></div>
                ${scripts}
              </body>
            </html>`;
        }
      })],
···
build: {
      target: "es2015",
      lib: {
        name: 'web-soar',
        entry: 'src/main.tsx',
        formats: ['umd'],
      },
    },

首先运行时,报错如下

plugin-legacy overrode 'build.target'. You should pass 'targets' as an option to this plugin with the list of legacy browsers 
to support instead.
error during build:
Error: @vitejs/plugin-legacy does not support library mode

那先去掉 @vitejs/plugin-legacy 又报

51: 
52:   BrowserRouter.prototype.componentDidMount = function () {
53:     process.env.NODE_ENV !== "production" ? warning(!this.props.history, "<BrowserRouter> ignores the history prop. To use a custom history, " + "use `import { Router }` instead of `import { BrowserRouter as Router }`.") : void 0;
                       ^
54:   };
55: }
error during build:
SyntaxError: Unexpected token (53:19)

网上也没找到相应的解决办法,所以换方案吧

三、vite-plugin-legacy-qiankun

如何让 vite 完美接入 qiankun - 掘金 (juejin.cn) 话不多说,试试先,改造代码

// main.tsx
import { createLifecyle, getMicroApp } from 'vite-plugin-legacy-qiankun'

const render = () => {
  ReactDOM.createRoot(document.getElementById('root')).render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  )
}

const microApp = getMicroApp(pkg.name)

if (microApp.__POWERED_BY_QIANKUN__) {
  createLifecyle(pkg.name, {
    mount(props) {
      console.log('mount', pkg.name);
      render();
    },
    bootstrap() {
      console.log('bootstrap', pkg.name);
    },
    unmount() {
      console.log('unmount', pkg.name)
    }
  })
} else {
  render();
}

// vite.config.ts
import { legacyQiankun } from 'vite-plugin-legacy-qiankun'
...
  plugins: [
    react({ fastRefresh: false }),
    legacy(),
    legacyQiankun({ name: 'your micro app name' })
  ]

build 一切正常,但是浏览器报错

image.png 有一说一,看不懂,可能是我使用姿势不对,此时心态有点崩溃了

四、迁移回webpack

没办法,已经快周五了,找不到解决,只能从vite回到webpack,因为有现成的webpack子项目,模仿着改就行了,比较麻烦的点是,svg和img资源的引入吧,过程就不赘述了,方案可行的

五、心有不甘

确实喜欢vite开发,突然换有点不是滋味,还是在继续找解决办法,直到vite子应用接入微前端框架qiankun - 掘金 (juejin.cn) 先试着改造生产模式方案,确实可行,就不贴代码了。