Front-end

前言

在前面幾篇裡面,我們知道 CORS protocol 基本上就是為了安全性所產生的協定,而除了 CORS 以外,其實還有一系列跟跨來源有關的東西,例如說:

  1. CORB(Cross-Origin Read Blocking)
  2. CORP(Cross-Origin Resource Policy)
  3. COEP(Cross-Origin-Embedder-Policy)
  4. COOP(Cross-Origin-Opener-Policy)

是不是光看到這一系列很類似的名詞就已經頭昏眼花了?對,我也是。在整理這些資料的過程中,發現跨來源相關的安全性問題比我想像中還來得複雜,不過花點時間整理之後發現還是有脈絡可循,因此這篇會以我覺得應該比較好理解的脈絡,去講解為什麼會有這些東西出現。

除了上面這些 COXX 的各種東西,還有其他我想提的跨來源相關安全性問題,也會在這篇一併提到。

在繼續下去之前先提醒一下大家,這篇在講的是「跨來源的安全性問題」,而不單單只是「CORS 的安全性問題」。CORS protocol 所保護的東西跟內容在之前都介紹過了,這篇要談的其實已經有點偏離大標題「CORS」完全手冊,因為這跟 CORS 協定關係不大,而是把層次再往上拉高,談談「跨來源」這件事情。

所以在看底下的東西的時候,不要把它跟 CORS 搞混了。除了待會要講的第一個東西,其他的跟 CORS 關係都不大。

閱讀更多

前言

在上一篇裡面我們提到了常見的 CORS 錯誤解法,以及大多數狀況下應該要選擇的解法:「請後端加上 response header」。

但其實「跨來源請求」這個東西又可以再細分成兩種,簡單請求跟非簡單請求,簡單請求的話可以透過上一篇的解法來解,但非簡單請求的話就比較複雜一些了。

除此之外,跨來源請求預設是不會把 cookie 帶上去的,需要在使用 xhr 或是 fetch 的時候多加一個設定,而後端也需要加一個額外的 header 才行。

與 CORS 相關的 header 其實不少,有些你可能聽都沒聽過。原本這篇我想要把這些東西一一列出來講解,但仔細想了一下覺得這樣有點太無趣,而且大家應該看過就忘記了。

那怎樣的方法會比較好呢?大家都喜歡聽故事,因此這篇讓我們從故事的角度下手,為大家講述一段愛與 CORS 的故事。

主角的名字大家都知道了,對,就是毫無新意的小明。

閱讀更多

前言

在上一篇 CORS 完全手冊(一):為什麼會發生 CORS 錯誤?裡面,我們理解了為什麼瀏覽器要有 same-origin policy,以及跨來源請求擋的其實是 response 而不是 request。在釐清了一些錯誤的觀念以及對 CORS 有基本的認知以後,就可以來講講怎麼樣解決 CORS 的問題。

先跟大家預告一下,這篇會提到的解決問題的方法並不完整。事實上,跨來源請求分成兩種,簡單請求跟非簡單請求,「跨來源請求擋的其實是 response 而不是 request」基本上只適用於簡單請求,而這一篇只會針對「簡單請求」,至於到底怎麼分簡單還是非簡單,以及非簡單的要如何處理,這些都會在下一篇提到。

想要解決基本的 CORS 錯誤,其實有滿多種方法,先來介紹幾個「治標不治本」的:

  1. 關掉瀏覽器的安全性設置
  2. 把 fetch mode 設成 no-cors
  3. 不要用 AJAX 拿資料

以下就會先針對這三個方法再進一步講解,講完以後我們會來講最後一個也是最正確的做法:「請後端加上 CORS header」。

閱讀更多

前言

三年前的時候寫了一篇文章:輕鬆理解 AJAX 與跨來源請求,提到了串接 API、AJAX、same-origin policy、JSONP 以及 CORS,當時把自己想講的都放進去了,但現在回頭看,好像有很多滿重要的部分沒有提到。

三年後,再次挑戰這個主題,並且試著表達地更完整。

會想寫這個系列是因為在程式相關的討論區上,CORS 是發問頻率很高的主題,無論是前端或是後端都有可能來問相關的問題。

