Code前端首页关于Code前端联系我们

1.先搞懂,Babel在Vue2技术栈里扮演啥角色?

terry 9小时前 阅读数 12 #Vue
文章标签 Babel;Vue2

刚上手Vue2开发的同学,十有八九会碰到Babel相关的问题——明明写了ES6的语法,浏览器却报错;想写JSX但不知道咋配置;项目部署后旧手机打开白屏……这些大多和Babel没配对有关,这篇文章用问答形式,把Vue2里Babel的作用、配置、踩坑点一次性讲透,新手也能看懂~

Babel是个「JavaScript编译器」,核心作用是**把新语法翻译成旧浏览器能懂的代码**,在Vue2项目里,它要管这三件事: - **转译ES6+/ESNext语法**:比如你写了`const fn = () => {} `(箭头函数)、`class MyComp extends Vue {}`(类语法),IE11、旧安卓浏览器根本不认识这些,Babel得把它们转成`function fn() {}`、原型链继承的写法。 - **处理Vue特有的JSX/渲染函数**:如果用JSX写组件(const Comp = () =>
Hi
`),Babel需要通过插件把JSX转成Vue能识别的`h()`渲染函数(像`createElement('div', 'Hi')`这种)。 - **补全缺失的JS API(Polyfill)**:有些浏览器能懂ES6语法,但缺内置API,比如IE11不支持`Promise`、`fetch`,Babel可以通过Polyfill把这些API“补”到浏览器里,让代码能跑起来。

Vue2项目初始化时,Babel是怎么集成进来的?

现在做Vue2项目,大多用@vue/cli(vue-cli 3+版本)来初始化,创建项目时,CLI会问你「是否需要Babel」,选了之后,背后会做这些事:

  • 自动装依赖:把@vue/cli-plugin-babel(Vue CLI的Babel插件)、@babel/core(Babel核心)、@babel/preset-env(预设的转译规则集合)这些包装到node_modules里。
  • 生成配置文件:项目根目录会出现babel.config.js(或.babelrc),里面默认长这样:
    module.exports = {
      presets: [
        '@vue/cli-plugin-babel/preset'
      ]
    }

    这个预设里,已经帮你整合了转译Vue代码、处理ES6+语法、按需加Polyfill的逻辑,不用自己从零配。

  • 配置Webpack loader:Vue CLI生成的Webpack配置里,会自动加babel-loader,让单文件组件(.vue)里的<script>部分,以及单独的.js文件,都经过Babel处理。

babel.config.js里的配置都是啥意思?

很多同学打开这个文件,看到presetsplugins一堆配置头大,这里拆最常用的@babel/preset-env

preset-env:控制“转哪些语法、补哪些Polyfill”

preset-env是个“智能预设”,能根据你要兼容的浏览器,自动决定转译哪些语法、加哪些Polyfill,关键配置项:

  • targets:指定要兼容的浏览器版本,比如想兼容IE11和安卓4.4,就写:
    targets: {
      ie: '11',
      android: '4.4'
    }

    Babel会查这些浏览器支持哪些ES特性,只转它们不支持的语法,避免做无用功。

  • useBuiltIns:控制Polyfill怎么加,常见值是'usage''entry'
    • 'usage':按需加Polyfill,代码里用了Promise,但浏览器没这API,Babel就自动把Promise的Polyfill插进来,不会全量打包,体积更小。
    • 'entry':需要你在项目入口(比如main.js)里手动引入core-js/stableregenerator-runtime/runtime,Babel会把所有目标浏览器缺失的Polyfill都加上,适合需要完全兼容旧浏览器的场景。
  • corejs:指定Polyfill用的core-js版本(要先装对应版本的core-js包),比如用core-js@3,就配:
    corejs: 3

plugins:处理特殊语法/框架需求

plugins是“个性化插件”,处理预设覆盖不到的场景。

  • @vue/babel-plugin-jsx:让Vue支持JSX写法,装了这个插件,才能写const Comp = () => <div>JSX</div>这种代码,它会把JSX转成Vue的h()函数调用。
  • @babel/plugin-proposal-decorators:处理ES装饰器语法(比如给Vue组件加@Component注解),注意Vue2里用装饰器要配legacy模式。
  • @babel/plugin-proposal-optional-chaining:转译可选链语法(a?.b?.c),旧浏览器不支持这个,就得用插件。

举个实际配置的例子,要兼容IE11,用JSX,还想按需加Polyfill,babel.config.js可以写成这样:

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: { ie: '11' },
        useBuiltIns: 'usage',
        corejs: 3
      }
    ],
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    '@vue/babel-plugin-jsx',
    ['@babel/plugin-proposal-decorators', { legacy: true }]
  ]
}

想给Vue2项目加JSX支持,Babel咋配置?

很多同学觉得“Vue只能写template”,其实用JSX更灵活(比如动态渲染组件时),给Vue2加JSX支持分三步:

  • 装依赖:执行npm i @vue/babel-plugin-jsx -D(开发依赖,因为编译时用)。
  • 改babel配置:在babel.config.jsplugins里加上'@vue/babel-plugin-jsx',像前面例子那样。
  • 写JSX组件测试:比如新建个JSXComp.js
    import Vue from 'vue'
    export default {
      render() {
        return <div>{this.msg}</div> // JSX写法,会被转成h('div', this.msg)
      },
      data() {
        return { msg: 'JSX测试' }
      }
    }

    然后在父组件里引入<JSXComp />,能正常渲染就说明配置对了。注意:Vue2的JSX和Vue3有区别,比如Vue2里JSX的指令要写成{/* v-if */} { show && <div>显示</div> },不像Vue3能直接写<div v-if={show}></div>,这点要留意~

为啥项目里写了ES6语法还是报错?可能是Babel配置哪错了?

碰到“浏览器报语法错误,比如不认识箭头函数、const”,先按这几步排查:

  • targets配置:是不是漏了要兼容的浏览器?比如测试的是IE11,但babel.config.js里没写ie: '11',Babel就不会转译IE不支持的语法,导致报错。
  • 检查useBuiltInscorejs:如果用了PromiseArray.includes这些API,但没开Polyfill(比如useBuiltIns: 'false'),旧浏览器就会因为缺API报错,要确认是用'usage'自动加,还是'entry'手动引。
  • 看Webpack的babel-loader配置:有没有漏掉对.js文件的处理?比如Vue CLI生成的项目一般没问题,但自己改了Webpack配置的话,要确保babel-loader包含了node_modules外的所有.js和.vue里的script
  • 检查依赖版本:比如Babel 7要用@babel/xxx包,要是装了Babel 6的包(比如babel-core),就会不兼容,可以搜项目里的package.json,看有没有旧版本的Babel包,统一换成@babel开头的。

生产环境和开发环境,Babel配置要区分吗?

建议区分!因为开发和生产的需求不一样:

  • 开发环境:优先“调试方便”,可以把targets设为现代浏览器(比如Chrome最新版),少转译语法,让代码更接近源码,方便调试;Polyfill也可以少加,加快编译速度。
  • 生产环境:优先“体积小、兼容性强”,把targets设为要兼容的所有旧浏览器(比如IE11、安卓4.4),打开useBuiltIns: 'usage'做树摇,只加必要的Polyfill,减少打包体积。

怎么动态切换?可以用环境变量(process.env.NODE_ENV)判断,比如在babel.config.js里写:

module.exports = (api) => {
  api.cache.using(() => process.env.NODE_ENV)
  const isProd = process.env.NODE_ENV === 'production'
  return {
    presets: [
      [
        '@babel/preset-env',
        {
          targets: isProd ? { ie: '11', android: '4.4' } : 'last 2 Chrome versions',
          useBuiltIns: 'usage',
          corejs: 3
        }
      ],
      '@vue/cli-plugin-babel/preset'
    ]
  }
}

这样开发时编译快,生产时兼容性好、体积小,一箭双雕~

Vue2项目升级Babel版本会有坑吗?比如从Babel 6到7?

如果项目还在用Babel 6(比如依赖里有babel-corebabel-preset-env),升级到Babel 7要注意这些点:

  • 包名全换:Babel 7的包都以@babel/开头,比如把babel-core换成@babel/corebabel-preset-env换成@babel/preset-envbabel-loader换成@babel-loader(注意webpack里的loader配置也要改)。
  • 配置文件升级:Babel 6用.babelrc,Babel 7推荐用babel.config.js(因为Vue CLI项目是多包结构,babel.config.js能作用于子包),把旧配置里的presetsplugins迁移过去,注意语法变化(比如预设的写法从'env'变成'@babel/preset-env')。
  • 测试Vue单文件组件:升级后,重点测.vue文件里的script部分——比如类组件、装饰器、JSX有没有转译错误,有些旧插件(比如babel-plugin-transform-vue-jsx)在Babel 7里要换成@vue/babel-plugin-jsx,不然会解析失败。
  • 处理依赖冲突:升级后可能出现依赖版本不兼容(比如Vue CLI版本和Babel插件版本不匹配),可以先把node_modulespackage-lock.json删掉,重新npm install,再测试编译是否正常。

Babel在Vue2项目里是“语法翻译官+API补给员”,配置对了能让新语法在旧浏览器跑通,还能灵活写JSX,只要把`preset-env`的 `targets`、`useBuiltIns` 这些关键配置吃透,再结合项目场景(比如需不需要JSX、兼容哪些浏览器)调整,就能避开绝大多数坑~要是配置后还报错,回到上面的排查步骤,从`targets`、polyfill、插件、依赖版本这几个点一个个查,基本都能解决~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门