Webpack_(第三章)_使用Babel处理ES6语法

使用Babel处理ES6语法(1)

如何结合webpack与Babel使我们在项目中编写ES6的语法
在index.js 写一些ES6的语法

const arr = [
  new Promise(() => {}),
  new Promise(() => {})
]
arr.map(item => {
  console.log(item)
})

运行npx webpack打包
为什么是运行npx webpack而不是用webpack-dev-server配置的npm run start
原因是想看一下npx webpack打包生成的main.js文件,如果使用webpack-dev-serve做打包的话,打包生成的文件都在内存里面
打开main.js代码
在这里插入图片描述
在main.js的最后,实际上是src目录下index.js代码打包生成的内容,在src下的代码原封不动的打包出来,那么这个时候就会有一些问题。这段代码能不能在浏览器中正确的运行呢?
运行npm run start查看一下ES6的运行结果
在这里插入图片描述
在控制台中可以打印出promise对象,这是为什么呢。Chrome浏览器与时俱进,ES6规范的很多内容都做了实现,所以在Chrome浏览器写ES6的语法都能进行,但假如在IE浏览器打开的话,尤其是低版本的一些IE浏览器,包括国产的一些浏览器,程序执行就会报错,因为这些浏览器执行的也是main.js打包生成的代码,这些浏览器不支持ES6的语法,就会报错。
如果我们在src目录下去写ES6的代码,webpack会把ES6的代码都转换成ES5的代码,这样的话所有的浏览器运行就都不会有问题了。
要想实现这样的功能,我们可以借助Babel来实现。
Babel可以把ES6的语法转换成ES5的语法,我们在webpack中使用Babel。
执行 npm install -D babel-loader @babel/core, 安装babel-loader和babel/core(Babel的核心库)
在webpack-config.js中做配置项中增加一条规则

  module: {
    rules: [
      {
        test: /\.js/,
        exclude: /node_modules/, exclude的含义是如果js文件在node_modules中,那么就不使用babel-loader
        loader: 'babel-loader'
      }
    ]
   }

如果检测到是js文件,那么使用babel-loader来进行语义的分析。
还需要再安装 npm install @babel/preset-env -D
为何 安装preset-env这个模块,因为在使用babe-loader处理js文件的时候,实际上babel-loader只是webpack和babel做通信的一个桥梁,用了它之后webpack和babel打通,但是实际上babel-loader并不会帮助我们把js里的ES6语法翻译成成ES5的语法,还需要借助一些其他的模块才能完成语法翻译,preset-env模块就是起到这个作用,preset-env模块包括了所有ES6转换成ES5语法的规则
安装好了preset-env,还需要做一下配置
使用loader的时候可以给loader一个options配置参数

      {
        test: /\.js/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env']  将这个包名放在presets中就可以了
        }
      },

至此,配置就完成了
执行npx webpack ,查看生成的main.js
在这里插入图片描述
然后发现ES6的语法被翻译成了ES5的语法,const变为var,箭头函数变为普通函数,但是光做到这一点还不够,比如说promise这样新的语法变量包括数组里面的map方法在低版本的浏览器中实际上还是不存在的,虽然做了翻译,但是只翻译了一部分,还有一些对象和函数再一些低版本浏览器中还是没有的,所以不仅需要使用preset-env做语法的翻译,还需要把缺失的变量或者函数补充到低版本浏览器里,怎么补充呢
利用babel的polyfill
安装 npm install --save @babel/polyfill
安装完怎么使用呢,只需要在多有代码运行之前先去引入import '@babel.polybill'来补充缺少的内容就好了
import '@babel.polybill'放在index.js文件头部就可以了
现在代码基本完善了,使用@babel/polyfill打包完成后的main.js会大很多,多出来的就是polyfill要去补充的低版本浏览器不存在的内容。如果我们不需要把一下没用到的语法也打包进main.js,比如现在只需要promise和map方法,如何配置呢
给preset-env增加一个新参数

      {
        test: /\.js/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: [['@babel/preset-env', {
            useBuiltIns: 'usage'
          }]]
        }
      },

useBuiltIns: 'usage'的意思是当做polyfill做填充的时候,往页面上加一些低版本浏览器可能不存在的特性时,不是把所有的特性都加进来,是根据业务代码来决定的。按需添加。
这样打包完成的main.js比全部打包小了很多,也同样可以在低版本中运行了

使用Babel处理ES6语法(2)

Babel的presets还可以配置一些额外的参数
比如targets属性

        options: {
          presets: [['@babel/preset-env', {
            targets: {
              edge: '17',
              firefox: '60',
              chrome: '67',
              safari: '11.1',
            },
            useBuiltIns: 'usage'
          }]]
        }

意思是打包生成的项目会运行在大于67的版本下,babel在打包的过程中,使用present-env结合babel /polyfill要去把ES6的语法变成ES5的语法,要看是否有必要做ES6到ES5的转换,是否有必要往项目里注入一下promise和map这样的函数,Chrome浏览器67以上的版本,里面对ES6支持的很好,其实完全没必要做ES6转ES5这样的操作,这样配置过后再来打包,项目就会小很多

在开发一个内库和第三方模块的时候,或者是开发一个组件库,使用babel/polyfill这种方案是有问题的,因为它在注入promise和map这样的函数,它会通过全局变量的形式来注入,会污染到全局环境,所以在打包UI组件库或者内库这样的情况下,需要换一种配置的方式,在index.js 中去掉polyfill的引入。
安装 npm install @babel/plugin-transform-runtime -D
还要安装 npm install -save @babel/runtime
babel对应的loader中增加plugins的配置

        options: {
          // presets: [['@babel/preset-env', {
          //   targets: {
          //     edge: '17',
          //     firefox: '60',
          //     chrome: '67',
          //     safari: '11.1',
          //   },
          //   useBuiltIns: 'usage'
          // }]]
          plugins: [['@babel/plugin-transform-runtime', {
            corejs: 2,
            helpers: true,
            regenerator: true,
            useESModules: false
          }]]
        }

如果配置了corejs: 2,那么需要额外安装 npm install --save @babel/runtime-corejs2,重新打包运行项目
corejs: 2的作用是当页面不存在一个promise和map方法的时候,它才会去把这个代码打包到main.js里面,如果不配置的话,是不会打包的进来的
综上,如果写的只是业务代码,那么配置的话只需要配置presets,同时,在index.js引入babel/polyfill即可, 如果写的是一个库项目代码的时候,需要使用babel/plugins-transform-runtime这个插件,这个插件的好处是可以有效的避免presets的一个问题,或者是说polyfill的一个问题,polyfill会污染全局,plugins-transform-runtime会以闭包的形式去注入,或者帮助组件去引入对应的内容,不存在全局污染的这样的概念,所以写内库的时候不去污染全局环境,是一个更好的方案。

babel对应的配置项会非常的多,如果我们认真的去配置babel相关的内容的时候,就会发现options的内容可能非常的多,如何解决这个问题呢?
我们可以在项目的跟目录创建一个.babelrc的文件,把options这个对象都拿出来放在该文件里
在.babelrc文件里

{
  "plugins": [["@babel/plugin-transform-runtime", {
    "corejs": 2,
    "helpers": true,
    "regenerator": true,
    "useESModules": false
  }]]
}

在webpack.config.js中的babel配置中去掉options的配置项即可

以上就是babel经常用的两种配置方案

发布了137 篇原创文章 · 获赞 30 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/hani_wen/article/details/100029991
今日推荐