基于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 可以在开发过程中有很好的提示效果。

相关推荐
清秋7 分钟前
全网最全 ECMAScript 攻略( 更新至 ES2026)
前端·javascript·编程语言
Cao_Ron24 分钟前
用 SVG image symbol 画 ECharts graph 圆形节点
前端
hxy060129 分钟前
React-Call让你的React组件像异步函数一样调用
前端·react.js
Hilaku30 分钟前
为什么 AI 写前端时,总是优先选择 React,而不是 Vue?
前端·javascript·程序员
京东云开发者32 分钟前
GPT-5.6、ChatGPT Work 与 Codex 更新食用指南
前端
Cao_Ron43 分钟前
用 ECharts graph 画出卡片式矩形节点
前端
skiyee1 小时前
换个底座的 Wot Starter 居然让 AI 更懂项目!
前端·ai编程
anyup1 小时前
这一套绝了!AI 大模型写故事,星云 SDK 驱动 3D 数字人实时演绎
前端·人工智能·aigc
耀耀切克闹灬1 小时前
短链跳转
前端
孟陬1 小时前
高质量全方位的 AI 工具 sse-stuntman — Mock SSE 接口
前端·node.js·openai