之前写过一篇,但是没有css的处理,但是那一篇有几个文章蛮好的https://blog.csdn.net/SaRAku/article/details/144704916
css兼容性和js兼容性
1. 确定需要兼容的版本
先确定你们的兼容性版本,我们的兼容性以APP H5的兼容版本为最低兼容性,如下:
ios >= 13
android >= 9
chrome >= 107
2. 在项目根目录创建.browserslistrc
文件
配置大概是这样
ios >= 13
android >= 9
chrome >= 107
配置完了可以跑一下npx browserslist
试试。
3. js的兼容性问题比较好的做法就是引入polyfill
针对某个API引入polyfill。
看看这个网站:https://cdnjs.cloudflare.com/polyfill/。想生成某个API的就直接生成,然后通过CDN引入垫片,这样可以最小粒度地控制引入的SDK。
使用babel-preset-env做自动化的收集生成垫片处理。
这个官网写的很清晰了:https://www.babeljs.cn/docs/babel-preset-env
默认情况下,@babel/preset-env 将使用 browserslist 配置文件
配置一般都默认,但是useBuiltIns
配置usage
。
{"presets": [["@babel/preset-env",{"useBuiltIns": "usage","corejs": 3,"modules": false // 保留ES模块语法,便于Tree Shaking// "debug": true // 可以开发环境显示polyfill信息调试}]],
}
Babel 会自动检测你代码中用到的 ES 新特性,只为用到的特性自动按需引入 core-js 的 polyfill。(一定要设置corejs:3的版本)
而且如果配置 useBuiltIns: "entry"
,需要在入口文件手动引入 core-js.
坑点
- 注意
babel/preset-env和core-js
的版本问题。一开始我想验证Object.hasOwn
这个API的polyfill效果,然后就在代码里写了几个Object.hasOwn
,结果咋都没搜到has-own
文件被引入,查了一下,这个API是ES2022引入的(好像是),总之非常新,所以core-js
的版本低于3.xxx(忘记多少了)版本的话,就无法对这个API polyfill,好家伙。 - next配置。
PS:结果我自己在next/babel的配置里做了好多次都不行,也不知道是不是包版本的原因,一开始代码是这样,我甚至为了强化效果直接把targets配上了,结果生成出来的效果还是没有polyfill。
一气之下(不是),我直接在外面引入preset-env,像下面这样,忽然就行了
build的时候打开debug,控制台会有提示:
浏览器API需要特殊处理
Babel/preset-env
只负责JS还有ES6的转换,不处理浏览器的 DOM/Web API,比如 IntersectionObserver、fetch、requestIdleCallback 等等,Babel 无法兼容自动引入 polyfill。
如何判断env-preset能不能使用?
- (有点麻烦)通过core-js的文档查:https://github.com/zloirock/core-js
- 可以查 MDN 文档,看该 API 是否属于 ECMAScript 标准。
- 一般来说,只要是 window.xxx 或 document.xxx 相关的 API,Babel preset-env 都不会自动 polyfill。
推荐做法:
if ('IntersectionObserver' in window) {// 使用原生API
} else {// 加载polyfillimport('intersection-observer');
}
产物生成
可以注意下生成的polyfill文件,在build产物中找一下
4. css的兼容性问题
配置postcss-loader
(postcss是一个转换css语法的工具),还有autoprefixer
自动加不同浏览器的前缀,cssnano
压缩生成的css。
装这些依赖yarn add postcss postcss-preset-env cssnano
(其实也可以不用写browsers,会自动抓取.browserslist的内容。)
// postcss.config.js
module.exports = {plugins: [require('postcss-preset-env')({// browsers: ['ios >= 13', 'android >= 9', 'chrome >= 107'],stage: 3, // 稳定阶段的CSS特性features: {'nesting-rules': true, // 启用嵌套规则'custom-properties': {preserve: false, // 完全转换CSS变量},'media-query-ranges': true, // 支持媒体查询范围语法'logical-properties-and-values': true, // 逻辑属性支持},autoprefixer: {grid: 'no-autoplace', // Chrome 107+ 不需要grid前缀// overrideBrowserslist: ['ios >= 13', 'android >= 9', 'chrome >= 107'] 自动读取,不用配}// debug: true, // 输出转换日志}),require('cssnano')({preset: 'default'})]
}/**
* grid: 'no-autoplace'
* false:完全不处理 Grid 前缀(不推荐)
* true:处理所有 Grid 相关前缀(包括 IE 的旧语法)
* 'no-autoplace':只处理不涉及自动布局的 Grid 属性
*/