你以為 React 什麼都幫你處理好了嗎?

set: 踩坑分享
tags: React
category: Front-End
description: 你以為 React 什麼都幫你處理好了嗎?
created_at: 2022/05/23 17:30:00

cover image


前言

React確實已經幫忙做掉了好多事( 我指的是 create-react-app ),在環境的部分已經設定好了很多 (像是 Webpack 不常用或不熟的人可能就會搞一陣子)

順便偷偷廣告一下,如果要快速幫你裝好像是 EslintPrettierTailwindcss 之類的環境,可以考慮我做的 cmd: https://github.com/LaiJunBin/lai-cmd


至於為什麼會寫這一篇呢,因為我以為 React 有設定好 Webpack 、 也使用了 Babel 幫忙轉譯,我就以為他應該有幫忙套上一些 Polyfill 去支援一些舊的瀏覽器支援新的語法。 很理所當然地以為他都幫我做好了


大綱

這一篇主要講兩點

  1. 關於 Polyfill
  2. 關於 Source Map

關於 Polyfill

首先是 Polyfill 這個東西,從當初當選手的時候就有聽過這個詞,主要是拿來修復一些舊版瀏覽器不支援新的 JavaScript 語法的類似補丁的東西;但是當初當選手只要在比賽場地中做完當下能 Run 就可以交差了,也沒有後續維護之類的問題 (雖然時間相對緊湊),所以也沒特別去使用過。

而前陣子在實習公司有個案子就有個功能我使用到了 matchAll 這個函數,在 iOS 12 炸掉才發現原來 React 沒有幫忙做掉這個部分。

所以首先你要先有一個空的或既有的專案,再來實驗以下的內容。

首先在你的 App.js 加入下面這一段

function App() {

  console.log(''.matchAll)  // <-- 這一行,沒有括號哦!

  return (
    // 略
  );
}

沒有呼叫函數的話可以印出那個函數的定義,如果他不存在就會是 undefined,但是一般現在瀏覽器應該都支援,就會看到下面的結果。

ƒ matchAll() { [native code] }

那再來看看這個函數的支援度: match-all-browser-cap

順帶一提: Safari 的版本是跟 iOS 版本一致的。

所以這麼剛好,Safari 12 剛好不支援,所以如果你剛好有舊的裝置或是模擬器可以測,或是找找看有沒有別的函數支援度更差的來實驗來玩(?)

因為特別開舊的 Demo 來貼圖呈現好像也沒什麼太大意義,畢竟就只是個 Undefinedƒ matchAll() { [native code] } 的差異 (?

所以以下就用文字來描述吧 (反正你也應該是有問題才會來用,所以應該是有環境的)


首先既然要有補丁(Polyfill),那你要嘛自己寫或是找現成的,自己寫可能會比較麻煩,而且可能沒處理好就有 bug(?),如果是自己寫補丁來實現某件事,我更傾向於換個寫法達到同樣的目的。(除非你有大量地方用到真的需要先抽一層出來,或是你已經沒辦法改既有的 code 了)

舉例來說假設你要做 matchAll 這件事情,就先想想真的有必要使用他才能抓出你要的資訊嗎?

或許這個舉例不太好,不過懂我的意思就好,我這次爆炸是用在於我拿他來抓取路由參數。

Example:

/users/:id/xxx/:yyy/zzz

而你想抓出 idyyy,你不只可以使用 matchAll , 其實你使用單純的 split 再加以判斷,也可以達到一樣的效果。


再來就開始安裝 Polyfill 吧,這邊使用的是 core-js: https://www.npmjs.com/package/core-js

基本上非常簡單,照著他的說明安裝然後 import 基本上就能動了。

安裝 core-js

npm i core-js

安裝好之後,以我們這次的範例是 matchAll 這個函數,所以可以去找 string 相關的類別做引入(當然你也可以直接引入整包)

如果整包的話是

import 'core-js/actual';

如果部分引入功能(feature)的話是

import 'core-js/features/string/match-all';

然後你可能打開 開發伺服器 Dev Server之後發現,咦 怎麼沒有反應,還是一樣 Undefined 啊,這可能要檢查你的 package.json

{
  //...
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

主要是這個 browserslist 的值,他代表你的這個應用程式要支援到哪種等級的瀏覽器,這個設定會給很多工具的設定檔吃,他會決定他要不要做事。

所以可能你的 development 的值並沒有涵蓋到你當前測試的環境,以我的例子來說,我如果偷懶我就打 iOS 12,那在開發模式下就也會生效了。

詳細的設定可以去參考 browserslist 可以放哪些東西。(https://github.com/browserslist/browserslist)


關於 Source Map

關於 Source Map 這個的話大家應該就比較不陌生了,簡單來說就是前端工具 build 你還有沒有辦法檢視真正的原始碼, 也就代表著被壓過的原始碼還能不能好好 debug,因為被編譯完大概都長這樣

(()=>{var e={7057:(e,t,a)=>{function n(e){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}!function(){"use strict";var e={},t={};try{"undefined"!=typeof window&&(e=window),"undefined"!=typeof document&&(t=document)}catch(e){}var a=(e.navigator||{}).userAgent,n=void 0===a?"":a,r=e,i=t,o=(r.document,!!i.documentElement&&!!i.head&&"function"==typeof i.addEventListener&&i.createElement,~n.indexOf("MSIE")||n.indexOf("Trident/"),function(){try{return!0}catch(e){return!1}}());

我只從開頭隨便截個一小段,這種東西非常難閱讀,在執行過程如果有噴錯,在 F12主控台(Console) 雖然會顯示哪邊怎麼了,但如果在沒有 Source Map 的情形下點過去就是一坨奇怪的東西(類似上面這樣),而如果你有開啟 Source Map 這個功能,則會在你點出錯的行數導向過去的時候,會幫你映射到你的原始碼,不再是經過壓縮的樣子難以 debug

另外你也可以透過 F12原始碼(Source) 去直接看別人的 Code如果對方沒關你就可以把他看光光


而因為我最一開始是寫 VueVue 在你 build 的時候會自動幫你關掉這個功能,所以我以為,對 又是我以為,我以為 React 也有幫忙做掉這件事XD

結果並沒有,要自己手動關。 所以說不定你去找一些 react 寫的網站別人也沒關ㄛ~

既然我原本以為他有幫我關,那就代表我很舊的專案也都沒關XDD (side project..)

關掉的方式很簡單,這邊提供幾種做法

  1. env 關 (比較推薦)
GENERATE_SOURCEMAP=false
  1. 附加在指令前面 (但是 windows 可能需要額外裝套件)
"scripts": {    
    "start": "react-scripts start",
    "build": "GENERATE_SOURCEMAP=false react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
}



最後更新時間: 2022年05月23日.