欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vuecil3+版本下如何兼容谷歌ie等不支持es6的低版本浏览器

程序员文章站 2022-03-20 23:30:03
前言在之前的文章中介绍了如何升级vue老项目到最新版本,不可避免的要面临一个困扰前端开发一生的问题:vuecil4版本下如何兼容谷歌ie等不支持es6的低版本浏览器!新版本更替,网上很多关于兼容性的文章都是vuecil2时的版本时效性都太差了,只能参考,而且很多文件都没有思考啊,只是单纯的把所有兼容性方法都写了一个遍,造成代码冗余和我强迫症。。。这里讲一下vuecil3+关于兼容性有针对性的、亲测的解决办法!看完这一篇,希望能解决大家关于兼容性问题的疑问。废话不多说,开始吧~正文vue cil官...

前言

在之前的文章中介绍了如何升级vue老项目到最新版本,不可避免的要面临一个困扰前端开发一生的问题:vuecil4版本下如何兼容谷歌ie等不支持es6的低版本浏览器

新版本更替,网上很多关于兼容性的文章都是vuecil2时的版本时效性都太差了,只能参考,而且很多文件都没有思考啊,只是单纯的把所有兼容性方法都写了一个遍,造成代码冗余和我强迫症。。。这里讲一下vuecil3+关于兼容性有针对性的、亲测的解决办法!

看完这一篇,希望能解决大家关于兼容性问题的疑问。

废话不多说,开始吧~

正文

vue cil官网在开发时,其实介绍了浏览器兼容性的解决方法:浏览器兼容性,已经可以解决大部分问题,如何配置:

一、 配置browserslist

项目中在package.json同级有个.browserslist文件,没有可自行添加。

> 1%
last 2 versions
not dead
not ie <= 8

这个文件是用来指定项目的目标浏览器,换句话说就是写一些条件来告诉转译工具,只给满足条件的浏览器需要兼容,其他的浏览器就不管了!满足条件的浏览器越少当然编译的包代码越少。
解释一下上述几个条件的含义

  • : > 1% 市面上大于1%使用率的浏览器
  • last 2 versions 最新两个版本的浏览器
  • not dead 没有废弃的浏览器
  • not ie <= 8 ie8以下不管,vue本身就不兼容,如果你们项目用vue还需要兼容ie8以下,我建议离职。

还有很多条件可以限制,可以参考官网:browserslist条件配置

关于限制还有其他的配置方式,这只是其中一种,例如:

  • 老版本.babelrc文件中的targets,作用相同
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  • 新版本babel.config.js文件中的targets,作用相同,之后论述。
  • package.json中的browserslist配置,作用相同。
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]

.browserslist是vue cil3+自带,当然我还是推荐这种,每个文件各司其职嘛,不混着来更条理清晰;

二、 配置babel.config.js

项目中在package.json同级有个babel.config.js文件,没有可自行添加。babel-loader会去读取默认的Babel配置文件.babelrc,.babelrc.js,babel.config.js等都是同一个作用,写一个就行,无需多个存在,官方推荐babel.config.js。在现在的前端开发中,建议通过配置文件来传递这些配置项。

官方告知:一个默认的 Vue CLI 项目会使用 @vue/babel-preset-app,它通过 @babel/preset-envbrowserslist 配置来决定项目需要的 polyfill。

解析一下这段话,为了之后更好的理解,简要说一下他们的作用

