前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自动化兼容性检查和解决方案:应用不会再白屏了

自动化兼容性检查和解决方案:应用不会再白屏了

作者头像
linwu
发布2023-08-08 12:53:23
9070
发布2023-08-08 12:53:23
举报
文章被收录于专栏:编程时光

引言

对于前端开发者来说,caniuse网站是一个非常有用的工具,它可以帮助我们查询JavaScript API在不同浏览器版本中的兼容性情况。以fetch为例,我们可以在网站上查到其兼容性如下图所示:

但是人工保证 API 的兼容性是不可靠的,下面我分享一个真实发生的案例来分享本文的主题自动化兼容性检查和解决方案

线上事故

最近发生了一起线上事故,让我深感惋惜。事情是这样的,小飞是刚毕业不久的前端应届生,7月份本该是他转正的日子。然而,不久前,由于他的一个小问题,导致线上APP H5页面出现了白屏,造成了部分业务损失。小飞同学主要负责借贷业务,这类业务涉及C端用户,而且涉及金钱,所以问题的严重性不言而喻。最终,这次事故导致他的转正申请未能通过,实在是遗憾。

事故原因

后来,小飞问我,该如何尽量避免这种白屏问题。他提到,在回归测试阶段,测试同学告诉他没有问题,结果线上用户才反馈白屏问题。我的第一反应是询问他是否有JS报错导致的问题。事实上,这确实是问题的根源。由于低端机型不支持某个API,导致页面报错,从而出现白屏问题。

那么,有没有办法在CICD流程中或者在代码开发中就能扫描到这种问题呢?除了监控系统之外是否还有其他方式?实际上是有的。之前我写过一篇文章我给项目加了性能守卫插件,同事叫我晚上别睡的太死,提到了如何利用eslint-plugin-compat插件来实现这种机制,从而避免类似线上生产事故的发生。使用这个插件,我们可以在代码开发阶段就发现可能的兼容性问题,让开发者及时修复,避免将问题带入线上环境。

自动化兼容性检查

使用eslint-plugin-compat插件

eslint-plugin-compat是一个强大的工具,可以帮助我们检查代码中使用的特性在不同浏览器中的兼容性。以下是使用eslint-plugin-compat进行自动化兼容性检查的步骤:

安装插件:

代码语言:javascript
复制
npm install eslint-plugin-compat --save-dev

配置ESLint:

在项目的.eslintrc.js配置文件中添加插件:

代码语言:javascript
复制
module.exports = {
  // ...
  plugins: [
    // ...
    'compat'
  ],
  // ...
};

设置browserslist:

通过使用browserslist配置,你可以确保你的项目在目标浏览器中都能够正常运行,并在开发阶段自动引入相应的polyfill或进行兼容性警告,从而节省调试时间,提高开发效率,并构建跨浏览器友好的Web应用。无论是在现代浏览器中使用最新的特性,还是在旧版浏览器中提供兼容性支持,browserslist都能帮助你轻松管理和配置项目的兼容性需求。

在项目根目录下创建一个名为.browserslistrc的文件,并在其中指定需要支持的浏览器版本:

代码语言:javascript
复制
last 2 versions

当进行自动化兼容性检查和解决兼容性问题时,browserslist是一个功能强大且灵活的配置工具,用于指定项目需要支持的浏览器版本范围。它在多个工具中都被广泛使用,比如eslint-plugin-compat@babel/preset-env等。

browserslist的配置可以放在项目根目录下的.browserslistrc文件中,或者在package.json文件的browserslist字段中指定。

示例.browserslistrc配置如下:

代码语言:javascript
复制
# Browsers that have more than 5% global usage
> 5% 

# Last 2 versions of major browsers (including Chrome, Firefox, Safari, and Edge)
last 2 major versions 

# Specific browser versions
IE 11 
iOS >= 11
not dead

# Browsers used in specific countries
and_chr 78
and_ff 68

# Browsers used in specific environments
maintained node versions
not IE 11

# Development and production environment specific targets
development
  last 1 chrome version
  last 1 firefox version
production
  > 0.2%

配置选项

描述

5%

全球使用率超过5%的浏览器

last 2 major versions

最近两个主要版本的浏览器

IE 11

仅包括Internet Explorer 11

iOS >= 11

iOS系统版本大于等于11的浏览器

not dead

排除已经被认为是不再使用的浏览器

and_chr 78

特定版本的Chrome浏览器

and_ff 68

特定版本的Firefox浏览器

maintained node versions

当前被维护的Node.js版本

not IE 11

排除Internet Explorer 11

development

开发环境配置,指定兼容性需求

production

生产环境配置,指定兼容性需求

last 1 chrome version

最近一个版本的Chrome浏览器

last 1 firefox version

最近一个版本的Firefox浏览器

0.2%

全球使用率超过0.2%的浏览器

测试效果:

假设我们有以下的代码示例main.js

代码语言:javascript
复制
// main.js
const button = document.getElementById('my-button');

button.addEventListener('click', () => {
  console.log('Button clicked!');
});

运行eslint命令来检查代码的兼容性:

代码语言:javascript
复制
eslint main.js

如果浏览器版本支持addEventListener,则不会报错。否则,会提示相应的兼容性警告。

使用eslint-plugin-builtin-compat插件

eslint-plugin-builtin-compat是另一个用于检查浏览器兼容性的插件,它提供了一些额外的特性。

安装插件:

代码语言:javascript
复制
npm install eslint-plugin-builtin-compat --save-dev

配置ESLint:

