webpack-babael7转译ES6

如今 JavaScript代码主要采用 ES6编写,但并非全部浏览器都支持 ES6语法,所以,在其中须要某种转化机制,也就是将 ES6+语法转化为 ES5语法, babel7能够帮助咱们作到这件事。

一、babel介绍

babel-loader是一个webpack的加载器,用于将ES6+转译成ES5,要开始使用babel-loader,咱们须要安装一些依赖项,以babel7为例,有这么一些依赖:javascript

  • @babel/core
  • @babel/preset-env
  • @babel/plugin-transform-runtime
  • @babel/polyfill

下面细说如下这些依赖具备是干什么的:
@babel/core
这是babel编译库的核心包
@babel/preset-env
这个包是指编译时会自动按照最新的转译规则去编译,除了这个包外还有一些规则包,好比babel-preset-es2015(将es6javascript代码转化浏览器兼容javascript代码), babel-preset-es2016(将es7javascript代码转化浏览器兼容javascript代码), babel-preset-es2017(将es8javascript代码转化浏览器兼容javascript代码)等。
@babel/polyfill
接下来咱们继续说babel/polyfill是个什么东东。babel官网上写了很明确一句话,babel只负责对语法进行编译。当咱们写尖头函数,babel会帮你把它编译成普通函数,这没有任何问题,可是,好比说咱们代码里使用了promisebabel打包出来的代码其实仍是promise,在低版本浏览器里,promise并不支持,可是babel并不会帮你处理,由于这不是语法编译层面须要作的事情。不转换新的API包括,好比Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象。
因而,若是咱们要让打包出来的代码能兼容低版本浏览器,还要考虑到promise,Set这样的新语法低版本浏览器不兼容的问题,这时候babel/polyfill就出场了。你只须要全局安装一下babel/polyfilljava

npm install --save-dev @babel/polyfill

而后在项目中使用一下它,你的代码就不存在刚才提到的兼容性问题了。node

import '@babel/polyfill'

可是,直接用babel-polyfill会有一些坑,第一个坑是污染全局环境,好比说低版本浏览器没有Set,可是babel-polyfill会在全局变量里加一个Set。再一个问题是,会形成代码冗余,举个例子,多个模块用到Promise,每一个模块里都有可能独立存在一个对Promise作兼容性的代码。因此,使用babel-polyfill能够解决兼容性问题,但并非最佳方案,因而,出现了babel-plugin-transform-runtime,使用这个插件,就能够解决上面的问题了。webpack

@babel/plugin-transform-runtime
为了避免污染全局对象和内置的对象原型,可是又想体验使用新鲜语法的快感。就能够配合使用babel-runtimebabel-plugin-transform-runtime。 好比当前运行环境不支持promise,能够经过引入babel-runtime/core-js/promise来获取promise, 或者经过babel-plugin-transform-runtime自动重写你的promise。也许有人会奇怪,为何会有两个runtime插件,实际上是有历史缘由的:刚开始开始只有babel-runtime插件,可是用起来很不方便,在代码中直接引入helper 函数,意味着不能共享,形成最终打包出来的文件里有不少重复的helper代码。因此,Babel又开发了babel-plugin-transform-runtime,这个模块会将咱们的代码重写,如将Promise重写成_Promise(只是打比方),而后引入_Promise helper函数。这样就避免了重复打包代码和手动引入模块的痛苦。git

在使用@babel/plugin-transform-runtime以前须要安装@babel/runtime,由于前者依赖后者。es6

用了babel-runtime 就能够不用 babel-polyfill 了,连接https://babeljs.io/docs/en/babel-plugin-transform-runtime/有说明github

二、webpack中配置babel

① 安装依赖web

npm i @babel/core babel-loader @babel/preset-env @babel/plugin-transform-runtime @babel/polyfill @babel/runtime--save-dev

② 在项目的根目录中建立名为 .babelrc 的新文件来配置 Babel:npm

{
  "presets": ["@babel/preset-env"],
  "plugins": ["@babel/plugin-transform-runtime"]
}

③ webpack 配置 loader(加载器)promise

module: {
  rules: [
    {
      test: /\.js$/, // 使用正则来匹配 js 文件
      exclude: /node_modules/, // 排除依赖包文件夹
      use: {
        loader: 'babel-loader' // 使用 babel-loader
      }
    }
  ]
}

webpack.config.js 最终配置:

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  entry: './babel7转义ES6.js',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js',
    publicPath: __dirname + '/build/'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin() // 会删除上次构建的文件,而后从新构建
  ]
}

④ 在 app.js 全局引入 @babel/polyfill 并写入 ES6 语法,并执行 npm run build 打包

// 测试 ES6 语法是否经过 babel 转译

import '@babel/polyfill'
const array = [1, 2, 3]
const isES6 = () => console.log(...array)

isES6()

const arr = [new Promise(() => {}), new Promise(() => {})]

arr.map(item => {
  console.log(item)
})

5.png
全局引入 @babel/polyfill 的这种方式可能会导入代码中不须要的 polyfill,从而使打包体积更大
更改 .babelrc,只转译咱们使用到的

/**
* babel配置文件
*/
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",// 按需引入
        "corejs": "3.3.2"
      }
    ]
  ],
  "plugins": ["@babel/plugin-transform-runtime"]
}

同时,将全局引入这段代码注释掉,再次打包

// 全局引入
// import '@babel/polyfill'

6.png
参考文章:
https://zhuanlan.zhihu.com/p/35378233
http://www.javashuo.com/article/p-ambqyqxk-ev.html
https://www.jianshu.com/p/7bc7b0fadfc2
https://github.com/SunshowerC/blog/issues/4

相关文章
相关标签/搜索