Yakim shu Hi, 這是我擴充腦內海馬體的地方。

[第二十一週] React 環境建置:手把手步驟 & 超級懶人包

前置作業

因為 React 會用到 webpack、babel 等等,所以環境建置會麻煩一些,但還是有些懶人建置指令一次完成,在文章最下面會介紹。

但其實不管怎樣,跑一次流程都會讓你對 React 的運作更清楚,所以自己跑過建置環境還是必要的步驟。


1. 用 webpack 打包 js

因為寫 React 會用到 import 語法,所以需要 webpack 來幫我們做 bundle

npm init
yarn add webpack webpack-cli
export function log(str) {
  console.log(str);
}
import { log } from './utils';
log('hello world');
const path = require('path');

module.exports = {
  entry : './src/index.js',
  output : {
    path: path.join(__dirname, '/dist'),
    filename : 'bundle.js'
  }
}
"scripts": {
    "start": "webpack --mode development",
    "build": "webpack --mode production",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
npm run start
<script src="./dist/bundle.js"></script>

2. babel 轉成 ES5

因為許多瀏覽器還是不支援 ES6 語法,所以需要 babel 轉成 ES5 語法,而且需要 babel 轉化 JSX 語法

yarn add @babel/core babel-loader @babel/preset-env
{
  "presets" : ["@babel/preset-env"], // 符合大部分現代瀏覽器的
}

設定完之後,當 webpack 在打包的時候看到 .js 結尾的檔案時,就會用 babel-loader 去把它轉化成 ES5 再 load 進來

module.exports = {
  entry : './src/index.js',
  output : {
    path: path.join(__dirname, '/dist'),
    filename : 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/, 
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  }
}

3. 加入 React

yarn add react react-dom @babel/preset-react
{
  "presets" : ["@babel/preset-env", "@babel/preset-react"],
}
import React, {Component} from 'react';

class App extends Component { // => Component
  render() {
    return (
      <h1>hello React</h1>
    )
  }
}

export default App; // 記得 export 出去

底下這段的意思是當成是執行到這段時,會找到 #root 這個元素,將 App 這個 Component render 在這個 #root 的 DOM 裡面。

import React from 'react';
import ReactDom from 'react-dom';
import App from './App';

ReactDom.render(<App />, document.getElementById('root')); // => 將 APP render 到 #root 元素

4. webpack dev server

以上就算環境建置完成了,但還是有美中不足的地方,接下來的步驟是讓開發環境更友善一點:

☞ 第一個優化: 檔名加入 hash 防止被 Cache

為了避免打包出來的 bundle.js 被瀏覽器 cache 住,webpack 有提供一個貼心功能 hash,將打包出來的 bundle.js 的檔名加入 hash 防止 cache

filename: 'bundle.[hash].js'

所以打包出來的檔名會像 bundle.a3jk23423adsf397s.js

但這樣就會碰到另一個問題了,index.html 不就要同時更新的 js 檔名嗎?

yarn add html-webpack-plugin
const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry : './src/index.js',
  output : {
    path: path.join(__dirname, '/dist'),
    filename : 'bundle.[hash].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/, 
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  },
  plugins: [
    new htmlWebpackPlugin({
      template: './index.html' // => 以主目錄的 index 為範本
    })
  ]
}

☞ 第二個優化: webpack-dev-server 網頁自動更新

像這樣每做一個小修改就要重新 build bundle.js 也太麻煩了吧,所以現在要實現的功能是每次存檔就會自動更新網頁,不用再手動下指令。

所以這次的工具叫做 webpack-dev-server

yarn add webpack-dev-server
  "scripts": {
    "start": "webpack-dev-server --mode development --open --hot",
    "build": "webpack --mode production",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

環境建置超級懶人包

嫌以上步驟都太麻煩嗎?

其實 React 有提供一個很方便的指令,可以把上述步驟一鍵完成 ( 包括 hot reload ),只要照官網輸入:

npx create-react-app my-app
cd my-app
npm start

成功之後應該就會自動跑出 localhost:3000 的網頁囉!

其實這指令的背後跟我們剛剛做的事情是一樣的,只是他用一個指令把剛剛的步驟都包裝起來,但缺點是有可能安裝了許多你不需要的東西,功能比剛剛自己建置的還多,所以還是要看個人需求。


( 以上內容大部分是 程式導師實驗計畫第三期 的學習筆記,如有錯誤歡迎糾正,非常感謝 🤓 )