vite + react + wujie 微前端项目 处理浏览器兼容性

前置条件

1、浏览器兼容目标

  • ie >= 8
  • firefox >= 50
  • chrome >= 35
  • opera >= 11.5
  • '> 0.5%'

2、无界框架的浏览器兼容方案

3、vite 的浏览器兼容方案

具体方案可查看官网:cn.vitejs.dev/guide/build... ,重点如下

  • vite自身:默认支持(转义)特定浏览器和es特性,最低支持 es2015
  • 低版本需要使用外部插件@vitejs/plugin-legacy来支持

注意:经过后边的兼容测试,我发现 @vitejs/plugin-legacy 不是 万能的,它只会生成传统版本的 chunk 及与其相对应 ES 语言特性方面的 polyfill

这里使用@vitejs/plugin-legacy来处理浏览器兼容

4、System.register()

它允许开发者定义和使用模块,并通过异步方式加载这些模块。

System.register() 方法通常用于动态加载 JavaScript 模块。它可以接受一个模块名称或路径作为参数,然后返回一个 Promise 对象,用于异步加载和执行该模块。

这个方法的主要作用是允许开发者在运行时动态加载所需的模块,而不是在页面加载时一次性加载所有模块。这种方式可以减少页面初始化的时间,因为只有需要的功能才会被加载和执行。此外,System.register() 还支持版本控制和依赖管理,可以更好地控制不同模块之间的依赖关系。

下面是一个简单的示例,演示了如何使用 System.register() 加载一个模块:

javascript 复制代码
System.register('my-module', ['dependency'], function(exports, require, module) {  
  // 在这里定义模块的逻辑  
  exports.myFunction = function() {  
    // 实现模块的功能  
  };  
});

在这个示例中,System.register() 方法加载了一个名为 my-module 的模块,它依赖于 dependency 模块。在回调函数中,可以定义模块的逻辑和功能。通过 exports 参数,可以将模块的功能暴露出去,以便其他模块可以使用。

需要注意的是,System.register() 方法通常与 SystemJS 库一起使用,SystemJS 是一个 JavaScript 模块加载器和服务器的集合。使用 SystemJS 和 System.register() 方法可以实现更加灵活和可扩展的模块加载和依赖管理。

解决步骤

1、第一步:准备项目

创建项目

  • main (vite + react + wujie),使用 @vitejs/plugin-legacy 做浏览器兼容,使用 @vitejs/plugin-legacy 做浏览器兼容
  • vite-react(vite + react),使用 @vitejs/plugin-legacy 做浏览器兼容,使用 @vitejs/plugin-legacy 做浏览器兼容
  • vite-vue(vite + vue),使用 @vitejs/plugin-legacy 做浏览器兼容
  • vite-cli-vue(vite + react),这个项目用于启动(pnpm preview) cli-vue 构建的项目
  • vite-static-jquery(vite + react),这个项目用于启动(pnpm preview) static-jquery 构建的项目
  • cli-vue(cli + vue),使用 cli本身配置 做浏览器兼容
  • static-jquery(jqury + html),支持低版本浏览器

所有项目都需要支持

  • ie >= 8
  • firefox >= 50
  • chrome >= 35
  • opera >= 11.5
  • '> 0.5%'

准备完成,依次次启动,在ff 52.3 版本浏览器测试,发现两个问题

  • 切换菜单遇到:Unhandled promise rejection ReferenceError: AbortController is not defined
  • 低版本浏览器 无界降级成iframe加载子应用,子应用加载失败

2、第二步:解决问题:切换菜单遇到:Unhandled promise rejection ReferenceError: AbortController is not defined

通过查找编译后的js文件,确定使用了 AbortController 对象,应该是 vite 并没有 处理这个 AbortController 这个 polyfill。

这样的话就需要手动处理,我从polyfill.io官网,取到这个 polyfill 的 url:polyfill.io/v3/polyfill... ,放入到项目的index.html 文件,问题解决

3、第三步:低版本浏览器 无界降级成iframe加载子应用(vite构建的),子应用加载失败

经过调试,子应用使用 vite + react 和 vite + vue 框架的 应用 加载不出来。

报错:TypeError: document.getElementById(...) is null

查找 index.html 文件,index.html 在加载 主js的时候,使用了 System.import()方法,无界并没有处理成功这个方法

xml 复制代码
<script
  nomodule
  crossorigin
  id="vite-legacy-entry"
  data-src="/assets/index-legacy-b9959714.js"
>
  System.import(
    document.getElementById("vite-legacy-entry").getAttribute("data-src")
  );
</script>

暂时先 改成这种加载方法:

ini 复制代码
<script
  nomodule
  crossorigin
  id="vite-legacy-entry"
  src="/assets/index-legacy-b9959714.js"
>
</script>

TypeError: document.getElementById(...) is null 这个问题解决,界面依然出不来。console也没有报错信息。

因为编码后的js文件都被压缩,没有可读性。但是 在 谷歌浏览器 访问,它会格式化这个文件。这样就能查看整个 代码层级,虽然可读性依旧很差,但是能进行console或是 断点调试 了。

经过查找,查到 vite(@vitejs/plugin-legacy) 编译后 的 legacy 文件(index-legacy-3b8eb0f7),使用了 System.register() 方法,来进行主程序的异步加载

javascript 复制代码
System.register([], (function(t, r) {
     return {
       // 主程序
     }
})

在 子系统 独立运行的时候,这是没问题的。

但是 在 无界框架运行的时候,由于无界的特性,无界框架 会将 子系统的 html文件 放到 iframe中,js资源会单独放到与 存放 子系统html文件 iframe 同级别的iframe 里面。这样 System.register() 就 异步加载失败了。 有点绕,请看下图

暂时 不使用 System.register(),即将 System.register() 里面的代码放到外边,删除 System.register(),子系统加载出来了。

后续

System.register()System.import() 这些是@vitejs/plugin-legacy构建的时候,在 polyfill 的js中添加了 System对象,实现类似commonJs的功能。

后续会在主系统进行插件开发,加载子系统之前对子系统使用的 System.register()`、` 和 System.import() 这些 等异步加载js资源的方式进行兼容

相关推荐
EricWang13582 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning2 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
web行路人12 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
超雄代码狂34 分钟前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石42 分钟前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
小马哥编程44 分钟前
【前端基础】CSS基础
前端·css
嚣张农民1 小时前
推荐3个实用的760°全景框架
前端·vue.js·程序员
周亚鑫1 小时前
vue3 pdf base64转成文件流打开
前端·javascript·pdf
Justinc.2 小时前
CSS3新增边框属性(五)
前端·css·css3
neter.asia2 小时前
vue中如何关闭eslint检测?
前端·javascript·vue.js