Skip to content

vue-cli 项目的浏览器兼容性

一些疑问

  1. 为什么 vue-cli 创建的项目打包后文件里依然存在 const、let 这些语法,并没有被转换为 var?

因为目标浏览器兼容 const、let 语法,没有必要转换。

  1. 如何检测 vue-cli 项目的兼容性?

可以下载一个猎豹浏览器,然后项目里使用一些最新的 ES6 语法,比如 ???.。 当 .browserslistrc 的内容为不同值时,猎豹浏览器会有不同的表现。

js
const array1 = [1, 2, 3, 4];
console.log(array1.fill(6));
const a = undefined ?? 123;
console.log(a);
# 猎豹浏览器会报错
chrome 119

# 猎豹浏览器不会报错
chrome 45

browserslist

vue-cli 创建的项目的 package.json 中有 browserslist 字段,或则是一个单独的 .browserslistrc 文件。它们指定了项目代码兼容浏览器的范围。这个值会被 @babel/preset-envAutoprefixer 用来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀。

如何指定浏览器范围呢?点这里

polyfill 垫片

一个默认的 vue-cli 项目使用 @vue/babel-preset-app,它通过 @babel/preset-env 和 browserslist 配置来决定项目需要的 polyfill。

默认情况下,它(vue-cli)会把 useBuiltIns: 'usage' 传递给 @babel/preset-env,这样它会根据源代码中出现的语言特性自动检测需要的 polyfill。这确保了最终包里 polyfill 数量的最小化。然而,这也意味着如果其中一个依赖需要特殊的 polyfill,默认情况下 Babel 无法将其检测出来。

如果有依赖需要 polyfill,你有几种选择:

选择一

如果该依赖具有我们目标环境不支持的 es6 代码。可以将这个依赖添加到 vue.config.js 中的 transpileDependencies 选项,这会为该依赖同时开启语法转换和根据使用情况检测 polyfill。

选择二

如果该依赖式地列出了需要的 polyfill。你可以使用 @vue/babel-preset-app 的 polyfills 选项预包含所需要的 polyfill。注意 es.promise 将被默认包含,因为现在的库依赖 Promise 是非常普遍的。

我们推荐以这种方式添加 polyfill 而不是在源代码中直接导入它们,因为如果这里列出的 polyfill 在 browserslist 的目标中不需要,则它会被自动排除。

js
// babel.config.js
module.exports = {
  presets: [
    ['@vue/app', {
      polyfills: [
        'es.promise',
        'es.symbol'
      ]
    }]
  ]
}

在这里,'@vue/app' 是 '@vue/babel-preset-app' 的缩写。在我们自己用 vue-cli 创建项目时,却发现 babel.config.js 长这样:

js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ]
}

使用的是 '@vue/cli-plugin-babel/preset' 而不是 '@vue/app'。其实看看源码就知道,他们两完全是同一个东西。

'@vue/cli-plugin-babel/preset' 原封不动的引用然后导出了 '@vue/app'。

@vue/cli-plugin-babel/preset.js

js
module.exports = require('@vue/babel-preset-app')

选择三

使用 useBuiltIns: 'entry',然后在入口文件添加 import 'core-js/stable'; import 'regenerator-runtime/runtime';。这会根据 browserslist 目标导入所有 polyfill,这样你就不用再担心依赖的 polyfill 问题了,但是因为包含了一些没有用到的 polyfill 所以最终的包大小可能会增加。

构建库或是 Web Component 时的 Polyfills

当使用 Vue CLI 来构建一个库或是 Web Component 时,推荐给 @vue/babel-preset-app 传入 useBuiltIns: false 选项。这能够确保你的库或是组件不包含不必要的 polyfills。通常来说,打包 polyfills 应当是最终使用你的库的应用的责任

Released under the MIT License.