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

相關文章
相關標籤/搜索