iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 4
5

前言

基本上瀏覽器只看得懂三種語言,分別是 HTM、CSS 和 JavaScript,因此接下來學習 React 使用的 JSX 語法,瀏覽器無法讀懂,也沒辦法執行正確的結果給我們,因此我們需要 Babel 幫忙,它會依照語法規則將程式碼翻譯給瀏覽器看。

Babel 可以將程式碼編譯成網頁看得懂的樣子。

但 Babel 處理的也不全然是 JavaScript 外的語法,有些新版本的 JavaScript 瀏覽器開放支援前也會看不懂,這時候 Babel 也能將這些新版本的語法翻譯成舊的版本,讓大部分的網頁能夠正確執行。

Babel 也能夠處理不同瀏覽器對 JavaScript 的支援程度。


前置準備

  1. 文中的專案會以前一天的專案架構繼續講解,如果未跟到前一天的進度,可以從 GitHub 上 Clone 下來。
  2. 一顆擁有學習熱忱的心。

注意!
如果 ESLint 沒有反應,要再用以下指令另外下載 @babel/runtime:

npm install @babel/runtime --save-dev

他是 Day02 的 eslint-config-airbnb 依賴套件,雖然 Day02 很正常,但複製到 Day03 就出現找不到這個套件的錯誤,我不確定是不是大家都會有這個狀況,如果是的話麻煩留言告訴我,我會直接將該套件補到 Day02 的 Package.json 裡。


使用方法

確認使用情境

在開始前,先將 src/index.js 打開,並將內容改為下方:

for (let i = 0; i <= 10; i += 1) {
  console.log(i);
}

完成後透過 npm run build 讓 Webpack 將它打包,並打開打包後的 dist/bundle.js:

會發現在宣告時,依舊是用 let,也就是說

Webpack 到目前為止都只是將所有用到的檔案或套件給打包成同一份執行,

這也是 Webpack 的基本工作,但並不是所有的瀏覽器版本都能夠正確支援 let,於是為了能使用這些好用的新版本 JavaScript 語法,就得搭配使用 Babel 替程式做翻譯。

因為目前還沒在專案裡裝上 React,因此本階段的首要目標,先讓 ES6 的語法能正確被轉換。

安裝 Babel

開啟專案後,輸入以下指令安裝 Babel 的核心套件:

npm install @babel/core @babel/cli --save-dev

安裝 Preset 語法規則

不同的編譯對象會有不同的 Preset,它會觀察程式裡有哪些地方需要做處理語法轉換,因此下載對 ES6 轉換語法的 Preset:

npm install @babel/preset-env --save-dev

在 Webpack 中設置 Babel

Babel 會有個設定檔 babel.config.js,但目前暫時不需要也沒關係,因為 Webpack 在編譯時能夠設定 loader 使用 Babel,因此先下載 Webpack 需要的 loader 套件:

npm install babel-loader --save-dev

下載完後,到 webpack.config.js 中的 module 中設置轉換規則:

