render(){
return <div>
this .state.data ?.users?.id?
<div>{this .state.data .users.id}</div>:null
无比优雅的代码!
当然,es10自然是无法直接使用的,需要配置babel,我们接下来查一下plugin,度娘说直接在.bebelrc中plugin加入 "@babel/plugin-proposal-optional-chaining"和 "@babel/plugin-proposal-nullish-coalescing-operator"就行。
项目跑起来,意料之中的提示缺少npm包,三下五除二装完包,意料之外的问题来了,报错Error: Requires Babel “^7.0.0-0“, but was loaded with “6.26.3“ 这个问题当时困扰了我,当然其实本质原因是babel/core和babel-core冲突的问题,更本质的说是babel6和babel7的问题,这也是后话了,正好我对babel的基础不是很熟悉,再去从babel的基础学一遍吧!
babel是什么
工欲善其事,必先利其器。
babel 最开始叫 6to5,顾名思义,功能是 es6 转 es5。我们知道,es 版本一年一代,有了 es7(es2016)、es8(es2017)等之后,显然,6to5 的名字已经不合适了,所以 6to5 改名为了 babel。
babel的运行有三个阶段
1. parse
解析阶段对代码进行解析,生成AST语法树,这个流程主要由@babel/parser完成
2. transform
转换阶段将 AST 语法树转换为目标的 AST 语法树,主要由@babel/traverse遍历节点,具体的 AST 转化根据babel.config.json中配置的presets、plugins处理
3. generate
生成阶段将 AST 生成代码,并生成sourcemap,主要由@babel/generator完成
babel怎么用
babel的配置(babel.config.json或.babelrc)中有两种,分别是presets和plugins。
比如如需要转换箭头函数,我们可以添加
"plugins": [ "@babel/plugin-transform-arrow-functions"]
但是这么做就有一个问题,随着代码中使用的 ES6+ 规则越来越多,plugins 中的规则也会越来越多,导致plugins非常的长长长长长。这个时候 presets 就起作用了。
bebel 6 中引入了 presets 的概念,预设(presets)大大帮助我们简化了 plugins 中配置的数量。在 babel6 中,如果我们想用 es6 语法就引入babel-preset-es2015,es7 就引入 babel-preset-es2016 等等。如果是想用还没加入标准的特性,可以用 babel-preset-stage0、babel-preset-stage1 等来引入
显然,这种命名方式存在一定的问题,这些babel-preset-stage0、babel-preset-stage1等集成的未加入标准的特性会加入标准,这样命名不是很好;另外,用户的浏览器已经可以使用高级的语法,多做转化可能会多此一举。
babel7就解决了这些问题。
babel 7废弃了preset-2015和preset-stage-x 的 preset 包,而换成了preset-env。
preset-env 默认会支持所有es标准的特性,如果没进入标准的,也不再封装成preset,需要手动引入plugin-proposal-xxx。
babel7 允许指定浏览器版本。
使用babel7后,实际开发中,大多数时候直接使用@babel/preset-env,就能将语法转换到目标环境能支持的语法。
配置中可以不写target,这样会让所有es6-es10转化为es5兼容。但是官方不推荐这么做,因为指定浏览器版本是一个很强大很好用的功能(官方觉得不用太浪费了)。
更多的可以去官方文档中查看,我这边列一个比较常见的配置
"presets" : [
[ "@babel/preset-env" , {
"targets" : "> 0.25%, not dead" ,
"useBuiltIns" : "usage" ,
"corejs" : 3
注:通过useBuiltIns+ browserlist实现按需引入
其实以上就是当前版本的babel的主要内容,概括的说就是去了解一下babel干了什么,怎么用babel。下面我整理了一些其他遇到的问题。
令人困扰的babel-polyfill、babel6迁移babel7指南、babel7新特性、babel8(coming soon)新特性 以及更多
集成包babel-polyfill(@babel/polyfill)
babel-polyfill 其实是对 core-js 和 regenerator 的封装,与 babel/runtime 下的 core-js 区别是
babel-polyfill 支持实例方法,类似Array.includes()这种的转换会污染全局实例。所以官方建议不要在提供给他人使用的模块中使用 babel-polyfill。同时也因为这个原因,@babel/polyfill在7.4.0中已弃用
core-js:用es3 实现的包含 es5及es6+提案的库
regenerator-runtime:解析异步的库
babel7新特性
不再支持放弃维护的 node 版本 0.10、0.12、4、5 ;
舍弃了以前的 babel-- 的命名方式,使用 @babel 命名空间,如 @babel/core (babel6中为babel-core,这也是上文遇到问题的原因);
@babel/preset-env 代替 preset-es2015 等 ;
plugins内的包名改为 -proposal,代替 -transform ;
针对面向用户的包(如 babel-loader、@babel/cli)在@babel/core中引入peerDependencies(用于控制版本,使用率极低)
Babel 7 在编译速度上表现的更加优秀,并且加了一些新的功能,如支持编译 TypeScript;支持 JSX Fragment(针对 React 的 Fragment 特性);支持自动引用 polyfill 等
.babelrc和babel.config.js区别
babel 会在根目录搜索 babel.config.js或babel.config.json(7.8.0以上)作为全局配置。然后在编译一个具体的js文件时会去搜索目录结构向上搜索最近的一个.babelrc.json,将其与全局配置合并。
如上图,.babelrc的配置管不到common/utils.js,如果换成babel.config.json,其中的配置就可以应用到common/util.js
其实大多数情况下都没什么区别...
babel6迁移babel7指南
虽然这个自标题很大,但是事实上迁移操作很简单,而且babel的版本迭代大多数情况下不会出问题(也可能会出,我就遇到过一个废弃的语法的plugin,babel更新后直接跑不起来)
实际操作: 进行.babelrc配置后(见上文或官方文档),按报错安装npm包(如@babel/preset-env,@babel/core, @babel/preset-react)
常见问题: Module build failed: Error: Requires Babel "^7.0.0-0", but was loaded with "6.26.3". If you are sure you have a compatible version of @babel/core, it is likely that something in your build process is loading the wrong version. Inspect the stack trace of this error to look for the first entry that doesn't mention "@babel/core" or "babel-core" to see what is calling Babel. (While processing preset: "/path")
翻译:如果您确信您有一个兼容版本的@babel/core,那么很可能是构建过程中加载了错误的版本。检查此错误的堆栈跟踪以查找第一个没有提到“@babel/core”或“babel-core”的条目,以查看调用babel的内容
原因:babel7的包更名为babel/core,有些包用的是babel6的babel-core,有所冲突,需要一个bridge
解决方案:更新babel-core至bridge版本
npm i babel-core@^7.0.0-bridge.0 @babel/core regenerator-runtime -D
babel8 coming soon!
We have been talking about the Babel 8 release for more than one year (we initially scheduled it about one year ago)! However, we are now closer then ever to it's release!
我们已经讨论发布Babel 8一年多了(我们大约在一年前就计划好了)!并且,我们现在离它的发布更近了!
目前的babel团队遇到的一些障碍:
考虑放弃对Node.js 10的支持,因为该版本将于2021年4月30日停止维护;
希望能将Babel作为纯ESM包发布,现在正在将babel源码与Node.js的ESM兼容,同时,正在研究如何通过Babel更容易更便捷地将ESM编译为CJS;
正在尝试使TypeScript AST与typescript-eslint保持一致。目前的 AST 几乎完全相同,但仍需一些小的突破性更改来让它们完全一致;
发布基建不支持预发布,不支持使用多个“主”分支(一个用于 Babel 8,一个用于 Babel 7);
正在考虑Babel 7的维护策略。 可能进行的改动: 移动@babel/preset-env直接进入@babel/core
这样改动的两大优点:
1.在简单的项目中配置 Babel 会更容易,你只需要启用一个compileJS: true选项babel.config.json
2.它将确保插件版本与@babel/core版本同步,避免大多数由不匹配/不兼容包版本引起的错误 解决迁移至ESM后遇到的一些问题
由于笔者文笔不佳,很多地方的阐述较为混乱,后续也会逐渐修改;文中技术内容也会因为自身技术所限有失偏颇,还望大佬指点。
92
zxg_神说要有光
Docker
Node.js
3.4w
ssh_晨曦时梦见兮
JavaScript
Vue.js
370
superZidan
JavaScript
React.js
248
CUGGZ
JavaScript
React.js