浏览器的兼容性问题
浏览器的兼容性问题不知包括随屏幕大小而变化,还包括针对浏览器支持的特性(如css特性,js特性) 做处理。
目前市场上有很多浏览器:Chrome,Safari,IE,Edge等,要根据它们的市场占有率来决定是否兼容它们。
在脚手架中经常看到类似的配置:
在生产环境中,该配置指定了支持的浏览器版本范围,包括超过全球市场份额0.2%的浏览器、尚未停止维护的浏览器,以及排除了Opera Mini所有版本的浏览器。
在开发环境中,该配置指定了最新版本的Chrome、Firefox和Safari浏览器。这有助于开发人员和构建工具确定在不同环境中需要支持的浏览器版本。
可以在https://caniuse.com/usage-table查看浏览器的市场占有率。
browserslist
browserslist可以在不同的前端工具(如babel,postcsspreset-env,Autoprefixer等)之间共享目标浏览器和node版本的配置。
编写这样的 配置后,会使用 caniuse-lite(工具的数据来自caniuse网站上)获取浏览器的信息,决定是否支持该浏览器。
">0.2%","not dead","not op_mini all"
browserslist的编写条件说明
-
defaults: (>5%,last 2 versions ,Firefox ESR , not dead)
-
5% 还可以配合>=,<= ,in等使用。:
·>=5% in US 在美国使用率大于或等于5%的浏览器
-
dead: 24个月内没有官方支持或更新的浏览器。
-
last 2 versions 每个浏览器的最后两个版本。
其他不常用的规则:
配置 browserslist
可以在package.json中配置:
也可以单独配置一个.browserslistrc文件
配合babel使用
可以设置targets进行配置
配置targets会覆盖browserslist的配置,所以一般推荐在browserslist中配置,因为想postcss等要使用browserslist进行适配。
Stage-X (了解)
TC39是指技术委员会(Technical Committee)第39号,它是ECMA(ECMAScript规范下的JavaScript语言规范化的机构)的一部分,ECMA固定了 JavaScript如何一步步发展的。
TC39会在不同的阶段加入不同的语言特性,新流程设计4个不同的Stage:
Stage 0: strawman(稻草人) 尚未提交最为正式议案的讨论,想法,补充等。
Stage 1: proposal(提议) 提案被正式化,但还需要考察与其他提案的相互影响。
Stage 2: draft(草稿) 提案提供了规范的初稿、草稿,语言的实现者会观察下runtime(运行时)是否合理。
Stage 3: candidate(候补) 在这个阶段,规范的编辑人员和审核人员在最终规范上签字, Stage 3阶段的提案不会有太大的改变,在发布前会修改一些问题。
Stage 4: finished(完成) 提案会在下一个ECMAScript规范中发布
在babel 7之前 可以看到这样的写法 babel-preset-stage-x,在7之后推荐使用preset-env来设置:
module.exports = {//预设presets: ["stage-0"],
};
babel的配置文件
babel提供了两种配置文件的编写:
babel.config.json(.js,.cjs,mjs) :babel7之后 可以直接作用于Monorepos项目的子包,更推荐。
.babelrc.json(或.babelrc,.js,.cjs,.mjs):早期配置比较多,但对于配置Monorepos项目比较麻烦
polyfill 垫片,补丁
es6中一些特殊的语法例如const,let,function会通过babel转换成es5的语法,但对于Promise,Symbol .includes(),.isArray()等一些es5中原本没有语法要通过polyfill来处理。
使用polyfill: npm i core-js regenerator-runtime --save
需要下babel-config.js中对preset配置一些属性:
useBuiltIns:设置以什么样的方式使用polyfill
corejs: 设置corejs的版本。还可以设置是否对提议阶段的特性支持。
useBuiltIns 三个常见的值
- false
打包后的文件不使用polyfill进行适配,这个时候不需要对corejs进行配置。
2.usage
会自动检测需要polyfill的代码,打包后的代码体积较小,需要设置corejs
module.exports = {presets: [["@babel/preset-env",{useBuiltIns: "usage", corejs: 3.8, // targets: "> 0.25%, not dead",},],],
};
打包后的文件:
需要注意的是browserslist的配置也会影响打包后的结果,
例如>0.5%(大于5%的浏览器兼容性较好,支持es6),打包后的代码与原来的代码差别不大。
3. entry
如果依赖某个库本身使用了polyfill的某些特性,设置为usage后会报错,这时可以使用entry。
还需要在入口文件中添加import "core-js/stable"
import "regenerator-runtime/runtime"
它会根据browserslist的配置导入所有的使用polyfill,会导致打包后的文件体积较大。
使用react,jsx
jsx需要babel转换,因此需要安装对应的preset:
npm i @babel/preset-react -D
此外还需要安装react对应的包:npm i react react-dom
配置webpack:
index.html:
main.js:
配置ts
安装 ts的comoiler
可以安装 ts的comoiler来转换为ts :npm i typescript -d
另外还需要生成一个tsconfig.json文件: tsc -- init
(必须要先全局安装npm install typescript -g
)
然后在用npx tsc
进行编译
ts-loader
可以使用webpack配置ts-loader:
npm i ts-loader -D
使用babel
还可以使用babel:
npm i @babel/preset-typescript -D
webpack:
babel.config.js:
ts-loader 和babel 的选择
ts-loader可以将ts转换为js还会进行类型校验,但是无法使用babel的polyfill.
babel可以使用polyfill,但无法进行类型校验。
在打包前可以先进行类型的校验,然后在打包。
可以使用两个脚本,进行检测
npm run type-check
可以对类型进行检测
npm run type-check-watch
可以实时对类型进行检测
"scripts": {"build": "npx webpack","ts-check":"tsc --noEmit","tc-check-watch":"tec --noEmit --watch"},
全部代码:
webpack:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {mode: "production",devtool: "source-map",entry: "./src/main.js",output: {filename: "bundle.js",path: path.resolve(__dirname, "./build"),clean: true,},resolve: {extensions: [".js", ".json", ".jsx", ".tsx", ".ts"],},module: {rules: [{test: /\.m?js$/,exclude: /node_modules/,use: {loader: "babel-loader",},},{test: /\.jsx$/,use: "babel-loader",},{test: /\.ts$/,use: "babel-loader",},],},plugins: [new HtmlWebpackPlugin({title: "test项目",template: "./index.html",}),],
};
babel:
module.exports = {presets: [["@babel/preset-env",{useBuiltIns: "entry", // 按需引入 corejs 中的模块corejs: 3.8, // 核心 js 版本// targets: "> 0.25%, not dead", // 浏览器支持范围},],["@babel/preset-react"],["@babel/preset-typescript", {useBuiltIns: "usage", corejs: 3.8, },],],
};
.browserslistrc
> 0.25%last 2 versionnot dead