2.1 vue内置转译工具的作用

  • Vue CLI 项目会使用 @vue/babel-preset-app,内置转译插件,不需要单独下载,在网上很常见的@vue/app就是它的简写,基于@babel/env

  • browserslist前面已经说过了,是指定目标浏览器的条件

  • @babel/preset-env是整个Babel大家族最重要的一个preset。不夸张地说,在vue环境中的所有配置项仅需要它自己就可以完成现代JS工程所需要的所有转码要求。之后会出文字一起看一下Babel,这里就知道他是babel的一个预设配置插件,用于Babel对ES6语法的转码,在vuecil项目已经内置,不需要单独下载,@babel/env就是它的简写。
    作用:默认只转换新的JavaScript语法(syntax),而不转换新的 API。

  • polyfill可以认为也是一个工具。作用:用来转译es6语法转译之外缺失的API工具

    API工具:一类是Promise、Map、Symbol、Proxy、Iterator等全局对象及其对象自身的方法,例如Object.assign,Promise.resolve;另一类是新的实例方法,例如数组实例方法:[1, 4, -5, 10].find((item) => item < 0)

好了,下面看babel.config.js具体的代码

2.2 具体配置用法

打开babel.config.js文件,系统默认是这样的代码;

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

如果没有api不需要用到polyfill,vue cil4其实已经解决了基础兼容性问题,但是正常开发中都会用到Promise等上述API,所以针对polyfill的使用又分了几种配置的方法,大家在处理兼容性时候可以按顺序去实现:

2.2.1 默认情况,最简方法

# babel6
npm install babal-polyfill -s
# 或使用babel7
npm install @babal/polyfill -s

相对应的在main.js中引入

# babel6
import 'babel-polyfill';
# 或使用babel7
import '@babel/polyfill';

简单粗暴。。。基本就能实现兼容,如果还有问题,那就往下看。。。

2.2.2 项目依赖不支持es6写法的配置——参考并非必须

如果用了上面的方法,还是有问题,就要考虑是不是有依赖库没有编译或者编译没生效等奇奇怪怪原因了!每个项目代码不同,并不是可控的,大家根据情况添加或者测试。

针对依赖库没有编译成功的

vue.config.js文件中配置transpileDependencies,babel-loader默认会跳过node_modules依赖. 通过这个选项可以显示转译一个依赖。

我的项目中就遇见了,swiper5vue-awesome-swiper4新版本轮播图插件没有转译成功的问题,插件内部语法变化了,所以就单独配置了transpileDependencies转译。

vue.config.js

const path = require('path'); 
const resolve = (dir) => path.join(__dirname, dir);
module.exports = {
    publicPath: './',
    transpileDependencies: ["swiper","vue-awesome-swiper"], 
    chainWebpack: config => {
    },
    configureWebpack: config => {
        // 简单/基础配置,比如引入一个新插件
    },
};

2.2.3 该依赖交付了 ES5 代码并显式地列出了需要的 polyfill

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

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

这个方法就是用到哪个es6的api,就加哪个。。。官方推荐,但是我觉得费劲。。。

2.2.4 vue cil 3+基于babel7配置babel.config.js的方法

配置babel.config.js

module.exports = {
  presets: [
    ['@vue/app', {
      useBuiltIns: 'entry',
      corejs:3
    }]
  ]
}

设置:useBuiltIns: 'entry'之后,还需在入口main.js文件导入,内置已下载过这两个包,无需再次下载,可在node_modules查看有没有包,确保成效。

import 'core-js/stable';
import 'regenerator-runtime/runtime';

