Babel & Browserify

Babel 转码器

Babel

Babel is a JavaScript compiler ( Put in next-gen JavaScript, Get browser-compatible JavaScript out)

一种转码器,将ES6代码转换为ES5代码,从而在现有环境执行

eg:用 ES6 编写程序,特性还没有得到广泛支持,用Babel将其转换为ES5标准的代码,就能在现有的JavaScript环境执行了

转码前

input.map(item => item + 1);

转码后

input.map(function (item) {
  return item + 1;
});

配置执行

.babelrc

Babel的配置文件,用来设置转码规则和插件,存放在项目的根目录下。使用Babel的第一步,就是配置这个文件

  1. 基本格式:

     {
       "presets": [],
       "plugins": []
     }
    
  2. 说明:

    • presents字段用来设定转码规则,按需下载安装和配置
    • 官方提供的规则集:
      • ES2015转码规则: babel-preset-es2015
      • react转码规则: babel-preset-react
      • ES7不同阶段语法提案的转码规则(共有4个阶段),任选一个:
        • babel-preset-stage-0
        • babel-preset-stage-1
        • babel-preset-stage-2
        • babel-preset-stage-3
  3. Demo:

    • 安装转码规则集:
        npm install --save-dev babel-preset-es2015 babel-preset-react babel-preset-stage-2
      
    • 配置.babelrc:
        {
            "presets": [
              "es2015",
              "react",
              "stage-2"
            ]
        }
      

babel-cli

用于命令行转码

  1. 安装

     npm install --global babel-cli
    
  2. 使用

     # 转码结果输出到标准输出
     $ babel example.js
    
     # 转码结果写入一个文件 ( --out-file 或 -o 参数指定输出文件 )
     $ babel example.js -o compiled.js
    
     # 整个目录转码 ( --out-dir 或 -d 参数指定输出目录 )
     $ babel src -d lib
    
     # -s 参数生成source map文件
     $ babel src -d lib -s
    
  3. 注:若要支持不同项目使用不同版本的Babel,可将babel-cli安装在项目之中,再配置package.json

    • 安装:
        $ npm install --save-dev babel-cli
      
    • package.json配置:
        {
          // ...
          "devDependencies": {
            "babel-cli": "^6.0.0"
          },
          "scripts": {
            "build": "babel src -d lib"
          },
        }
      
    • 执行转码
        $ npm run build
      

钩子

babel-polyfill

Babel默认只转换新的JavaScript句法,而不转换新的API(如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法,eg:Object.assign)详细清单可以查看babel-plugin-transform-runtime模块的definitions.js文件 eg: ES6在Array对象上新增了Array.from方法。Babel就不会转码这个方法。如果想让这个方法运行,必须使用babel-polyfill,为当前环境提供一个垫片。

安装:

npm install --save babel-polyfill

在脚本头部导入:

import 'babel-polyfill';    // 或者 require('babel-polyfill');

babel-register

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

注:

  • 只会对require命令加载的文件转码,不会对当前文件转码
  • 它是实时转码,所以只适合在开发环境使用

Demo:

$ npm install --save-dev babel-register
require("babel-register");        // 使用时,必须首先加载babel-register
require("./index.js");            // 然后,就不需要手动对index.js转码了

代码调用Babel API

引入babel-core

  1. 安装:

     $ npm install babel-core --save
    
  2. API调用:

     var babel = require('babel-core');
    
     // 字符串转码
     babel.transform('code();', options);
    
     // 文件转码(异步)
     babel.transformFile('filename.js', options, function(err, result) {
       result;
     });
    
     // 文件转码(同步)
     babel.transformFileSync('filename.js', options);
    
     // Babel AST转码
     babel.transformFromAst(ast, code, options);
    
    • transform方法说明:
      • 参数:
        • 参数一:一个字符串,表示需要转换的ES6代码
        • 参数二:配置对象options,可以参看官方文档
      • 返回对象:{ code, map, ast }
  3. Demo:

     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};'
    

执行环境

  1. REPL环境: 可使用babel-cli工具自带的babel-node命令,会提供一个支持ES6的REPL环境 ( 支持Node的REPL环境的所有功能,可直接运行ES6代码 )

    • Demo1: 直接执行babel-node就进入PEPL环境
        $ babel-node
        > (x => x * 2)(1)
        2
      
    • Demo2:执行ES6脚本文件 (注:脚本本身不做任何转码处理)
        $ babel-node es6.js
        2
      
  2. 浏览器环境: 使用转换器,直接在浏览器运行

    • 使用Babel提供的转换器脚本browser.js,直接在浏览器运行(注:Babel 6.0开始,不再直接提供浏览器版本,而是要用构建工具构建出来;可使用Babel 5.x)
        <script type="text/javascript" src="bower_components/babel/browser.min.js"></script>
        <script type="text/babel">
            // write your ES6 code here
        </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,对性能会有影响,生产环境最好加载已经转码完成的脚本
  3. 浏览器环境: 先将代码打包转码成浏览器可使用的脚本在加载

    • 使用Browserify(配合Babel,需安装babelify模块)

        # 安装babelify模块
        $ npm install --save-dev babelify babel-preset-es2015
      
        # 执行转换:将ES6脚本script.js,转为bundle.js,然后浏览器直接加载bundle.js即可
        $ browserify script.js -o bundle.js -t [ babelify --presets [ es2015 ] ]
      
    • 使用webpack(babel-loader),配置webpack.config.js,执行webpack
        module.exports = {
          entry: "./src/a.js",
          output: {
              path: __dirname+"/dist",
              filename: "a.js"
              publicPath:"/dist"
          },
          resolve: {
              extensions: ['','.js']
          },
          module: {
              loaders: [
                  { test: /\.js$/, loader: "babel",query:{presets:['latest']} }    //babel参数,例如presets,也可以在.babelrc或package.json中指定
              ]
          }
        };
      
    • 在线转换:Babel提供一个REPL在线编译器,可以在线将ES6代码转为ES5代码。转换后的代码,可以直接作为ES5代码插入网页运行

Browserify

Browserify

Browserify lets you require('modules') in the browser by bundling up all of your dependencies

让服务器端的CommonJS格式的模块可以运行在浏览器端(Browserify编译时,会将脚本所依赖的模块一起编译进去,即可以将多个模块合并成一个文件)

Demo:

  1. 安装
     npm install -g browserify
    
  2. 编写一个服务器端脚本a.js,代码中uniq模块是CommonJS格式,无法在浏览器中运行
     var uniq = require('uniq');
     var nums = [ 5, 2, 1, 3, 2, 5, 4, 2, 0, 1 ];
     console.log(uniq(nums));
    
  3. 通过Browserify将上面代码编译为浏览器脚本
     browserify a.js > bundle.js
    
  4. 生成的bundle.js可以直接插入网页
    <script src="bundle.js"></script>
    

Reference

阮一峰/前端模块管理器简介

阮一峰/Babel 入门教程