bebal知识

https://blog.jakoblind.no/babel-webpack-es6/

https://blog.jakoblind.no/babel-preset-env/

nice blog: https://blog.jakoblind.no/

如何通过 Babel 和 Weback 使用ES6?

要使用ES6并不是一件简单的事情,在写代码之前,我们必须要设置BaBel和webpack.

Babel is a transpiler that can compile ES6 and ECMAScript to old Javascript(ES5) .

Babel does one thing and it does that one thing really well: it transpile JavaScript to a newer version of JavaScript.

run babel from command line

  1. install babel as adependency in project
npm install --save-dev @babel/core @babel/cli @babel/preset-env

  1. add .babelrc file . this is the configuration file for babel,we use it to tell babel to transpile ES6.
{
  presets: ['@babel/preset-env']
}
  1. transpile file js file with Babel
npx babel myES6Code.js
npx babel myES6Code.js --out-file script-compiled.js

call babel from webpack

Most non-trivial web apps also require a build system, such as webpack. With webpack, you can configure how different types of files should be transpiled. You configure rules like this.

bebal知识_第1张图片
image.png

The rules are defined in the webpack config file which is a JavaScript file in your project.

What is babel-preset-env and why do I need it?

installed Babel and then added babel-preset-env to your .babelrc:

{
  presets: ['@babel/preset-env']
}

…and things works fine. It transpiles the ES6 for you just like you wanted to and you move on with the tutorial.
what did you just do with your .babelrc file and why does it work?
It’s not a nice feeling to just type something that you read in a tutorial without really understand why you should use it. Let’s look into what babel-preset-env really do, and why you need it.

Babel from scratch

The most common way to use Babel is together with a build system such as webpack. When using Babel with a build tool it’s easy to overlook how Babel really works. It feels like Babel and webpack is the same thing.

A good exercise is to learn Babel without a build system - even though you don’t intend to use it that way in production. So get your editor and terminal ready and code along.

First create a new NPM project:

mkdir babel-test
cd babel-test
npm init -y

Next install Babel as dependency to your empty project:

npm install --save-dev @babel/core @babel/cli

Add a file called input.js and add the following to it:

const hello = () => console.log("hello world!");

That is an arrow function which is an ES6 feature. This is supported in most browsers but not all, that’s why it’s a good idea to transpile it to ES5. Now let’s run this file through Babel:

npx babel input.js --out-file output.js

If you open output.js, you’ll see that nothing has changed. It’s exactly the same content as input.js. That’s not what you expected, was it?

The reason for this is that Babel doesn’t do anything out-of-the-box but Babel is built on presets and plugins. If you don’t add any presets or plugins, then Babel will do nothing.

如果不设置presets和plugins,Bable什么事情也不会做!!
Babel doesn't do anything out-of-the-box

It’s the Babel plugins that does the work

To make Babel actually do something, we need to add a plugin. It’s the plugins that does the heavy lifting.

Each plugin is it’s own NPM library. So for every plugin you want to install, you have to install a new NPM library or you can use a preset that we’ll come back to in the next section.

In the code you have written in input.js you only have one ES6 feature: an arrow function. So what we are going to now is to install a Babel plugin that transpiles ES6 arrow functions.

Let’s start by installing a plugin that transpiles the function you have written in input.js file.

npm install --save-dev @babel/plugin-transform-arrow-functions

Next, you need to tell Babel to use the dependency. Add a file called .babelrc file to the root of your project. This is the configuration file for Babel, and you’ll use it to tell babel to use the plugin @babel/plugin-transform-arrow-functions when doing the transpliation. This plugin only transpiles ES6 arrow functions.

{
  plugins: ['@babel/plugin-transform-arrow-functions']
}

Ok, that’s it. Now you can re-run babel and look at the generated output.js file. It now contains the transpiled code!

const hello = function () {
  return console.log("hello world!");
};

That’s awesome! But if you want to use more ES6 features you would need to install one NPM package and add an entry in .babelrc for every feature. That’s just too much work. But there is a solution to this: presets!

Babel presets bundles together common Babel plugins

The Babel foundation has created presets that contains common bundles of plugins. That means you only have to do the NPM installation and babel configuration once and then a bunch of plugins are automatically installed for you.

There are many different Babel presets, both official presets from Babel foundation and unofficial presets from other organizations such as Airbnb. Heck, you could even create your own preset if you want.

