React技术栈之Babel

Babel一个广泛使用的转码器,可以将ES6/ES7代码转为ES5代码。JavaScript在不断发展,各种新的标准提案层出不穷,由于浏览器的多样性导致可能几年之内都无法广泛普及,Babel可以让你无顾虑的使用这些特性。

Babel提供一个REPL在线编译器,可以在线将ES6代码转为ES5代码。你可以感受下。

基于插件的转换

先安装babel命令行工具:

npm install --global babel-cli

创建示例目录

mkdir babel-demo
cd babel-demo
npm init --yes
mkdir src

在babel6里,要转换ES6标准以上的代码,需要配置插件

待转换的示例,src/test.js:

let fun = () => console.log('babel');

上面用到了ES6的箭头函数,需安装箭头函数转换插件

npm install --save-dev babel-plugin-transform-es2015-arrow-functions

配置babel插件,babel-demo/.babelrc:

{
  "plugins": ["transform-es2015-arrow-functions"]
}

执行babel转换:

babel src/test.js

可以看到输出

'use strict';

var fun = function fun() {
  return console.log('babel');
};

babel命令基本用法

# 转码结果输出到标准输出
$ babel example.js

# 转码结果写入一个文件
# --out-file 或 -o 参数指定输出文件
$ babel example.js --out-file compiled.js
$ babel example.js -o compiled.js

# 整个目录转码
# --out-dir 或 -d 参数指定输出目录
$ babel src --out-dir lib
$ babel src -d lib

# -s 参数生成source map文件
$ babel src -d lib -s

基于插件包的转换

基本上ES6/ES7的新语法和API,babel都有相应的插件用于转换,但如果要一个个安装配置,那是有点烦人的。babel 还提供了presets,可理解为预置插件包。

要转换ES6,可以安装babel-preset-es2015插件包:

npm install babel-preset-es2015 --save-dev

要转换React语法,可以安装babel-preset-react插件包:

npm install babel-preset-react --save-dev

修改配置,babel-demo/.babelrc:

{
  "presets": ["es2015","react"]
}

再次执行命令babel src/test.js,得到相同的换换结果。

可以事先配置npm命令,package.json:

"scripts": {
    "build": "babel src -d lib"
},

运行npm run build,可以看到src下代码转换结果保存到了lib目录下。

官方提供了以下插件包,可以根据需要安装:

# ES6转码包
$ npm install --save-dev babel-preset-es2015

# react转码包
$ npm install --save-dev babel-preset-react

# ES7不同阶段语法提案的转码包(共有4个阶段),选装一个
$ npm install --save-dev babel-preset-stage-0
$ npm install --save-dev babel-preset-stage-1
$ npm install --save-dev babel-preset-stage-2
$ npm install --save-dev babel-preset-stage-3

babel-node

babel-register是在node里使用的。它改写require命令,为它加上一个钩子。此后,每当使用require加载.js、.jsx、.es和.es6后缀名的文件,就会先用Babel进行转码。

$ npm install --save-dev babel-register

使用时,必须首先加载babel-register。

require("babel-register");
require("./index.js");

然后,就不需要手动对index.js转码了。
需要注意的是,babel-register只会对require命令加载的文件转码,而不会对当前文件转码。另外,由于它是实时转码,所以只适合在node开发环境使用。

babel-core

如果某些代码需要主动调用Babel的API进行转码(基本没这种需求),可以使用babel-core模块。
安装命令如下。

$ npm install babel-core --save

然后,在项目中就可以调用babel-core

var es6Code = 'let x = n => n + 1';
var es5Code = require('babel-core')
  .transform(es6Code,{
    presets: ['es2015']
  })
  .code;
// '"use strict";\n\nvar x = function x(n) {\n  return n + 1;\n};'

babel-polyfill

Babel认只转换新的JavaScript句法(Syntax),而不转换新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。

举例来说,ES6在Array对象上新增了Array.from方法。Babel就不会转码这个方法。如果想让这个方法运行,必须使用babel-polyfill,为当前环境提供一个垫片。