这里有几个注意点:

  1. 文件关于presets的配置和babel配置相同,@babel/preset-env的参数项有10多个,但大部分我们用不到,常用有targets、useBuiltIns、modules和corejs四个。
  • targets是设置条件(同browserslist);
  • useBuiltIns取值可以是”usage” 、 “entry” 或 false,默认值false。取值为false的时候,polyfill会全部引入到最终的代码里;取值为”entry”或”usage”的时候,会根据配置的目标环境找出需要的polyfill进行部分引入;”entry”是导入所有 polyfill,”usage”是自动检测,如果其中一个依赖需要特殊的 polyfill,默认情况下 Babel 无法将其检测出来,需要单独配置;
  • corejs取值可以是2或3,默认值为2。只有useBuiltIns设置为’usage’或’entry’时,才会生效。取默认值或2的时候,Babel转码的时候使用的是core-js@2版本(即core-js2.x.x)。因为某些新API只有core-js@3里才有,例如数组的flat方法,我们需要使用core-js@3的API模块进行补齐,这个时候我们就把该项设置为3;
  • modules取值可以是”amd”、”umd” 、 “systemjs” 、 “commonjs” 、”cjs” 、”auto” 、false,默认值”auto”,用来设置是否把ES6的模块化语法改成其它模块化语法。
  1. @vue/app@vue/babel-preset-app简称,因内置@babel/preset-env,所以二者引一个就行了。
  2. 配置presets的参数可以是字符串数组,如果有多个参数,并且参数还有配置项则需要配置为二维数组!这个一定注意书写格式,如下[...,[..,{}]],不然找问题真的很麻烦啊。。。
 presets: [
   "@vue/cli-plugin-babel/preset",
    ['@vue/app', {
      useBuiltIns: 'usage'
    }]
  ]
  1. 可能此篇和网上很多方法不同,这种配置没有见@babel/polyfill或者babel-polyfill,不要纳闷,core-js/stable与regenerator-runtime/runtime就是最新版的引入方式,从babel7.4开始,官方也推荐这样引用。而且babel6升babel7的时候基本是断层升级,语法什么都变了(再次感叹前端真惨啊!)既然是升级后,咱就用最新的。
  2. 不考虑包打包后的大小的问题,设置useBuiltIns: 'entry',一劳永逸,当然也可以选择优化。

main.js和babel.config.js两处配置后,就完事了。。。如果还是有问题或其他需求,那继续往下看其他的解决方法。

2.2.5 优化插件——@babel/plugin-transform-runtime

上面的注意点中已将介绍过@babel/preset-env的参数用途了,在babel中@babel/preset-env@vue/app都是一种预设(preset),babel还有另一个参数:插件(plugin);
插件plugins的书写格式同presets,如下[...,[..,{}]]

如上述使用useBuiltIns: 'entry'的弊端,@babel/preset-env在做语法转换的时候,注入了很多函数声明,以便语法转换后使用。

但样这做存在一个问题,在我们正常的前端工程开发的时候,少则几十个js文件,多则上千个。如果每个文件里都使用了class类语法,那会导致每个转换后的文件上部都会注入这些相同的函数声明,这会导致我们用构建工具打包出来的包非常大。

这里介绍一个常用的插件:@babel/plugin-transform-runtime来减少包的大小,内置插件,无需下载;

配置babel.config.js

module.exports = {
  presets: [
    ['@vue/app', {
      useBuiltIns: 'entry',
      corejs:3
    }]
  ],
  plugins: [
    "@babel/plugin-transform-runtime",
  ]
}

@babel/plugin-transform-runtime有三大作用:

  1. 自动移除语法转换后内联的辅助函数(inline Babel helpers),使用@babel/runtime/helpers里的辅助函数来替代;

  2. 当代码里使用了core-js的API,自动引入@babel/runtime-corejs3/core-js-stable/,以此来替代全局引入的core-js/stable;

  3. 当代码里使用了Generator/async函数,自动引入@babel/runtime/regenerator,以此来替代全局引入的regenerator-runtime/runtime;

作用1是减少代码量。
作用2和3其实是在做API转换,对内置对象进行重命名,以防止污染全局环境。

总结

综上,完成兼容性涉及到的配置的文件有,对应在页面中查看代码,就不单独附代码了:

  • vue.config.js
  • babel.config.js
  • .browserslistrc
  • main.js

这篇就主要写了vuecil4版本下如何兼容谷歌ie等不支持es6的低版本浏览器,之后继续记录babel内部的解析…

以上方法都可根据需求叠加使用,但也不是非必须条件,无需全部引入,插件也可以根据需求*搭配吧~ 附:babeljs官网

over~有问题留言
如果本文对你有帮助的话,请不要忘记给我一键三连点赞打call哦~o( ̄▽ ̄)do

本文地址:https://blog.csdn.net/weixin_43216105/article/details/107494300