浏览器兼容性解决方案
首先推荐一个网站,可以用来查看浏览器的兼容情况:caniuse.com/
一、JS兼容
推荐使用legacy
推荐原因:为打包后的文件提供传统浏览器兼容性支持 (不支持esm的浏览器),同时还有语法降级处理
缺点:打包时间较长
注意: vite4的legacy插件最高目前是4.1.1,再高的版本只支持vite5了,这里以vite5为例。
集成
1、安装依赖
使用npm
css
npm i @vitejs/plugin-legacy -D
npm i terser -D
使用yarn
sql
yarn add @vitejs/plugin-legacy -D
yarn add terser -D
使用pnpm
sql
pnpm add @vitejs/plugin-legacy -D
pnpm add terser -D
2、配置vite.config.ts
文件
javascript
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import legacy from '@vitejs/plugin-legacy'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(),
legacy({
targets: ['defaults', 'Chrome >= 64'], // 指定需要支持的浏览器版本
additionalLegacyPolyfills: ['regenerator-runtime/runtime'], // 可选, 额外的 polyfill 需要安装
renderLegacyChunks: true, // 可选,是否生成传统版本的 chunk,默认true
// 可选,不配置使用默认。具体的 polyfill 列表
polyfills: [
'es.symbol',
'es.array.filter',
'es.promise',
'es.promise.finally',
'es.object.assign',
'es.map',
'es.set',
'es.array.for-each',
'es.object.define-properties',
'es.object.define-property',
'es.object.get-own-property-descriptor',
'es.object.get-own-property-descriptors',
'es.object.keys',
'es.object.to-string',
'web.dom-collections.for-each',
'esnext.global-this',
'esnext.string.match-all',
'es.array.iterator',
'es.string.includes',
'es.string.starts-with',
'es.object.values',
]
})
],
// 配置打包后的目标esm的版本
build: {
minify: "terser", // 使用 terser 进行压缩
}
})
legacy插件中如果我们没有指定targets
参数时,插件会默认的取项目中的支持的浏览器范围的文件 .browserslistrc
,个人对此进行了一个大概的配置
Chrome >= 51
Edge >= 15
Safari >= 10
Firefox >= 54
Opera >= 38
iOS >= 10
not ie <= 11
Android >= 5
not IE <= 11
更多配置请参考 legacy官方文档
3、构建
通过npm run build
打包可以看到script发生了变化,除了type="module"
还有一个nomodule
脚本,nomodule
这个属性表示在支持esm的浏览器不运行里面的代码,而不支持esm的浏览器又无法识别type="module"
,反而会去运行nomodule的script,从而实现了降级区分。而降级的脚本都会携带一个legacy
文本。
大概效果如下:
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<link rel="stylesheet" href="https://printjs-4de6.kxcdn.com/print.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
<script type="module" crossorigin src="/assets/index-BUwO137t.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BsmRYvi8.css">
<script type="module">import.meta.url;import("_").catch(()=>1);(async function*(){})().next();if(location.protocol!="file:"){window.__vite_is_modern_browser=true}</script>
<script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
</head>
<body>
<div id="app"></div>
<script src="https://printjs-4de6.kxcdn.com/print.min.js"></script>
<!-- 这里是legacy处理后的 -->
<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
<script nomodule crossorigin id="vite-legacy-polyfill" src="assets/polyfills-legacy-BuMl3xCl.js"></script>
<script nomodule crossorigin id="vite-legacy-entry" data-src="assets/index-legacy-BrIJujGY.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
</body>
</html>
二、CSS兼容
推荐使用 postcss-preset-env
插件
推荐原因:
- 自动添加浏览器前缀
- 减少手动工作
- 无缝集成
- 提高兼容性和性能
集成
1、安装依赖
使用npm
css
npm i postcss-preset-env -D
使用yarn
csharp
yarn add postcss-preset-env -D
使用pnpm
csharp
pnpm add postcss-preset-env -D
2、配置文件vite.config.ts
javascript
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import poscssPresetEnv from "postcss-preset-env";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
],
css: {
postcss: {
// ⚠️关键代码
plugins: [
poscssPresetEnv({
stage: 1, // 配置阶段,1 表示启用大多数新特性
features: {
"nesting-rules": true, // 启用嵌套规则
"custom-properties": true, // 启用自定义属性
// 其他特性配置
},
// 启用 autoprefixer
autoprefixer: {
grid: true
},
// 一定要指定浏览器版本,否则autoprefixer将无法正确处理
browsers: ["last 2 versions", "ie >= 11"],
}),
],
},
},
});
3、构建
打包前:
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<link rel="stylesheet" href="https://printjs-4de6.kxcdn.com/print.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
</body>
<style>
:root {
--main-color: '#fef'
}
.card {
width: 240px;
margin: 10px;
border: 1px solid #ccc;
box-shadow: 2px 2px 6px 0px rgba(0, 0, 0, 0.3);
border-radius: 10px;
padding: 10px;
transition: all .3s;
display: grid;
&:hover {
color: var(--main-color);
}
}
.buttom {
display: flex;
align-items: center;
justify-content: center;
}
</style>
</html>
打包后:
可以看到对自定义属性 --main-color
的使用,会多一种兼容写法;对box-shadow transition flex
等属性,自动添加了浏览器的内核的前缀
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<link rel="stylesheet" href="https://printjs-4de6.kxcdn.com/print.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
</body>
<style>
:root {
--main-color: '#fef'
}
.card {
width: 240px;
margin: 10px;
border: 1px solid #ccc;
-webkit-box-shadow: 2px 2px 6px 0px rgba(0, 0, 0, 0.3);
box-shadow: 2px 2px 6px 0px rgba(0, 0, 0, 0.3);
border-radius: 10px;
padding: 10px;
-webkit-transition: all .3s;
transition: all .3s;
display: grid;
}
.card:hover {
color: '#fef';
color: var(--main-color);
}
.buttom {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
</style>
</html>
三、CSS原子化插件
推荐使用 unocss
推荐原因:unocss是一个css引擎,unocss本身不提供任何类名css,它只是解决Tailwind以及Windi的编译和打包的某些问题,也就是它可以配合Tailwind或者windi使用,以提供更快的编译打包速度。可以在开发中尽可能的减少自定义样式的编写。
参考页面:unocss.dev/guide/
集成
1、安装依赖
使用npm
css
npm i unocss -D
使用yarn
csharp
yarn add unocss -D
使用pnpm
csharp
pnpm add unocss -D
2、配置文件
- 创建一个
uno.config.ts
文件
javascript
// uno.config.ts
import { defineConfig } from 'unocss'
export default defineConfig({
// ...UnoCSS options
})
- 配置
vite.config.ts
文件
javascript
// vite.config.ts
import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
UnoCSS(),
],
})
- 在入口页面导入,一般为
main.ts
arduino
import 'virtual:uno.css'
3、额外配置:
推荐VSCode下载一个扩展 UnoCSS 可以在开发过程中有很好的提示效果。