所以我就想說:「好,那我來寫一個系列好了,我要試著把這個主題寫到每個碰到 CORS 問題的人都會來看這個系列,而且看完以後就知道該怎麼解決問題」,這算是我對這篇文章的目標,如果文章的品質沒辦法達成這個目標,我會持續改進。

這系列一共有六篇文章,分別是:

會從 same-origin policy 開始講起,接著講到為什麼跨來源存取資源會有錯誤,再來會講如何錯誤地以及正確地解決 CORS 相關的問題,而第三篇會詳細講解跨來源請求的詳細流程,像是 preflight request 之類的東西。

基礎的部分看前三篇就夠了,接下來會比較深一點。第四篇會帶你一起看 spec,證明前面幾篇不是我在虎爛的,而第五篇則是帶大家看看 CORB(Cross-Origin Read Blocking)、COEP(Cross-Origin Embedder Policy)或是 COOP(Cross-Origin-Opener-Policy)之類的跨來源相關規定,以及相關的安全性問題,最後一篇則是一些比較零散的主題以及心得感想。

閱讀更多

前言

當你獲得了一個知識之後,要怎樣才能知道那是正確的還是錯誤的?在程式的領域中這其實是一個相對簡單的問題,只要去確認規範是怎麼寫的就可以了(如果有規範的話)。

舉例來說,JavaScript 的各種語言特性在 ECMAScript Specification 裡面都找得到,為什麼 [] === [] 會是 false,為什麼 'b' + 'a' + + 'a' + 'a' 會是 baNaNa,這些在規範裡面都有,都會詳細說明是用怎樣的規則在做轉換。

而 Web 相關的領域除了 JS 以外,HTML 或是其他相關的規範幾乎都可以在 w3.org 或是 whatwg.org 裡面找到,資源相當豐富。

雖然說瀏覽器的實作有可能跟規範寫的不一樣(像是這篇),但 spec 已經是最完整而且最有權威性的一個地方了,因此來這邊找準沒錯。

如果搜尋 CORS 的 spec,可能會找到 RFC6454 - The Web Origin Concept 以及 W3C 的 Cross-Origin Resource Sharing,但這兩份都叫這一份叫做 Fetch 的文件給取代了。

當初我疑惑了一陣子想說是不是自己看錯,fetch 跟 CORS 有什麼關係?後來才知道原來這邊的 fetch 跟 Web API 那個 fetch 其實不同,這份規格是定義了所有跟「抓取資料(fetch)」有關的東西,就如同它的大綱所寫的:

The Fetch standard defines requests, responses, and the process that binds them: fetching.

這一篇就讓我們一起來看一下 CORS 相關的規範,證明我前面幾篇沒有在唬爛你,講得都是有所根據的。因為規格還滿長的,所以底下就是我挑幾個我認為的重點講而已,想要理解所有的規格內容,還是需要自己去看才行。

閱讀更多

前言

不知道大家有沒有聽過 vite 這個工具,看它名字有個 v,大概就可以猜到可能跟 Vue 有關。沒錯,這是 Vue 的作者尤雨溪開發出來的另外一套工具,原本是想要給 VuePress 用的,但是強大之處就在於它不僅限於此。

Vite 在 GitHub 上的 About 只寫了兩個句子:

Native-ESM powered web dev build tool. It’s fast.

如果你有體驗過,就會發現真的很快。Vite 是 build tool 跟 dev server 的綜合體,這篇會簡單教大家使用一下 vite,然後來談 ES modules,再來看看 vite 神奇的地方。

閱讀更多

前言

之前在公司裡面做一些效能上的調整時,無意間發現了一個奇怪的現象,繼續往下追查之後才發現是個好像沒有被什麼人發現過的 bug,而且成因我覺得挺有趣的,就想說可以寫一篇跟大家分享一下。

這篇技術含量不高,可以抱持著看故事的心態來看這篇,會比較有趣一點。

故事的開端

故事的起源呢,是之前在公司裡面要做一些網站上的調整,試著增進一下載入的速度。當我們談到性能最佳化這一塊,其實有很多可以做的,例如說跟 Server 那邊比較有關的是:

  1. 使用 HTTP/2
  2. 使用 gzip 或是 brotli 進行壓縮
  3. 使用 Cache(可以加快 revisit 的速度)
  4. 使用 CDN
  5. 降低 TTFB 時間

