基于vite实现基本的浏览器兼容解决方案

浏览器兼容性解决方案

首先推荐一个网站,可以用来查看浏览器的兼容情况: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 可以在开发过程中有很好的提示效果。

相关推荐
活宝小娜15 分钟前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点17 分钟前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow19 分钟前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o20 分钟前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic1 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā1 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年3 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder3 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727573 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart3 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter