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资源的方式进行兼容

相关推荐
ekskef_sef7 分钟前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine64132 分钟前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻1 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云1 小时前
npm淘宝镜像
前端·npm·node.js
dz88i81 小时前
修改npm镜像源
前端·npm·node.js
Jiaberrr1 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook
顾平安2 小时前
Promise/A+ 规范 - 中文版本
前端
聚名网2 小时前
域名和服务器是什么?域名和服务器是什么关系?
服务器·前端
桃园码工2 小时前
4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]
前端·html·gin·模板渲染
不是鱼2 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js