1.先搞懂,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 = () =>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
里的配置都是啥意思?
很多同学打开这个文件,看到presets
、plugins
一堆配置头大,这里拆最常用的@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/stable
和regenerator-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.js
的plugins
里加上'@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不支持的语法,导致报错。 - 检查
useBuiltIns
和corejs
:如果用了Promise
、Array.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-core
、babel-preset-env
),升级到Babel 7要注意这些点:
- 包名全换:Babel 7的包都以
@babel/
开头,比如把babel-core
换成@babel/core
,babel-preset-env
换成@babel/preset-env
,babel-loader
换成@babel-loader
(注意webpack里的loader配置也要改)。 - 配置文件升级:Babel 6用
.babelrc
,Babel 7推荐用babel.config.js
(因为Vue CLI项目是多包结构,babel.config.js
能作用于子包),把旧配置里的presets
、plugins
迁移过去,注意语法变化(比如预设的写法从'env'
变成'@babel/preset-env'
)。 - 测试Vue单文件组件:升级后,重点测
.vue
文件里的script
部分——比如类组件、装饰器、JSX有没有转译错误,有些旧插件(比如babel-plugin-transform-vue-jsx
)在Babel 7里要换成@vue/babel-plugin-jsx
,不然会解析失败。 - 处理依赖冲突:升级后可能出现依赖版本不兼容(比如Vue CLI版本和Babel插件版本不匹配),可以先把
node_modules
和package-lock.json
删掉,重新npm install
,再测试编译是否正常。
Babel在Vue2项目里是“语法翻译官+API补给员”,配置对了能让新语法在旧浏览器跑通,还能灵活写JSX,只要把`preset-env`的 `targets`、`useBuiltIns` 这些关键配置吃透,再结合项目场景(比如需不需要JSX、兼容哪些浏览器)调整,就能避开绝大多数坑~要是配置后还报错,回到上面的排查步骤,从`targets`、polyfill、插件、依赖版本这几个点一个个查,基本都能解决~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。