const path = require('path');
module.exports = {
  /* 其餘省略 */
  module: {
    rules: [
      {
        test: /.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
};

關於上方的設置內容,有幾個比較需要了解:

  1. rules:之後如果有新要轉換語法的地方,都會在這邊設置,包括 Sass 轉換成 css 也是。
  2. test:這裡是目標檔案的副檔名,上方用正規表達式處理,讓所有 .js 結尾的都經由這個 rules 的 loader 做轉換。
  3. presets: 針對不同的副檔名(例如:JSX)會有不同的 Preset,而同一種副檔名也能夠使用多個 Preset。

重新編譯

接著使用 npm run build 再做一次編譯,就會看到他已經成為大部分瀏覽器都支援的可愛模樣:

下載 React

今天再請大家陪我久一點,接下來要下載 React,透過 Babel 從 JSX 轉換成一般的 JS:

npm install react --save
npm install react-dom --save

下載好後,打開 src/index.js,將檔名改成 index.jsx,並在裡面輸入:

import React from 'react';
import ReactDom from 'react-dom';

const Main = () => <h1>Hi JSX!</h1>;

ReactDom.render(<Main />, document.getElementById('root'));

上方這裡先複製貼上,React 的使用方式會在後天開始一一為大家說明,今天的目的要能正確編譯 JSX 到 JavaScript。

接下來要下載負責編譯 JSX 語法的 Preset:

npm install @babel/preset-react --save-dev

載好後,再回到 webpack.config.js 身上,加入對 jsx 的 loader,也不要忘了將 entry 的檔案從原本的 index.js 改成 index.jsx:

entry: './src/index.jsx',
module: {
  rules: [
    /* 其餘省略 */
    {
      test: /.jsx$/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-react', '@babel/preset-env'],
        },
      },
    },
  ],
}

這裡的 Preset 配置了兩個,因為 @babel/preset-react 只負責轉換 JSX 的語法,並不會幫忙處理 ES6 的部分,所以另外加上 @babel/preset-env 將 JavaScript 轉換成通用的版本,沒問題的話就能編譯看看:

最後,既然已經打包完 JavaScript 了,何不看看呈現的結果呢?

到 dist 的目錄下新增一個 index.html,並在裡面貼上下方的內容:

<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <div id="root"></div>
        <script src="./bundle.js"></script>
    </body>
</html>

再來將 dist/index.html 用瀏覽器打開,就能看到精美的「Hi JSX!」:

最後來看看 Babel 到底對 JSX 做了什麼,打開 dist/bundle.js 並搜尋 「Hi JSX!」,就能看見他在一片程式海中:

https://ithelp.ithome.com.tw/upload/images/20191017/20106935luMEDcFn34.png

雖然被編譯後的程式碼很亂,但仍然可以在裡面找出一些端倪,就是 createElement,而 createElement 不是別的,它正是 React 內的頂層 API,這裡可以查看 官方文件 內的說明:

https://ithelp.ithome.com.tw/upload/images/20191017/20106935ISo3ePW3Hk.png

其實我們在撰寫的 JSX 只是這些頂層 API 的語法糖而已

這邊就如同上方說的,瀏覽器只看得懂三種語言,分別是 HTML、CSS 與 JavaScript,因此 Babel 也只是將讀到的 JSX 再轉為真正的 JavaScript 寫法,如果沒有 Babel,等於就得親自使用 React 的 createElement 去寫,就會變得更複雜且沒那麼直觀。

今天的完整內容會放到 GitHub 上,歡迎各位參考!


結尾

大概是這三天來最長的一篇,也在前置準備的時候遇到一些小問題,但我還是會好好控制不讓每天的曲線跳得太多,如果對文中 Babel 的使用或操作有任何問題,再麻煩留言告訴我,謝謝大家!


上一篇
Day02 | 整齊的程式,讓看的人長命百歲,給我用 ESLint
下一篇
Day04 | SCSS 加上 Webpack 混搭款,讓你寫 CSS 上天堂
系列文
在 React 生態圈內打滾的一年 feat. TypeScript31

2 則留言

1
ninten
iT邦新手 5 級 ‧ 2019-09-24 14:51:30

ReactDom.render(document.getElementById('root'), );

這行參數好像相反了,會跳出Error: Minified React error #200

不過Github上的程式碼是正確的

萬分感謝!立馬修正過來!

2
alantsui
iT邦新手 5 級 ‧ 2019-10-13 15:16:23

這個系列很好,對C++人來說比較容易入門,不過JS webpack看上去比C++ xmake複雜的說.....

其實我沒有用過 C++ 的 xmake,所以無法體會到
至於 Webpack 最麻煩的應該就是版本的更新速度和豐富的生態圈可以用吧,導致每篇教學感覺都有一點不一樣 /images/emoticon/emoticon01.gif

我要留言

立即登入留言