深入浅出webpack之Babel

133 阅读2分钟

Babel是什么

  • 在开发中,我们很少直接去接触babel,但是babel对于前端开发而言是不可缺少的一部分
  • 例如ES6+转换为ES5的代码,语法转换,源代码转换,polyfill实现目标缺少的功能等

Babel底层原理

image.png

  • 源代码

    image.png

  • 词法分析就是把代码转换为tokens数组

    image.png

  • 经过语法分析之后再转换为AST抽象语法树

    image.png

  • 然后开始深度遍历每一个节点,然后访问节点,应用插件对源代码进行相应修改,然后生成新的AST抽象语法树,最终生成新的代码

使用示例

  • 源文件 image.png
  • 先安装babel对应插件npm i @babel/core @babel/preset-env babel-loader -D
   moduleexports = {
       mode:"development",
       devtool:false,
       entry: "./src/main.js",
       output: {
        filename: "awei.js",
        path: path.resolve(__dirname, "./build"),
       },
       module:{
           rules:[
               {
                   test:/\.js$/,
                   use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: ["@babel/preset-env"],
                        },
                    },
                ],
               }
           ]
       }
   }
   //如果直接使用打包后看不出修改效果,请调整 .browerslistrc 文件
  • 打包后文件(可见ES6代码已转换为ES5)

    image.png

单独配置文件使用babel

  • babel.config.json(或者.js .cjs .mjs)文件 ; 可以直接作用于Monorepos项目的子包,更加推荐
  • .babelrc.json(或者.babelrc .js .cjs .mjs) ; 早期使用较多的配置方式 , 对于配置Monorepos项目比较麻烦
   //项目根目录下创建babel.config.js
   //babel-config.js
   module.exports = {
       presets:[
           '@babel/preset-env'
       ]
   }
   
   //webpack.config.js中options配置项即可隐藏
   module.exports = {
       //...,
       module:{
           rules:[
               {
                   test:/\.js$/,
                   //表示排除这个文件夹下的js文件,不使用此配置
                   exclude:/node_modules/,
                   use:[
                       {
                           loader:'babel-loader',
                           //options: {
                           //     presets: ["@babel/preset-env"],
                           // },
                       }
                   ]
               }
           ]
       }
   }

ployfill

  • 可以理解为一个补丁,可以帮助我们更好的使用javascript
  • 比如我们使用了一些新语法特性(Promise,Generator,Symbol等,但是某些浏览器中不认识这些特性,调用这个方法就会报错,polyfill就会在打包后的代码中填充进去,这样就会包含该特性,就能正常调用了
    npm i core-js regenerator-runtime -S
    
    //babel.config.js 
    module.exports = {
        presets:[
            [
                '@babel/preset-env',{
                    // false:不使用任何polyfill相关的代码
                    // usage:代码中需要哪些polyfill,就引用相关api
                    // entry:依据我们当前筛选出来的浏览器.browserslistrc决定填充什么,需要手动在入口文件导入core-js/stable和regenerator-runtime/runtime
                    useBuiltIns:'usage',
                    // 默认corejs使用的是2,报错我们来修改为最新的3
                    corejs:3
                }
            ]
        ]
    }
    
    //main.js
    //useBuiltIns:'entry'的时候,需引入包进行使用
    import "core-js/stable";
    import "regenerator-runtime/runtime"
    
    const msg = "hello webpack";
    const foo = (str) => {
        console.log(str);
    }
    const p = new Promise((resolve,reject)=>{})
    foo(msg)
    

@babel/plugin-transform-runtime

  • 但是babel-polyfill会有近100K,打包后代码冗余量比较大,对于现代的浏览器,有些不需要polyfill,造成流量浪费污染了全局对象,@babel/plugin-transform-runtime以插件的形式在打包时引入到文件里,主要的功能是为api提供沙箱的垫片方案,更因此适合用在第三方的开发产品中(开发工具包,库),一方面是体积够小,另一方面是用户(开发者)不会因为引用了我们的工具,包而污染了全局的原生方法,产生副作用。
    npm i @babel/plugin-transform-runtime -D
    npm i @babel/runtime-corejs3 -S
    //babel.config.js
    module.exports = {
        presets:[
            ["@babel/preset-env"]
        ],
        plugins:[
            ["@babel/plugin-transform-runtime",{
                    corejs:3
                    }]
        ]
    }

TypeScript的编译

  • babel可以对TypeScript进行支持
  • 可以使用插件 : @babel/tranform-typescript
  • 推荐使用preset : @babel/preset-typescript
    npm i @babel/preset-typescript -D
    
    //babel.config.js
    module.exports = {
        presets:[
            ['@babel/preset-env',{
                useBuiltIns:'usage',
                corejs:3
            }],
            ['@babel/preset-typescript']
        ]
    }
    
   //webpack.config.js
   module.exports = {
       //...,
       module:{
           rules:[
               {
                   test:/\.ts$/,
                   //表示排除这个文件夹下的js文件,不使用此配置
                   exclude:/node_modules/,
                   use:[
                       {
                           loader:'babel-loader',
                       }
                   ]
               }
           ]
       }
   }
   

示例代码

    https://gitee.com/weiLZ598/webpack-study.git