不過以上都需要後端或是 SRE 的協助,跟前端其實關係不大。跟前端關係比較大的,也可以分成很多面向來看,例如說以「減少資源」的角度來看,可以做的事情有:

  1. Image 格式調整(壓縮 + webp 或其他格式)
  2. JS 大小(ugligy、code spliting、dynamic import)
  3. CSS 大小(minify、移除不需要的 CSS)

如果以「加速載入重要資源」的角度,可以加上 preload 或是 preconnect 這些 hint,來提示瀏覽器哪些東西應該先被載入。

還可以從「減少 JS 執行時間」的角度來看,例如說如果是寫 React,可以用 shouldComponentUpdate、PureComponent 或是 memo 來減少不必要的 re-render。

這一篇既然標題都寫 styled components 了,主題當然就是圍繞在 CSS 這一塊。

閱讀更多

前言

在我的部落格裡面,其實很少有工具類的教學文章。一來是因為這種工具類文章都大同小異,二來是我生性懶惰,許多手把手教學都需要鉅細靡遺外加豐富截圖,實在是不適合我。

但這次會來寫這個題目,是因為我覺得 webpack 是個新手不容易懂,就算懂了也不一定是真的懂的工具。或是換句話說,它是常常被誤解的一個工具。

這並不是 webpack 本身的問題,而是現在許多新手切入前端都直接從 React 或是 Vue 開始,而且都使用了他們各自提供的 CLI 工具,等到要客製化一些設定時才注意到:「阿,原來有個東西叫做 webpack」。

CLI 工具帶來了方便性,優點是讓新手能夠快速上手,不用去管那些繁瑣的設定;而缺點就是若是新手沒有意識到背後那些工具,等到哪一天工具壞了、不能用了或是有地方需要修改,就是噩夢的開始。

為了讓這種情況減少,我才決定寫這篇文章,希望從源頭帶大家認識 webpack 這項工具以及模組化的概念。你必須先知道什麼是模組,才能理解什麼是 webpack。

開頭我想先透過幾個問題讓大家思考自己對模組化以及 webpack 是否熟悉:

  1. 為什麼很多專案(例如說 React)在部署前都要先 build?這個步驟在幹嘛你知道嗎?
  2. 你知道 require/module.exportsimport/export 的差別嗎?
  3. 你知道 import 與 export 這兩個語法在瀏覽器上面不是隨便就能使用嗎?
  4. 你知道為什麼要用 webpack 嗎?
  5. 你知道 webpack 為什麼要有 loader 嗎?

這些問題應該會在讀這篇文章時慢慢有點靈感,在最後面時會幫大家解答。

閱讀更多

簡介

近幾年前端框架大放異彩,許多新手才學沒多久的 JavaScript,就直接學習三大框架了(雖然 React 不是框架,但整個生態系其實就跟框架沒兩樣,因此我覺得歸類在框架也不是不行)。

而這三大框架通常都是拿來寫 SPA(Single Page Application)用的,我一直認為在學習這些框架前應該要具備一些基礎知識,尤其是對於前後端的理解,否則一定會遇到很多不知道從何解起的問題。

因此,本文舉出一個我自己曾經碰過,學生也常常跑來問我的問題當作範例,大家也可以先想一下自己能不能回答出這個問題:

假設今天我有個 SPA,搭配某些 router 的 library 來實作路由,所以 /list 會連到列表頁,/about 會到關於我的頁面。

可是奇怪了,當我把 SPA 上傳到 GitHub Pages 之後,首頁是好的,我從首頁進去 /list 也是好的,可是當我在 /list 重新整理的時候,卻顯示 404 not found,這是為什麼呢?

要回答這個問題,必須先來複習一下前後端相關的網路基礎知識。

閱讀更多

(原文寫在 Medium,順便在這邊備份一下)

雖然說我一直很清楚自己目前偏好的學習方法以及路線,並且把我認為適合的路徑都變成上課的大綱拿去教學,但一來好像沒多少人會去看那個大綱,二來大綱並沒有詳細解釋背後的原因。因此我才覺得自己有必要寫這一篇,來寫一下自己認為比較「紮實」的網頁前端學習路線。

閱讀更多