前端经验分享

webpack babel 使用方法整理

2019-02-22  本文已影响115人  Samuel_543a

webpack babel-loader 基础配置

Babel

babel官网 :https://babeljs.io/
babel中文网: https://babel.bootcss.com/

推荐查看babel官方网站,babel中文网的翻译并不是最新版本

webpack基础配置

    npm install --save-dev babel-loader @babel/core
    npm install --save-dev @babel/preset-env
module.exports = {
    // ... other options
    module: {
        rules:[{
            test: /.(js|ts)x?$/,
            loader: 'babel-loader',
            options:{
                presets: ["@babel/preset-env"]
            },
            exclude: /node_modules/
        },
        {
            //... other loader options
        }]
    }
}
    // 源代码:
    
    let array = [1,2,3,4,5];
    
    array.map(item => item + 1)
    // 打包后:
    
    var array = [1, 2, 3, 4, 5];
    
    array.map(function (item) {
        return item + 1;
    });

但是!Array.map 是 ES6 数组扩展中新增的方法!尽管 babel 把 ES6 的语法转换为了 ES5 ,旧版本浏览器依然不支持 Array.map!

如果想要让低版本浏览器也能支持 ES6 的新增扩展,正常情况下就需要自己模拟实现 ES6 的扩展方法,然后通过prototype将方法插入JS对象的原型中,扩展原型方法。

那么,懒癌患者和前端新人怎么办?

不用怕!babeljs团队已经为我们准备好了一套比较完整的方法扩展(懒癌患者福音),我们只需要把扩展库引入就能让旧版浏览器支持 ES6 的新增扩展了 [/坏笑]


为代码添加 ES6 支持

@babel/polyfill

    npm install --save @babel/polyfill

首先不添加 @babel/polyfill ,直接在控制台输出 Promise

    // index.js
    
    console.log(Promise) // 在控制台输出 Promise

使用 IE9 打开后,控制台抛出错误

IE9 控制台输出

然后我们引入 @babel/polyfill 后,再在控制台中输入 Promise

    // 源代码:
    
    require( '@babel/polyfill') // 使用commonJS语法引入polyfill
    
    console.log(Promise) // 在控制台输出 Promise

依然使用 IE9 打开,可以发现控制台中成功打印出了 Promise 的构造函数

IE9 控制台输出

此处又有但是!可以运行并不意味着配置就完成了。

webpack bundle info

what?!
index.js文件里边只写了两行代码,打包后main.js的的大小竟然有207kb!
要是把业务代码都写进去,页面打开速度还不爆炸了!

那么,在当前代码中,我们只用到了Promise方法,能不能只把Promise的方法扩展打包?

修改一下配置试试吧。

// webpack.config.js

module.exports = {
    // ... other options
    module: {
        rules:[{
            test: /.(js|ts)x?$/,
            loader: 'babel-loader',
            options:{
-               presets: ["@babel/preset-env"],

+               presets: ["@babel/preset-env",{
+                   "useBuiltIns": "usage"
+               }],
            },
            exclude: /node_modules/
        },
        {
            //... other loader options
        }]
    }
}

修改完成之后,再执行一次打包

webpack bundle info

可以看到,打包后的文件大小降至29.5kb。
(这里由于使用了其他插件,所以文件依然比较大,在未使用其他插件情况下,打包出来的文件大约3kb)

之所以说以上针对babel的配置是比较符合要求,是因为 @babel/polyfill 虽然可以帮助开发者注入使用到的 ES6 方法,但是它是以 全局变量 的形式将方法注入。如果只是业务开发使用,问题并不是很大。但是如果在开发类库或UI组件时,全局注入的方式会造成变量的 全局污染 。这不是我们期望的结果。我们更希望在注入方法的同时保持全局环境的清洁。这就需要用到 @babel/plugin-transform-runtime 插件

@babel/plugin-transform-runtime

    npm install --save-dev @babel/plugin-transform-runtime
    npm install --save @babel/runtime
// webpack.config.js

module.exports = {
    // ... other options
    module: {
        rules:[{
            test: /.(js|ts)x?$/,
            loader: 'babel-loader',
            options:{
-               presets: ["@babel/preset-env",{
-                   "useBuiltIns": "usage"
-               }],

+               plugins: [
+                   ["@babel/plugin-transform-runtime", {
+                       "corejs": 2,
+                       "helpers": true,
+                       "regenerator": true,
+                       "useESModules": false
+                   }]
+               ]
            },
            exclude: /node_modules/
        },
        {
            //... other loader options
        }]
    }
}

npm uninstall --save @babel/runtime
npm install --save @babel/runtime-corejs2

.babelrc

可以将options中的所有配置都移动到.babelrc文件中单独书写

touch .babelrc
// webpack.config.js

module.exports = {
    // ... other options
    module: {
        rules:[{
            test: /.(js|ts)x?$/,
            loader: 'babel-loader',
-           options:{
-               plugins: [
-                   ["@babel/plugin-transform-runtime", {
-                       "corejs": 2,
-                       "helpers": true,
-                       "regenerator": true,
-                       "useESModules": false
-                   }]
-               ]
-           },
            exclude: /node_modules/
        },
        {
            //... other loader options
        }]
    }
}
{
    "plugins": [
        ["@babel/plugin-transform-runtime", {
            "corejs": 2,
            "helpers": true,
            "regenerator": true,
            "useESModules": false
        }]
    ]              
}

再次运行打包命令后,使用IE9打开,可以发现Promise方法依然可以被正常打印出来

目前通过babel转换后的代码只能支持 IE9+ 无法支持 IE8 及以下浏览器。原因是打包后的文件当中包含了Object.defineProperty方法,IE8 及以下浏览器不支持此方法。暂时还未找到比较完美的解决方案。希望有相关经验经验的小伙伴能帮助解答。

以上是对webpack使用babel进行打包的一些总结,如果有不正确的地方,欢迎各位大佬指出

参考资料

  1. 慕课网 DellLee 大大的课程:基础到实战 手把手带你掌握新版Webpack4
  2. babel官方网站: https://babeljs.io/
上一篇 下一篇

猜你喜欢

热点阅读