The official presets are:

@babel/preset-env
@babel/preset-flow
@babel/preset-react
@babel/preset-typescript

Every preset is its own NPM dependency that you need to install and configure. Ok, now you are finally ready to learn about babel-preset-env.

Ok, now babel-preset-env

Let’s convert you mini-code base to use babel-preset-env instead of @babel/plugin-transform-arrow-functions

Install the NPM dependency:

npm install --save-dev @babel/preset-env

Next, configure in the preset section of your .babelrc file

{
  presets: ['@babel/preset-env']
}

What you have done now, is that you have installed the basic configuration of babel-preset-env. Out-of-the-box you get all plugins you need to transpile all ES6 features!

But babel preset env is smarter than this. You can have even more fine grained controll over what plugins should be installed

The unique selling point with babel-preset-env is that you can define what browsers you support

plugin-transform-runtime和runtime

当我在用babel编译时,有些功能需要一些工具函数来辅助实现,比如class的编译。

class People{
}

// babel编译后
'use strict';

function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError('Cannot call a class as a function');
    }
}

var People = function People() {
    _classCallCheck(this, People);
};

编译后的代码中,_classCallCheck就是一个辅助功能实现的工具函数。如果多个文件中都用到了class,每一个文件编译后都生成一个工具函数,最后就会产生大量重复代码,平白增加文件体积。而plugin-transform-runtime就是为了解决这个问题,这个插件会将这些工具函数转换成引入的形式。

npm i @babel/plugin-transform-runtime -D

module.exports = {
    presets: ['@babel/preset-env'],
    plugins: ['@babel/plugin-transform-runtime']
};

安装设置完成之后再用babel编译结如下:

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var People = function People() {
  (0, _classCallCheck2["default"])(this, People);
};

_classCallCheck2这个工具函数已经变成从一个npm包中引入,不会再产生单独的工具函数代码。但是可以看到工具函数是从@babel/runtime这个包中引入,所以要安装@babel/runtime这个依赖包,在项目打包的时候才不会报错。

npm i @babel/runtime

注意:babel/runtime并不是开发依赖,而是项目生产依赖。编译时使用了plugin-transform-runtime,你的项目就要依赖于babel/runtime,所以这两个东西是一起使用的。

babel-polyfill

babel可以转化一些新的特性,但是对于新的内置函数(Promise,Set,Map),静态方法(Array.from,Object.assign),实例方法(Array.prototype.includes)这些就需要babel-polyfill来解决,babel-polyfill会完整模拟一个 ES2015+环境。

比如你的代码中用到了Array.from,但是目标浏览器不支持Array.from,引入babel-polyfill就会给Array添加一个from方法,代码执行的时候使用的Array.from其实是babel-polyfill模拟出来功能,这样虽然污染了Array的静态方法,但是确实实现了兼容。
之前的使用方式是npm安装@babel/polyfill,并在项目入口处引入@babel/polyfill包。

npm i @babel/polyfill

// entry.js
import "@babel/polyfill";

但是这种方式已经被废弃不推荐使用,因为@babel/polyfill体积比较大,整体引入既增加项目体积,又污染了过多的变量,所以更推荐使用preset-env来按需引入polyfill。

但是这种方式已经被废弃不推荐使用,因为@babel/polyfill体积比较大,整体引入既增加项目体积,又污染了过多的变量,所以更推荐使用preset-env来按需引入polyfill。

// babel.config.js
module.exports = {
    presets: [
        [
            '@babel/preset-env',
            {
                useBuiltIns: 'usage', // usage-按需引入 entry-入口引入(整体引入) false-不引入polyfill
                corejs: 2  // 2-corejs@2  3-corejs@3
            }
        ]
    ]
};

corejs 是一个给低版本的浏览器提供接口的库,也是polyfill功能实现的核心,此处指定的是引入corejs的版本,需要通过npm安装指定版本的corejs库作为生产依赖。

npm i core-js@2

之后执行babel编译可以看到如下效果:

const a = Array.from([1])

//babel编译后
"use strict";

require("core-js/modules/es6.string.iterator");

require("core-js/modules/es6.array.from");

var a = Array.from([1]); 

plugin-transform-runtime和babel-polyfill的讨论

你可能感兴趣的:(bebal知识)