安装命令如下。

$ npm install --save babel-polyfill

然后,在脚本头部,加入如下一行代码

import 'babel-polyfill';

Babel认不转码的API非常多,详细清单可以查看babel-plugin-transform-runtime模块的definitions.js文件

babel-runtime

与 babel-polyfill 一样,babel-runtime 的作用也是模拟 ES2015 环境。只不过,babel-polyfill 是针对全局环境的,引入babel-polyfill,我们的浏览器就好像具备了规范里定义的完整的特性。它内置提供promise,set,map这样的对象或功能,他们将会污染全局环境。也许在一个应用中或者命令行工具中没问题,但是如果你是写库的话,由于使用的人可能在各种各样的执行环境中,所以可能导致错误,不能执行。

babel-runtime 更像是分散的 polyfill 模块,我们可以在自己的模块里单独引入,比如require(‘babel-runtime/core-js/promise’) ,它们不会在全局环境添加未实现的方法,只是,这样手动引用每个 polyfill 会非常低效。我们借助 Runtime transform 插件自动化处理这一切。

至于要用 babel-polyfill 还是 babel-runtime,则需要根据具体需求。建议使用babel-runtime,配合runtime transfrom插件的方式。

比如安装插件

npm install --save-dev transform-es2015-template-literals
npm install --save-dev transform-class-properties

修改.babelrc配置文件

{
  "presets": [
    "es2015","stage-2","react",],"plugins": [
    ["transform-runtime",{
      "helpers": false,"polyfill": false,"regenerator": true,"moduleName": "babel-runtime"
    }],"transform-es2015-template-literals","transform-class-properties",]
}

因此你可以不使用require了,可以无缝使用内置垫片了。

配合工具

如果项目使用webpack进行打包,打包文件之前要先借助babel转码。
安装babel-core、babel-loader:

npm install --save-dev babel-core babel-loader

除配置.babelrc指定相应的转码插件包或插件后,还要修改webpack配置文件,webpack.config.js。

module: {
  rules: [
    {
      test: /\.jsx?$/,loader: 'babel-loader',include: /src/,}
}

上面的webpack打包规则,通过指定使用babel-loader插件,应用babel转换include指定目录下的jsx文件

Mocha 则是一个测试框架,如果需要执行使用ES6语法的测试脚本,可以修改package.json的scripts.test。

"scripts": {
  "test": "mocha --ui qunit --compilers js:babel-core/register"
}

上面命令中,--compilers参数指定脚本的转码器,规定后缀名为js的文件,都需要使用babel-core/register先转码。

浏览器版

Babel也可以用于浏览器环境。但是,从Babel 6.0开始,不再直接提供浏览器版本,而是要用构建工具构建出来。如果你没有或不想使用构建工具,可以通过安装5.x版本的babel-core模块获取

$ npm install babel-core@5

运行上面的命令以后,就可以在当前目录的node_modules/babel-core/子目录里面,找到babel的浏览器版本browser.js(未精简)和browser.min.js(已精简)。
然后,将下面的代码插入网页。

<script src="node_modules/babel-core/browser.js"></script>
<script type="text/babel">
// Your ES6 code
</script>

另一种方法是使用babel-standalone模块提供的浏览器版本,将其插入网页。

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.4.4/babel.min.js"></script>
<script type="text/babel">
// Your ES6 code
</script>

注意,网页中实时将ES6代码转为ES5,对性能会有影响。生产环境需要加载已经转码完成的脚本。
下面是如何将代码打包成浏览器可以使用的脚本,以Babel配合browserify为例。首先,安装babelify模块。

$ npm install --save-dev babelify babel-preset-es2015

然后,再用命令行转换ES6脚本。

$  browserify script.js -o bundle.js -t [ babelify --presets [ es2015 react ] ]

上面代码将ES6脚本script.js,转为bundle.js,浏览器直接加载后者就可以了。
在package.json设置下面的代码,就不用每次命令行都输入参数了。

{
  "browserify": {
    "transform": [["babelify",{ "presets": ["es2015"] }]]
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom