Nov. 2022
1 st
打包工具
- Turbopack
Turbopack 是針對 JavaScript 和 TypeScript 優化的增量打包工具。
由 Webpack 的創建者和 Next.js 團隊使用 Rust 編寫。
JavaScript 與 TypeScript 執行環境
Node.js
基於 V8 引擎,並且是由 C++ 語言所建構。
Deno
基於 V8 引擎,並且是由 Rust 語言所建構。
內建支援 TypeScript 執行。
不再需要如 npm 的套件管理工具,同時扮演了套件管理系統的角色。
如果要指定特定版本的套件也可以在 URL 中指定。
3 rd
工具
- Yup
第三方驗證函式庫。
用於解析和驗證 JS 的生成器,使用 Object 的驗證套件。
schema 可以說是對於「資料格式」與「數值」的一種描述架構,透過事先定義 schema 就像先訂好規則,然後要求 form 表單的資料要能夠匹配 schema,而 Yup 就是幫助我們整合這兩者的工具之一。- 優點
- 每個檢核子介面都設計淺顯易懂,且可以串接、好閱讀。
- 基本檢核一應俱全且統一。
- 缺點
- yup 內的程式碼出錯時,不會有任何反應。
建議都需要用
try-catch包起來比較保險。
4 th
CSS
::selection此偽元素將樣式應用於文件中已被使用者選取強調的部分(e.g. 在文件上單擊並拖動鼠標)。
CSS 框架
- Tailwind Tips
集合了有關 Tailwind 的有用小訣竅等。
工具
- Dropcode
簡單輕量的片段程式碼管理器。
5 th
JS
淺拷貝 Shallow Copy
原始物件資料與複製物件資料並非完全獨立,可能第一層就有指向相同地址的資料,也可能第二層才有指向相同地址的資料。
彼此資料內容的改變可能會互相影響。深拷貝 Deep Copy
原始物件資料與複製物件資料完全獨立,沒有任何一層資料指向相同的地址。
彼此資料內容的改變不會互相影響。JSON.parse(JSON.stringify(obj))
某些值經過
JSON.stringify/parse處理後,會產生變化:undefined:會連同 key 一起消失。NaN:會被轉成null。Infinity:會被轉成null。regExp:會被轉成空物件{}。Date:會被轉成String。
_.cloneDeep(obj):ladash 內部的 API。- 寫一份遞迴函式,遍歷 Object data 每一層級資料,將其完全複製新的一份。
6 th
技術
CSR (Client-Side Rendering)
表示所有的頁面渲染 (render) 都透過瀏覽器端的 JS 來完成。
所有的邏輯、取資料、路由、template 都在客戶端處理。- 優點
- 頁面的更新或是換頁都不需要刷新頁面,在使用體驗上相較於傳統的 SSR 應用會順暢許多。
- 缺點
- 載入速度通常較慢,尤其是在低階的行動裝置上。 原因如前所述,因為 CSR 要等待 JS 的下載及執行 render ,所以 CSR 頁面載入的前幾秒,頁面上會沒有東西或是只有一些骨架。
使用者必須要等待一段時間才能看到頁面的內容,相對來說會是較差的使用者體驗。 - SEO 較差,因為 CSR 的頁面對於爬蟲是比較不友善的。 雖然爬蟲有辦法執行 JS,但爬蟲也有一些 JavaScript render 頁面的限制。
SSR (Server-Side Rendering)
表示伺服器收到使用者的請求之後,在伺服器端生成完整的 HTML,再回傳給使用者。
因為生成 HTML 的時候會在伺服器端先取得內部或外部 API 資料,所以相較於 CSR 從瀏覽器端取資料的模式,SSR 可以省去多次的來回往返。- 優點
- 需要的 JS 比較少,因此有較快的 TTI,可以較快開始互動。 原因是相較於 CSR 所有 render 的邏輯都包含在 JS 中,SSR 已經在伺服器端把 render 的工作做完了,SSR 方案中瀏覽器端需要的 JS 理論上會比較少,所以會比較快達到 TTI。
- 有更多的 JS 預算可以留給其他第三方 JS 使用。
- SEO 較佳。 因為 SSR 產生的完整 HTML 可以很容易的被爬蟲解讀,不需要想辦法執行 JS。
- 缺點
- 較慢的 TTFB。 因為在伺服器產生完整的 HTML 很花時間。如果同時有許多人造訪 server 造成負擔很重,或是有一些非常慢的 API,都有可能讓 server 的回應速度非常慢。
- 互動性體驗差。 因為 SSR 的頁面在每次互動之間都要重新讀取頁面,這在使用體驗上就不如 CSR 的頁面順暢,也是現代 web app 大多數會採用 CSR 方案的主要原因。
TIP
- FCP (First Contentful Paint,使用者可以看到頁面上的重要內容的時間點)
- TTI (Time-to-Interactive,使用者首次可以跟頁面互動的時間點)
在 TTI 之前,使用者點畫面上任何東西都不會有反應。 - TTFB (Time to First Byte,從瀏覽頁面的動作開始到瀏覽器收到第一個 byte 所需要的時間)
7 th
CSS
偽元素
不是真正網頁裡的元素,但行為與表現和真正的網頁元素一樣,也可以對其使用 CSS 操控。
在 W3C 的定義裡總共有五個偽元素:::before、::after、::first-line、::first-letter和::selection。::before與::after最常使用的偽元素,兩者都是以
display: inline-block;的屬性存在。::before是在原本的元素之前加入內容,::after則是在原本的元素之後加入內容。
同時偽元素也會繼承原本元素的屬性。一定要具備 content 的屬性,就算是只有
content: "";都可以,因為沒有 content 的偽元素是不會出現在畫面上的,然而 content 是個很特別的屬性,它可以使用 attr 直接獲取內容元素的屬性值(attribute)。
content 內容可以相加的,直接使用一個空白鍵就可以不斷的累加下去。偽元素的內容實際上不存在網頁裡(如果打開瀏覽器的開發者工具,是看不到內容的)。
如果在裡頭放了太多的重要的內容,反而會影響到 SEO 的成效,因此對於使用偽元素的定位,還是當作輔助性質會比較恰當。
10 th
CSS
initial:恢復為該 css 屬性的初始值。每個 css 屬性都有其初始值(initial value),例如背景色的初始值是透明。
inherit:繼承最近的父層 css 屬性值。每個 css 屬性也都有繼承性(inherited)。
例如color有繼承性,而background-color則無。unset:是inherit和initial的結合。在屬性有繼承性時,設定
unset會等同於inherit的功能。
無繼承性時,設定unset則等同於initial。revert:優先恢復為瀏覽器預設。無瀏覽器預設則等同
unset。
HTML
<iframe>:內嵌框架 (Inline Frame)所謂的內嵌框架(內聯框架),用來在一個 HTML 網頁裡面嵌入另外一個 HTML 網頁。
但一般如果不是用來嵌入外站的內容,還是盡量少用iframe,因為對於網頁效能、維護性和 SEO 有非正面的影響。src:指定要被嵌入的網頁的網址 (URL)height:指定 iframe 的高度,單位為像素 (pixel)width:指定 iframe 的寬度,單位為像素 (pixel)name:指定 iframe 的名稱sandbox:當有這屬性時,表示針對 iframe 裡面的網頁啟用一些限制條件。
屬性值如果留空表示啟用所有限制,當有設定值的時候表示移除這些限制,你可以用空格設定移除多個限制條件。
12 nd
clamp(MIN, VAL, MAX)包含三個數值,定義「最大值、最小值以及中間的數值」。
其中MIN表示最小值,VAL表示首選值,MAX表示最大值。- 如果
VAL在MIN和MAX範圍之間,則使用VAL作為函式回傳值。 - 如果
VAL > MAX,則使用MAX作為回傳值。 - 如果
VAL < MIN,則使用MIN作為回傳值。
範例:
javascriptclamp(200px, 100%, 300px);- 如果
15 th
配置
- Package.json
個人筆記連結
19 th
Javascript
- prototype 原型與原型鏈
個人筆記連結
21 st
ES module
ES6 版本新加了 import 和 export,引入了模組化的思維,讓 JavaScript 在開發大型複雜應用程式時,更為方便且易於管理。
只要在 <script> 加上 type="module" 的 attribute,就可以在 script 裡面使用 import 與 export 。
- Default exports & Named exports
// Default exports
export default 7
// Named exports
export const monthDays = 31
export const log = () => { console.log('Hello, world!') }- import 靜態載入
import weekDays, { monthDays, log } from './script.js'
console.log(weekDays) // 7
console.log(monthDays) // 31
log() // Hello, world!- import 動態載入
btn.addEventListener('click', () => {
import('./modules/test.js').then(result => {
console.log(result);
})
});有些 script 只有特定情況才需要時可以使用動態載入,透過管理回傳的
Promise物件,盡可能提升 performance,避免一次性載入太多用不到的 js,造成首次白畫面過長。
- 優點
- 每個
.js都是獨立的作用域(scope),不用擔心變數汙染。 - 每個
.js都自行import自己的依賴,沒有順序相依問題。
24 th
CSS
Positioning schemes(定位規則)
normal flow
HTML 元素就是inline跟block兩類,所以normal flow就是由水平排列,以及垂直向下排列這樣的格式來渲染元素。
除非特別聲明,否則每個元素所產生的box都處在normal flow中。float
box從原本的 normal flow 中脫離出來,並以left、right參數來定位,通常用在文繞圖的排版中。absolute positioning
和 float 同為out of flow(脫離普通流)的定位,並以top、left、bottom、right搭配數值予以定位。Formatting context(格式化上下文)
是 CSS 中對於排版的概念,不同的格式化環境會有不同的渲染規則,決定box怎麼被排列、怎麼影響跟其它 box 的相對位置,也決定了其子元素的排列。 formatting context 有以下類型:
- BFC (Block formatting context)
- IFC (Inline formatting context)
- FFC (Flex formatting context)
- GFC (Grid formatting context)
以上都屬於 normal flow 的 範圍。 除了原本元素產生的原生
box有 block-level box 跟 inline-level box 之外,也可以用 CSS 的display屬性來改變box所參與的 formatting context。
有些屬性可以對box內創造一個 formatting context 的環境,例如生成 BFC、FFC、GFC 渲染環境給後代元素,而 IFC 是指元素參與 IFC 的佈局。BFC(Block formatting context)
是一個獨立的渲染區域,只有 Block-level box 參與,規定了內部的 block-level box 如何佈局,並且與這個區域外部毫無關聯。
佈局規則
- 內部的 box 會在垂直方向,一個接一個地放置。
- box 垂直方向的距離由 margin 決定。 屬於同一個 BFC 的兩個相鄰 Box 的 margin 會發生重疊。
- 每個元素的 margin box 的左邊, 與包含 block border box 的左邊相接觸(對於從左往右的格式化,否則相反),即使存在浮動也是如此。
- BFC 的區域不會與 float box 重疊。
- BFC 就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素;反之也如此。
- 計算 BFC 的高度時,浮動元素也參與計算。
主要作用
- 自適應兩欄佈局
- 可以阻止元素被浮動元素覆蓋
- 可以包含浮動元素(清除內部浮動)
- 分屬於不同的 BFC 時可以阻止 margin 重疊
26 th
工具
個人筆記連結
可以透過 JSON 格式,快速產生 DEMO 用的 API。
28 th
Vite deploy
- GitHub Pages
- 在
vite.config.js內部設定base名稱(通常為'/<REPO>/')
export default defineConfig({
base: '/<REPO>/',
plugins: [...]
})- 在專案目錄內新建檔案
deploy.sh並貼上以下內容
#!/usr/bin/env sh
# delete dist folder
rm -rf dist
# abort on errors
set -e
# build
pnpm run build
# navigate into the build output directory
cd dist
# place .nojekyll to bypass Jekyll processing
echo > .nojekyll
git init
git checkout -B main
git add -A
git commit -m 'deploy'
git push -f https://github.com/<USERNAME>/<REPO>.git master:gh-pages
cd -- 執行
deploy.sh檔案
sh deploy.sh將會建出新的
dist目錄並將專案內容 build 完放進dist中。
再將dist目錄內容push到 GitHub 專案上的gh-pages分支上。
JS
new URL(url [, base])url
是一個表示絕對或相對 URL 的DOMString。
如果url是相對 URL,則會將base用作基準 URL。
如果url是絕對 URL,則無論參數base是否存在,都將被忽略。base
是一個表示基準 URL 的DOMString,在url是相對 URL 時才會有效果。
如果未指定,則默認為''。
const url = new URL('https://exp.com/js/2#tag=es6')| 屬性 | 內容名稱 | 範例 |
|---|---|---|
url.href | 完整網址(URL) | "https://exp.com/js/2#tag=es6" |
url.hash | 網址中的 Hash 部分 | "#tag=es6" |
url.host | 網址中的主機名稱 | "exp.com" |
url.pathname | 網頁路徑部分 | "/js/2" |
url.protocol | 網址中的通訊協定部分 | "https:" |
- 取得網頁參數部分
const url = new URL('https://exp.com?tag=es6&page=2&tag=url')
const params = url.search // "tag=es6&page=2&tag=url"
const params = url.searchParams // URLSearchParams {}
params.has('page') // true
params.get('tag') // es630 th
JS
async,deferattributes
<script>
<p>...content before script...</p>
<script src="demo.js"></script>
<!-- 當 JS 還沒下載與解析完前,HTML 的繪製會卡在這,因此需等到 script 載入完後,才會看到下面的內容 -->
<p>...content after script...</p><script defer>
<script src="demo1.js" defer></script>
<script src="demo2.js" defer></script>網頁繪製不會停下,
demo.js在背景下載,不會阻塞頁面的繪製,並且會等到 DOM 準備好後(但DOMContentLoaded事件發生前)才加以執行。
因此相當實用,且目前瀏覽器多已經支援。
和傳統只使用<script>的方式一樣,使用defer能夠保證scripts的檔案會按照 document 中的順序執行。
以上面的程式碼為例,demo1.js和demo2.js會同時才背景開始被下載,但即使demo2.js比較早下載完成,瀏覽器仍會確保demo1.js執行完後才執行demo2.js。
TIP
defer 適合用在需要等待 DOM 完成後才能被執行的 JS,後者多個 JS 檔彼此之間有相依性的情況。
<script async>
<script src="demo1.js" async></script>
<script src="demo2.js" async></script>和
defer類似的是demo1.js和demo2.js都會在背景下載,但不同的地方在於,async會在該 JS 檔下載完成後,就會馬上被執行。
它不會等待DOMready 後才執行,也不保證各script間執行的順序,也就是說,如果demo2.js比demo1.js還快被下載完成的話,它就會先被執行。
因此,async適合用在每個script的 JS 檔彼此之間沒有相依性,不需要誰先執行才能換另一個執行的這種情況(例如,Google Analytics)。
TIP
async 適合用在各 script 間的 JS 檔沒有相依的情況下使用,例如 Ads、GA 等等。
瀏覽器私有屬性
-moz-:代表 firefox 瀏覽器私有屬性-ms-:代表 IE 瀏覽器私有屬性-webkit-:代表 chrome、safari 私有屬性-o-:代表 opera 私有屬性
資源
- Can I Use
可以用來查詢 HTML、CSS 的瀏覽器兼容度。