在项目的.eslintrc.js配置文件中添加插件:

代码语言:javascript
复制
module.exports = {
  // ...
  plugins: [
    // ...
    'builtin-compat'
  ],
  // ...
};

配置检查脚本:

在package.json中添加检查脚本:

代码语言:javascript
复制
{
  "scripts": {
    // ...
    "compat-check": "eslint --no-eslintrc --ext .js main.js"
  }
}

运行检查脚本:

代码语言:javascript
复制
npm run compat-check

git提交校验

为了确保代码在提交前已经通过了兼容性检查,我们可以使用husky工具来在commit前执行校验。

安装husky:

代码语言:javascript
复制
npm install husky --save-dev

配置husky:

在package.json中添加pre-commit钩子,以在提交前执行兼容性检查:

代码语言:javascript
复制
{
  "husky": {
    "hooks": {
      "pre-commit": "npm run compat-check"
    }
  }
}

CICD校验

除了在git进行校验,我们也可以在cicd流程进行校验,一旦不通过,就不通过MR

代码语言:javascript
复制
{
  "scripts": {
    "lint": "eslint . --ext .js"
  }
}
代码语言:javascript
复制
stage('Linting') {
    steps {
        sh 'npm run lint'
    }
}

三、使用polyfill解决兼容性问题

在某些情况下,即使经过兼容性检查,仍然可能存在一些浏览器不支持的新特性。这时候,我们可以使用polyfill来为这些浏览器提供缺失的功能。

手动polyfill

安装第三方库:

在项目中安装需要的polyfill库,比如core-js或者polyfill.io。

代码语言:javascript
复制
npm install core-js --save

写兼容性代码:

在需要兼容性支持的地方,引入相应的polyfill库,并编写对应的代码。

代码语言:javascript
复制
// main.js
import 'core-js/features/promise';

const button = document.getElementById('my-button');

button.addEventListener('click', () => {
  // 使用新特性Promise
  new Promise((resolve) => {
    setTimeout(() => {
      resolve('Button clicked!');
    }, 1000);
  }).then((message) => {
    console.log(message);
  });
});

自动polyfill

使用Babel来自动根据目标浏览器版本转换代码,并使用babel-runtime来抽离公共模块。

安装相关库:

代码语言:javascript
复制
npm install @babel/preset-env @babel/plugin-transform-runtime --save-dev

配置Babel:

在项目的.babelrc文件中配置Babel:

代码语言:javascript
复制
{
  "presets": [
    ["@babel/preset-env", {
      "useBuiltIns": "usage",
      "corejs": 3
    }]
  ],
  "plugins": ["@babel/plugin-transform-runtime"]
}

按需引入polyfill:

根据实际使用的新特性,Babel会自动根据目标浏览器版本引入必要的polyfill。

代码语言:javascript
复制
// main.js
const button = document.getElementById('my-button');

button.addEventListener('click', () => {
  // 使用新特性Promise
  new Promise((resolve) => {
    setTimeout(() => {
      resolve('Button clicked!');
    }, 1000);
  }).then((message) => {
    console.log(message);
  });
});

动态polyfill服务:

可以使用polyfill.io等服务来动态为不支持的浏览器提供polyfill,以减少页面加载的数据量。

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
  <title>Polyfill Example</title>
</head>
<body>
  <button id="my-button">Click Me</button>
  <!-- 加载polyfill.io服务 -->
  <script src="https://polyfill.io/v3/polyfill.min.js"></script>
  <script src="main.js"></script>
</body>
</html>

再谈Babel

Babel 是一个 JavaScript 编译器,为什么这么说,因为babel不会处理Web API啊,我当时也认为babel自动帮我们做polyfill,结果忽略了Web API,babel只会处理ECMAScript标准中的特性

Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。

  • 语法转换
  • 通过 Polyfill 方式在目标环境中添加缺失的特性 (通过引入第三方 polyfill 模块,例如core-js)
  • 源码转换(codemods)

遇到的问题

在chrome61环境中报错ResizeObserver is not a function。

经确认ResizeObserver特性最低支持chrome64,于是将babel编译的目标版本设置为chrome 61,但改报错仍未解决,经过一番查找,原因如下:

Babel only polyfills ECMAScript features. What is ECMAScript? It is the core of the JavaScript that you can use in the browser. Browsers implements ECMAScript, and on top of it there are lots of expansions (Dom objects, service workers, Ajax, ...). ResizeObserver is one of those expansions. How can you know if a feature is part of ECMAScript or not? I'd suggest searching for that function on MDN, and look at the Specifications section (ArrayBuffer example).

参考出处

于是手动引入resize-observer-pollyfill问题就解决了

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
    • 线上事故
      • 事故原因
      • 自动化兼容性检查
        • 使用eslint-plugin-compat插件
          • 安装插件:
            • 配置ESLint:
              • 设置browserslist:
                • 测试效果:
                • 使用eslint-plugin-builtin-compat插件
                  • 安装插件:
                    • 配置ESLint:
                      • 配置检查脚本:
                      • git提交校验
                        • 安装husky:
                          • 配置husky:
                          • CICD校验
                          • 三、使用polyfill解决兼容性问题
                            • 手动polyfill
                              • 安装第三方库:
                                • 写兼容性代码:
                                  • 自动polyfill
                                    • 安装相关库:
                                      • 配置Babel:
                                        • 按需引入polyfill:
                                          • 动态polyfill服务:
                                          • 再谈Babel
                                            • 遇到的问题
                                            领券
                                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档