babel介绍与使用

Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。下面列出的是 Babel 能为你做的事情:

  • 语法转换
  • 通过 Polyfill 方式在目标环境中添加缺失的特性 (通过 @babel/polyfill 模块)
  • 源码转换 (codemods)

转换过程

  • code转为ast树
  • 修改ast数据结构
  • 修改后的ast生成code

babel用法

  • @babel/core 核心转换工具
  • @babel/types 用于修改ast及判断的工具类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //遍历并修改ast
    const importPlugin = {
    visitor: {
    ImportDeclaration(path) {
    if (!t.isImportDefaultSpecifier(specifiers[0])) {//等等
    }
    }
    }
    //原始code
    const ast = babel.transform(code, {
    plugins: [importPlugin]
    });
    const newCode = ast.code;//转换后的code
    console.log(newCode)

实现babel-plugin-import插件

按需打包插件,避免导入整个包

  • webpack.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    module: {
    rules: [{
    test: /\.js$/,
    exclude:/node_modules/,
    use: {
    loader: 'babel-loader',
    options: {
    presets: ['@babel/preset-env', '@babel/preset-react'],
    plugins:['./plugins/plugin-transform-xu-import']
    },
    }
    }]
  • babel插件查找路径

  • 转换前

    1
    2
    3
    4
    import React from 'react';
    import ReactDOM from 'react-dom';
    import {Button,Alert} from 'antd'
    console.log(antd)
  • 转换后效果明显打包前5.7M,打包后1.56M

    1
    2
    3
    4
    import React from 'react';
    import ReactDOM from 'react-dom';
    import Button from 'antd/lib/button';
    import Alert from 'antd/lib/alert';
  • 插件源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    ////////#############
    let t = require('babel-types');
    // const code = "import {Button,Alert} from 'antd'";
    module.exports = function(){
    let importPlugin = {
    visitor: {
    ImportDeclaration(path) {
    console.log('myplugins')
    let { node } = path;
    let source = node.source.value;
    let specifiers = node.specifiers;
    if (!t.isImportDefaultSpecifier(specifiers[0])) {
    specifiers = specifiers.map((v, i) => {
    return t.importDeclaration(
    [t.importDefaultSpecifier(v.local)],
    t.stringLiteral(`${source}/lib/${v.local.name.toLowerCase()}`)
    )
    })
    path.replaceWithMultiple(specifiers);
    }
    }
    }
    };
    return importPlugin;
    }