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經常用的兩種配置方案

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章