<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Kelly CHI on Medium]]></title>
        <description><![CDATA[Stories by Kelly CHI on Medium]]></description>
        <link>https://medium.com/@Kelly_CHI?source=rss-f907fafd4899------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*P5GaZ1W7XGsBT96RwE1ZmQ.jpeg</url>
            <title>Stories by Kelly CHI on Medium</title>
            <link>https://medium.com/@Kelly_CHI?source=rss-f907fafd4899------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 07 May 2026 07:54:47 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@Kelly_CHI/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[電腦科學基本功對於前端來說重要嗎？一個菜鳥前端的思考]]></title>
            <link>https://medium.com/@Kelly_CHI/computer-science-for-frontend-developers-2addb977e92f?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/2addb977e92f</guid>
            <category><![CDATA[learning]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[addy-osmani]]></category>
            <category><![CDATA[computer-science]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Sat, 29 Jun 2024 10:28:54 GMT</pubDate>
            <atom:updated>2024-06-29T10:28:54.677Z</atom:updated>
            <content:encoded><![CDATA[<h4>從「宏觀」與「微觀」技能來理解學習基本功帶來的好處</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*X7STyLdZt-8zlzlZ" /><figcaption>Photo by <a href="https://unsplash.com/@emilep?utm_source=medium&amp;utm_medium=referral">Emile Perron</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>前言</h3><p>相較於其他工程師類型，前端開發相對容易入門。然而，這正是它的挑戰所在：入門容易，精通難。</p><p>在累積了一定的工作經驗後，會發現日常使用的技能會逐漸固定。除非遇到比較複雜的需求，或者在組織內層級提升 (例如需要帶領團隊)，否則在專案的技術、時程限制下，往往會選擇方便、快速的工具來完成任務。若沒有在工作之餘投入精力，便難以深入探索底層原理。隨著年資的累積，實力未能同步提升，<strong>可能就會陷入所謂的「十年經歷等於重複了十年的一年經歷」的窘境。</strong></p><p>儘管初期可能是抱著試試看的心態進入這個領域，但隨著時間的推移，還是有必要花時間補足基本功，否則在成為更資深角色的時候被新人看破手腳就慘了 (笑。</p><h3>Software Engineering: The Soft Parts</h3><p>會想要寫這篇文章的一部分原因，是因為最近讀了由 Google 資深工程師 Addy Osmani 所撰寫的<a href="https://addyosmani.com/blog/software-engineering-soft-parts/">《Software Engineering — The Soft Parts》</a>。(順帶一題，這本書免費！)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/475/1*jNrtUmERJPE5SVsRPAWg-g.png" /><figcaption>Software Engineering: The Soft Parts by Addy Osmani</figcaption></figure><p>該書大致分為幾個章節：學習新知、技術複雜性、溝通、資深度 (seniority)、有效的團隊和指導 (mentoring)。書中的後半部分主要是從資深成員的角度探討技術團隊管理的相關議題，這部分對我來說尚未產生強烈共鳴，因此就暫且先不討論。</p><p>然而，第一部分討論學習新知的內容對我來說相當有感，一部分是因為學習新知在工程師領域可以說是不可或缺的日常 (宿命?)，另一部分是因為這不僅適用於成為工程師之前，也適用於成為工程師之後的各個階段。在這個章節中，Addy Osmani 提到一些在我們面對日常任務時所思考的問題：</p><ul><li>我們如何知道我們解決的是正確的問題？</li><li>我們如何將關鍵問題拆解成更小的問題，以便進一步分析？</li><li>一但有了假設，我們如何安排工作來檢驗他們？</li><li>如果有時間壓力，我們可以採取哪些捷徑，而不犧牲嚴謹性？</li><li>如何知道我們已經「完成」了？一個解方怎樣才「夠好」？</li></ul><p>這些問題都沒有標準答案，但是要答的好，往往需要深厚的知識和經驗，對 Addy Osmani 來說，基本功的鑽研，是可以幫助我們分析這些問題的。</p><h3>學習基本功帶來的好處</h3><p>回到標題，電腦科學基本功對於前端工程師來說重要嗎？答案，是肯定的。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2i79ymdx0JoyfxJm" /><figcaption>Photo by <a href="https://unsplash.com/@nublson?utm_source=medium&amp;utm_medium=referral">Nubelson Fernandes</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h4>宏觀與微觀技能</h4><p>在 Addy Osmani 書中，他引用了 <a href="https://skorks.com/2010/04/on-the-value-of-fundamentals-in-software-development/">On The Value Of Fundamentals In Software Development</a> 這篇文章中提到的一個概念，叫做宏觀與微觀技能 (macro &amp; micro skills)。<strong>所謂宏觀的技能，指的是軟體工程的核心技能，例如資料結構、演算法、效能優化、軟體架構等等；而微觀的技能指的是這些宏觀技能的「實作」，例如不同的程式語言、前端框架、開發工具、使用平台等等</strong>。</p><p>對於初階開發者，學習微觀技能可以讓我們快速上手日常工作，但是當技術變遷、環境轉換時，對宏觀技能的掌握可以讓我們減少重新學習的陣痛期，並且在職涯中走的更久更遠，因為<strong>這些宏觀的技能是「能帶著走的 (transferable)」</strong>。</p><p>以前端為例，雖然三大框架各有各的語法架構，但它們共享了一些核心的概念：元件式架構 (component-based architecture)、響應式 (reactivity)、狀態管理 (state management)、生命週期 (life cycle) 等等。這就是為甚麼有人說，學會了一個框架以後，要學習新的框架就沒那麼困難了，因為很多的知識是共通的。</p><p>在了解「宏觀與微觀技能」的概念以後，就可以了解為何學習基本功可以為前端開發者帶來很多好處：</p><ul><li><strong>提升學習新技能的效率</strong>：工程師領域的環境和技術日新月異，從既有技能中提煉出宏觀部分，在平行轉換到另外一個具有類似功能的技術的時候，可以快速從宏觀部分切入，進一步掌握住微觀的細節。</li><li><strong>更了解你使用的工具</strong>：古語有云：工欲善其事，必先利其器。身為工程師，我們每天使用大量工具，但往往只停留在使用層次。如果能進一步了解工具背後的原理和脈絡，在面對問題時，可以更好地發揮工具潛能，更快速地解決問題。</li><li><strong>從容面對面試難題</strong>：在<a href="https://skorks.com/2010/04/on-the-value-of-fundamentals-in-software-development/">文章</a>中，作者提到一個面試的例子，他被問到<a href="https://zh.wikipedia.org/wiki/%E4%B9%90%E8%A7%82%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6">樂觀並行控制</a>概念在 <a href="https://hibernate.org/">Hibernate</a> 中的實作方式，由於對 Hibernate 不熟悉，他當場腦袋空白。事後回想，其實這個概念並不專屬於 Hibernate，如果他可以從更宏觀的角度來回答，也不至於交了個白卷。</li><li><strong>避免 FOMO 與資訊焦慮</strong>：在前端領域，FOMO (fear of missing out) 常使人覺得一天不追新技術，明天就會落伍了。然而，技術層出不窮，永遠追不完。如果能以更宏觀的視角看待新技術，會發現很多新技術只是「換湯不換藥」。</li><li><strong>不要被「前端」給侷限</strong>：雖然前端工程師常被嘲諷是在工程師鄙視鏈的最底層 (QQ，但不應因此侷限自己。許多前端工具的開發者，都是基本功紮實的一流軟體工程師，但他們選擇從從前端出發來解決各式各樣的工程議題。</li></ul><h3>從哪裡開始學習基本功</h3><p>身為菜鳥轉職仔，面對資工本科四年甚至是六、七年的深厚學習，在一時半刻之內是絕對學不完所有的東西的，更何況還要同時兼顧工作、家庭、健康、娛樂等其他人生的重要面向。因此，想要一次一網打盡的策略是行不通的 (當然，如果你喜歡的話也沒有不可以)，以下是幾個比較容易執行的方向：</p><ul><li><strong>了解日常使用的工具</strong>：從平常使用的 JavaScript，到框架 React、Vue 甚至一些常用的套件，深入掌握語言的特性、框架的原理和特色、工具的脈絡與原理，並延伸至更宏觀的議題，不管在日常工作或是求職面試時都會有很大的幫助。</li><li><strong>擴展常見的面試問題</strong>：以前端開發來說，在面試時很常會遇到網絡知識相關問題，像是 HTTP、CORS、CDN 等，我們可以從網路知識出發來充實基本功，學習起來也不會覺得太過陌生。</li><li><strong>知名的資工基礎課程</strong>：在 youtube 或是其他平台上都可以找到國際名校所開辦的資工基礎課程，最有名的莫過於哈佛大學的 <a href="https://pll.harvard.edu/course/cs50-introduction-computer-science">CS50</a>。如果不知道從何下手，這些入門課程會是很好的起點。</li><li><strong>參與線上線下讀書會</strong>：有自學經驗的人大概都知道，除非有強大的自制力，否則單打獨鬥很容易就會怠惰了。共同學習可以設定明確進度，若有導讀機制的話也能訓練自己消化並傳達資訊的能力。</li></ul><h3>結語</h3><p>根據觀察，身邊厲害的資深前端前輩總能以宏觀且清晰的角度看待前端開發中的大小事。他們不會將前端開發局限於簡單的切切版和接接 API，而是將自己視為對 UI 工程更感興趣的軟體工程師。</p><p>與這些前輩交流時，可以從前端的話題開始，逐漸延伸到瀏覽器引擎、程式語言特性、套件底層的資料結構設計等深層次的技術問題，就會覺得哇，好令人佩服啊，同時也意識到自己的不足。</p><p>此外，近期前端開發的發展趨勢也越來越往 server 端靠攏，前後端分離的架構思維正逐步被打破。若將視野僅局限於前端，將難以跟上這種發展方向。</p><p>當然，除了強化基本功外，提升軟實力也同樣重要。正如 Addy Osmani 書中所述，溝通、協作能力以及向上、向下管理的能力也是不可或缺的。總之，在軟、硬實力之間找到甜蜜點、最合適自己的平衡，也是在這個領域的長遠修練啊。</p><h4>推薦閱讀</h4><ul><li><a href="https://frontendatscale.com/issues/23/">Computer Science for Frontend Developers — Frontend At Scale</a>：文中討論了「前端工程師是否該學習資料結構演算法？」這個議題，並提供了學習的路徑和參考資源。</li><li><a href="https://blog.ploeh.dk/2024/05/20/fundamentals/">Fundamentals — Mark Seemann</a>：資深工程師談論對他來說哪些議題是所謂的「基本功」，以及為什麼要學習這些。</li><li><a href="https://skorks.com/2010/04/on-the-value-of-fundamentals-in-software-development/">On The Value Of Fundamentals In Software Development — Alan Skorkin</a>：前面有提到過的文章，2010 年撰寫，其中關於 macro 和 micro skills 的討論放在如今一樣適用。</li><li><a href="https://www.jing-tech.me/writing/experiences/2024_frontend_learning/">2024 前端工程師學習指南 — Jing Tech</a>：相當齊全的前端工程師學習資源，文中也提供了非常多線上 CS 基礎課程的介紹。</li><li><a href="https://gaia.cs.umass.edu/kurose_ross/online_lectures.htm">Computer Networking: A Top-Down Approach — Jim Kurose, Keith Ross</a>：從 APP 層開始的網路概論課程，課程影片、Lab 都能免費觀看。之前跟朋友組網路概論讀書會就是讀這本，教授的講解非常簡潔易懂，超推薦！</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2addb977e92f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[無障礙網頁開發：表單基礎概念與實作，以 React 為例]]></title>
            <link>https://medium.com/@Kelly_CHI/accessible-form-in-react-4cb277aa9db2?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/4cb277aa9db2</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[accessibility]]></category>
            <category><![CDATA[forms]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Tue, 04 Jun 2024 09:15:53 GMT</pubDate>
            <atom:updated>2024-08-24T09:48:45.626Z</atom:updated>
            <content:encoded><![CDATA[<h4>從語意結構、鍵盤操作與表單驗證三大面向，理解無障礙開發基礎</h4><h3>前言：為何要開發無障礙表單？</h3><ul><li><strong>表單是前端互動關鍵的一環</strong>：在現代網頁中，表單可說是無處不在，從登入、註冊，到進行購物付款，表單都是使用者與網站互動的主要方式之一。這就表示，表單的可用性會直接影響到使用者的體驗和滿意度。對於網頁的搜尋排名 (SEO)，無障礙也是關鍵指標之一。</li><li><strong>無障礙是為了所有人</strong>：我們常會先入為主的認為，無障礙設計只是為了少數有障礙的人，但其實在人生中我們多少有陷入不方便的時刻，例如受傷骨折手不能動、接受手術後短暫失去視力等等。此外，一些無障礙設計，例如顏色對比度、字體大小，也可以讓一般使用者受益。因此，無障礙絕對不僅僅是針對「有障礙的人」。</li></ul><h3>無障礙表單基礎概念</h3><p>在前端應用程式中，表單互動可以很簡單也可以很複雜，從最基本的聯絡表單，到包含多種欄位的多頁式表單，單靠一篇文章的篇幅可是說不完的。但我們可以從以下三個面向來探討一個具有好的可用性的表單該具備哪些條件：</p><ul><li><strong>語意結構、標籤與說明</strong>：<a href="https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantics_in_html">語意化 HTML</a> 是最基礎也最能快速提升無障礙體驗的方式。在表單中我們可以透過不同元素的屬性以及 <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA">ARIA 標籤</a>去正確關聯欄位與說明。</li><li><strong>鍵盤操作</strong>：對於以鍵盤操作為主的使用者，鍵盤就如同他們的「滑鼠」，因此，為表單元素提供正確且流暢的鍵盤操作，也是製作無障礙表單時不可忽略的一個步驟。</li><li><strong>表單驗證與錯誤訊息</strong>：填寫表單時，總無法避免出現一兩個錯誤，適當的驗證與訊息提醒，能讓使用者快速修正內容並完成填寫表單。因此，在實作表單時也要考慮到驗證與訊息是否能讓輔助科技正確接收。</li></ul><h3>語意結構、標籤與說明</h3><h4>語意與 Accessibility Tree</h4><p>首先，我們要先了解為何清晰的語意對網頁無障礙來說如此重要。</p><p>瀏覽器在載入網頁時，會根據 HTML 結構生成兩棵樹：DOM Tree 和 Accessibility Tree。而輔助科技主要依賴 Accessibility Tree 來理解網頁的結構和內容。如果網頁中使用了適當的語義化 HTML 元素，這些輔助科技就能夠準確地解讀並與網頁互動。例如，使用 &lt;button&gt; 標籤來表示按鈕，螢幕閱讀器會告訴使用者這是一個按鈕，並提供相應的操作選項。</p><figure><img alt="圖中示意了應用程式與輔助科技之間的關係，兩者中間透過可訪問 API ，進行事件、 Accessibility Tree 的溝通互動" src="https://cdn-images-1.medium.com/max/908/1*w2EY14paPlYopCGKcQW8PA.png" /><figcaption>圖中示意了應用程式與輔助科技之間的關係，兩者中間透過可訪問 API ，進行事件、 Accessibility Tree 的溝通互動</figcaption></figure><p>延伸閱讀：<a href="https://medium.com/a11yvillage/e2005a5d61ae">Accessibility Tree：細心的栽種打造無障礙頁面</a></p><p>當我們使用缺乏語意的元素來製作網頁，輔助科技就會不知道現在正在和什麼元素做互動。雖然現代前端框架（如 React、Vue.js）提供了很大的彈性，可以用自定義的方式來開發 UI 元件，但我們應該盡量使用原生的 HTML 元素來實現功能。當原生元素無法滿足需求時，我們才來思考使用 ARIA 標籤來補充語意，以確保自定義元件也能夠被輔助科技正確理解和使用。</p><h4>關於語意結構的重要實作要點</h4><ul><li><strong>使用 &lt;form&gt; 元素</strong>：會產生<a href="https://medium.com/p/eb9c1c1e66">地標</a>的語意，除了可以讓語意更加豐富以外，也可以允許瀏覽器用原生的操作方式送出表單資料。</li><li><strong>正確的關聯欄位標籤與欄位說明</strong>：</li></ul><ol><li>&lt;input&gt; 與 &lt;label&gt;: 使用 &lt;label&gt; 元素的 for 屬性，以及 &lt;input&gt; 上的 id 屬性來關聯欄位與欄位標籤，瀏覽器會使用 &lt;label&gt; 的內容作為欄位的可訪問名稱。</li><li>aria-labelledby: 若標籤文字已存在其他元素上，aria-labelledby 屬性可以將一個元素與另一個已存在的標籤元素關聯起來。</li></ol><pre>&lt;!-- 當搜尋輸入框旁邊已經有一個 &quot;Search&quot; 按鈕時，<br>使用 aria-labelledby 以按鈕文字作為欄位可訪問名稱 --&gt;<br>&lt;form&gt;<br>    &lt;input <br>       type=&quot;search&quot; <br>       name=&quot;search&quot; <br>       placeholder=&quot;Search&quot; <br>       aria-labelledby=&quot;search-button&quot; <br>    /&gt;<br>    &lt;button type=&quot;submit&quot; id=&quot;search-button&quot;&gt;<br>        Search<br>    &lt;/button&gt;<br>&lt;/form&gt;</pre><p>3. aria-describedby: 若欄位附近還有其他說明文字，aria-describedby 可以將元素與其他描述性內容關聯起來。</p><pre>&lt;!-- 欄位有額外的說明時，可以用 aria-describedby 關聯欄位與說明 --&gt;<br>&lt;form&gt;<br>  &lt;label for=&quot;password&quot;&gt;密碼：&lt;/label&gt;<br>  &lt;input <br>    type=&quot;password&quot; <br>    id=&quot;password&quot; <br>    name=&quot;password&quot; <br>    aria-describedby=&quot;password-help&quot; <br>  /&gt;<br>  &lt;span id=&quot;password-help&quot;&gt;<br>      密碼必須包含至少8個字符，其中至少有一個大寫字母和一個數字。<br>  &lt;/span&gt;<br>  &lt;!-- ... --&gt;<br>&lt;/form&gt;</pre><ul><li><strong>適當使用 &lt;fieldset&gt; 與 &lt;legend&gt;</strong>: 若輸入欄位為一群組時，例如核取方塊與單選按鈕 (radio)，可以用 &lt;fieldset&gt; 將輸入關聯起來，並用 &lt;legend&gt; 提供該群組說明。</li><li><strong>使用對應的 &lt;input&gt; 類型</strong>：在行動裝置上，會有對應的鍵盤出現，例如 type=”number” 會出現數字鍵盤，type=”date” 會出現日期選擇器。</li><li><strong>留意符號的意義是否有正確傳達</strong>：例如，表單中常使用星號 (*) 表示必填，但星號代表必填的意義未必能完整傳達給輔助科技使用者，我們可以在表單最前面加上一段敘述：<em>有星號(*)欄位表示必填</em>，並確保 &lt;input&gt; 元素有添加 required 或 aria-required 屬性。</li></ul><h4>❌常見錯誤：用 placeholder 取代欄位標籤</h4><p>在設計與開發表單時，一個常見的錯誤是用 placeholder 來取代欄位標籤。對明眼的使用者來說，這可能是個可行的做法，但從輔助科技的角度來看，即便一些輔助科技是可以報讀 placeholder 資訊的，但根據 <a href="https://www.w3.org/WAI/tutorials/forms/instructions/#placeholder-text">WCAG 官方建議</a>，placeholder 的支援度仍不完善，也不會被視為標籤，因此在實作上還是要以 &lt;label&gt; 為主。</p><p>此外，這個設計對一般使用者來說也有不方便的地方，因為在輸入的時候，placeholder 會消失，記性不好的使用者就不知道自己在輸入的是哪一個欄位了。</p><ul><li>解決方式1：正確連結欄位與標籤。可以使用 &lt;label&gt; 元素的 for 屬性，以及 &lt;input&gt; 上的 id 屬性來實現：</li></ul><pre>&lt;label for=&quot;username&quot;&gt;帳號：&lt;/label&gt;<br>&lt;input type=&quot;text&quot; id=&quot;username&quot; name=&quot;username&quot; placeholder=&quot;輸入您的帳號&quot; /&gt;<br><br>&lt;label for=&quot;email&quot;&gt;電子郵件：&lt;/label&gt;<br>&lt;input type=&quot;email&quot; id=&quot;email&quot; name=&quot;email&quot; placeholder=&quot;輸入您的電子郵件&quot; /&gt;</pre><ul><li>解決方式2：使用視覺上隱藏的標籤。在 Tailwind CSS 中，可以使用 “sr-only” 這個 utility class 來設定：</li></ul><pre>.sr-only {<br>    position: absolute;<br>    width: 1px;<br>    height: 1px;<br>    padding: 0;<br>    margin: -1px;<br>    overflow: hidden;<br>    clip: rect(0, 0, 0, 0);<br>    white-space: nowrap;<br>    border-width: 0;<br>}</pre><h4>⚠️提醒：使用 ARIA 來讓語意更加豐富，但要小心使用</h4><p>當原生的元素不足以提供足夠的語意時，使用 ARIA（Accessible Rich Internet Applications）標籤可以用來為輔助科技提供更多的訊息。但在使用 ARIA 屬性時要小心使用，因為<strong>過度使用是可能造成反效果的</strong>，記得這句話：<a href="https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/">No ARIA is better than Bad ARIA</a>！</p><p>延伸閱讀：<a href="https://medium.com/a11yvillage/8d92fded7a8">客製 Accessibility tree，從認識 ARIA 開始(上)</a></p><h3>鍵盤操作</h3><h4>WCAG Level A Success Criteria: Keyboard Accessible</h4><p>在 Web Content Accessibility Guidelines (WCAG) 所公布的 Level A 成功標準中，<a href="https://www.w3.org/WAI/WCAG21/Understanding/keyboard.html">2.1.1 Keyboard Accessible</a> 這一項標準要求所有功能都必須能夠使用鍵盤操作，而不必依賴滑鼠或其他設備。例如，某些使用拖放 (drag-and-drop) 操作的功能應該也要提供鍵盤的操作方式。</p><h4>確保每個表單元素都是可用鍵盤來操作的</h4><ul><li><strong>使用原生的 HTML 元素</strong>：例如 &lt;select&gt; 或原生的 radio input、date picker 等，都提供了完整的無障礙操作，因此，為了確保表單能夠使用鍵盤操作，我們應該優先使用原生元素，而非使用手刻的元件。</li><li><strong>使用受到肯定的元件庫</strong>：由於設計需求與開發效率等考量，在開發的時候我們經常會使用元件庫來實作。常見的元件庫通常都有不錯的無障礙支援，例如 <a href="https://mui.com/">MUI</a>、<a href="https://v2.chakra-ui.com/">Chakra UI</a> 等。若有客製化樣式的需求，也可以使用無樣式的 UI 庫，例如 <a href="https://headlessui.com/">Headless UI</a>、<a href="https://www.radix-ui.com/primitives">Radix UI</a>、<a href="https://react-spectrum.adobe.com/react-aria/">React Aria</a> 等。</li><li><strong>參考 APG Patterns 來實作</strong>：若遇到非不得已，一定要用手刻的方式來開發元件時，可以參考 ARIA Authoring Practices Guide (APG) 所提供的<a href="https://www.w3.org/WAI/ARIA/apg/patterns/">設計與開發模式指南</a>來設計與實作無障礙功能，避免誤用 ARIA 反而對無障礙造成了損害。</li></ul><figure><img alt="ARIA Authoring Practices Guide (APG) 的設計與開發模式指南，提供了多種常見元件的模式，來幫助設計師與開發者以正確的方式打造無障礙元件" src="https://cdn-images-1.medium.com/max/1024/1*verKa5xD_JfTVVxhhMJxTQ.png" /><figcaption>ARIA Authoring Practices Guide (APG) 的<a href="https://www.w3.org/WAI/ARIA/apg/patterns/">設計與開發模式指南</a>，提供了多種常見元件的模式，來幫助設計師與開發者以正確的方式打造無障礙元件</figcaption></figure><h4>設定清楚的焦點樣式</h4><p>對於低視能、肢障等必須依賴鍵盤操作的使用者來說，網頁中的元素具有清晰的焦點樣式是非常重要的。在表單中更是如此，使用者必須清楚知道現在正在和哪個元素做互動。因此，最重要也最關鍵的一點，是「<strong>不要關閉瀏覽器預設的焦點樣式！</strong>」</p><pre>* {<br> outline: none; /* 這樣非常不好! */<br>}</pre><p>如果在設計上並沒有針對每種元素客製化特殊的焦點樣式，可以使用<strong>雙層的黑白焦點樣式</strong>，確保焦點在深/淺色背景中都能被看見。</p><pre>:focus-visible {<br> outline: 9px double black;<br> box-shadow: 0 0 0 6px white;<br>}</pre><p>延伸閱讀：<a href="https://medium.com/@a11yvillage/de9d8b9481fe">焦點的無障礙 — 焦點可見與樣式篇</a></p><h3>表單驗證與錯誤訊息</h3><p>在開發表單時，除了讓使用者可以順利的填寫之外，在送出表單後，讓使用者知道有錯誤發生了，以及該如何修正也是表單操作體驗很重要的一環。</p><h4>正確提示與關聯錯誤訊息</h4><ul><li>aria-invalid：當欄位有錯誤時，通常我們會使用視覺上的樣式改變來傳達該欄位有誤，不過，這個方法未必能很好的傳遞給輔助科技的使用者。因此，使用 aria-invalid 可以多補充一些語意，例如，螢幕閱讀器會報讀「無效的輸入」。</li></ul><pre>&lt;label for=&quot;email&quot;&gt;電子信箱：&lt;/label&gt;<br>&lt;input type=&quot;text&quot; id=&quot;email&quot; aria-invalid=&quot;true&quot;&gt;</pre><ul><li>aria-describedby：對明眼人來說，在欄位附近顯示錯誤訊息可能很直覺，但是對於輔助科技來說，我們必須關聯此描述與欄位，才能將訊息正確傳遞給使用者。aria-describedby 屬性可以將一個欄位與一個或多個描述性元素關聯起來，提供更多關於錯誤的訊息。</li></ul><pre>&lt;label for=&quot;username&quot;&gt;帳號：&lt;/label&gt;<br>&lt;input type=&quot;text&quot; id=&quot;username&quot; aria-invalid=&quot;true&quot; aria-describedby=&quot;usernameHint usernameError&quot; /&gt;<br>&lt;span id=&quot;usernameError&quot;&gt;帳號已有人使用。&lt;/span&gt;<br>&lt;span id=&quot;usernameHint&quot;&gt;帳號需小於 20 字元。&lt;/span&gt;</pre><h4>Focus 到第一個錯誤的欄位</h4><p>當我們送出表單後，若驗證失敗，通常會使用醒目顏色和錯誤訊息來提示使用者，但是對於螢幕閱讀器使用者來說，若缺乏適當的回應，他們會無法知道現在表單中哪些欄位有誤。常見的一個方式是是用焦點控制 (focus control) 來告知使用者發生錯誤的欄位，在表單送出後，我們可以使用 element.focus() 方法將焦點移至錯誤的欄位上。</p><p>這樣做的好處是，<strong>使用者可以馬上對錯誤的欄位進行修正</strong>，而不用穿梭在各個欄位中找到有錯的那一個。</p><p>延伸閱讀：<a href="https://medium.com/a11yvillage/62404f74fb59">焦點無障礙 — 管理焦點的行為與轉移</a></p><h4>使用 ARIA Live Regions 來通知使用者</h4><p>除了焦點控制，我們也可以使用 <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions">ARIA Live Regions</a> 來通知使用者有錯誤發生。ARIA Live Regions 允許開發者向輔助科技的使用者提供即時訊息，使用的情境包括即時聊天、表單驗證、購物車等等。我們只要在元素上使用 ARIA 標籤中的 aria-live，就能標示某個區域為 Live Regions。</p><p>很多表單會統一在表單最上方列出哪些欄位有誤，我們可以將這個元素變成一個 Live Region，確保螢幕閱讀器使用者可以接收到這些訊息。</p><pre>&lt;div aria-live=&quot;polite&quot; id=&quot;form-status&quot;&gt;註冊失敗，無效的信箱和密碼。&lt;/div&gt;<br>&lt;form&gt;<br>&lt;!-- ... --&gt;<br>&lt;/form&gt;</pre><p>不過，<strong>當錯誤的欄位較多時，一次說明哪些欄位錯誤對使用者來說反而並不方便，報讀過後也忘記有哪些欄位需要修改了</strong>。 因此，我們可以改用輸入後及時驗證，或是僅用焦點控制加上適當的訊息關聯，這樣就可以大幅改善無障礙體驗了。</p><p>延伸閱讀：<a href="https://medium.com/a11yvillage/8994c375bc1e">使用 ARIA Live Regions 讓重要資訊不漏接 (上)</a></p><h4>❌常見錯誤：在未完成填寫時禁用送出按鈕</h4><p>有時設計師或開發者會在表單未完成填寫時禁用提交按鈕，這樣的設計原本用意在於避免使用者在還沒有正確填寫完畢的時候提交表單，但是這會產生幾個問題：</p><ol><li>Disabled 狀態無法有效說明發生什麼問題，使用者必須自行猜測禁用的原因。</li><li>Disabled 狀態會導致使用者無法與按鈕互動來得到一些回饋。更好的做法是<strong>允許提交，但在提交時進行驗證</strong>，並告知使用者錯誤。</li></ol><p>延伸閱讀：<a href="https://medium.com/a11yvillage/cab8b18917f6">表單錯誤訊息設計❶：如何設計能讓更多人容易理解？</a></p><h3>測試方法</h3><p>在開發完無障礙功能後，進行測試也是很重要的步驟，這邊說明一些簡單有效的測試方式：</p><h4>基本測試方法：</h4><ul><li><strong>鍵盤導航與焦點樣式</strong>：我們可以使用 Tab 鍵逐一與表單元素互動，確保每個元素能夠被聚焦、焦點順序邏輯正確，也都能正常使用。另外也要確認每個表單元素獲得焦點時應該有明顯的焦點樣式。</li><li><strong>觀察 Accessibility Tree</strong>：透過瀏覽器 devtools 中的 Accessibility Tree 和相關的面板，我們可以確認每個表單元素的語意有沒有正確顯示與關聯，例如標籤（label）、描述（description）、各種 ARIA 屬性等等（如 aria-invalid）。</li><li><strong>瀏覽器插件</strong>：使用像 <a href="https://chromewebstore.google.com/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk">Lighthouse</a> 或 <a href="https://chromewebstore.google.com/detail/wave-evaluation-tool/jbbplnpkjmmeebjpijfedlgcdilocofh">WAVE </a>這類插件，掃描頁面並檢查無障礙問題。這些工具可以幫我們檢查標籤、描述、ARIA 屬性是否正確實現，還可以查看顏色對比、焦點順序、網站語意結構等。</li></ul><figure><img alt="使用像 Lighthouse 或 WAVE 這類插件，可以幫我們檢查顏色對比、焦點順序、網站語意結構等是否正確" src="https://cdn-images-1.medium.com/max/1024/1*4l6pn9IbbfLBZGN35Ightg.png" /><figcaption>使用 WAVE 瀏覽器插件檢查網頁語意結構、焦點順序、顏色對比等無障礙問題</figcaption></figure><h4>進階測試：使用螢幕閱讀器</h4><p>雖然透過以上提到的基本測試方式，已經能揪出大部分的無障礙錯誤，但是像是<strong>焦點管理不當、描述性訊息缺乏或錯誤的語意標籤</strong>等等問題，就必須透過螢幕閱讀器才能發現。因此，如果要更貼近使用者真實的體驗，建議開發者親自使用螢幕閱讀器測試，才能發現一般檢查中可能忽略的問題。</p><p>對於 Windows 使用者，可以使用 NVDA 或 JAWS 來做測試，對於 Mac 使用者，可以使用 VoiceOver。在行動裝置上則可以使用 TalkBack（Android）或 VoiceOver（iOS）來測試。</p><p>延伸閱讀：<a href="https://medium.com/a11yvillage/afa465e8829c">螢幕閱讀器檢測無障礙，自己來！(一)</a>、<a href="https://medium.com/a11yvillage/b8d521c5a2ed">活用手機上的螢幕閱讀器(一)</a></p><h3><a href="https://accessible-form-react.netlify.app/">React 範例</a></h3><figure><img alt="無障礙表單 React 實作範例，使用 Frontend Mentor 網站所提供之設計稿" src="https://cdn-images-1.medium.com/max/1024/1*X8EoKpdFYYB3AKEQImHo7w.png" /><figcaption>無障礙表單 React 實作範例，使用 Frontend Mentor 網站所提供之設計稿</figcaption></figure><p>在 Frontend Mentor 網站上的<a href="https://www.frontendmentor.io/challenges/contact-form--G-hYlqKJj">這個練習</a>非常適合實作基礎無障礙表單，因此本篇文章的範例就決定使用此設計稿。有興趣的朋友不妨也到網站下載設計稿並親自實作看看。</p><p>建議可以先到 👉<a href="https://accessible-form-react.netlify.app/">Live Demo</a>👈實際使用鍵盤、螢幕閱讀器操作看看，觀察 Devtools 中無障礙面板中的資訊。接著，再到👉<a href="https://github.com/KellyCHI22/accessible-form-react">Github Repo</a>👈中查看原始碼，以下幾個問題提供大家思考看看：</p><ol><li>Markup 中使用了哪些語意化 HTML 元素？螢幕閱讀器如何報讀這些元素？</li><li>Markup 中使用了哪些 ARIA 標籤？他們有哪些功能？呈現出來的效果是什麼？</li><li>表單中的元素是否都能使用鍵盤來操作？(Tab, Shift+Tab, Space, Enter, Arrow Keys…)</li><li>表單中的元素獲得焦點時，是否都有清晰可見的焦點樣式？</li><li>錯誤發生時，哪些欄位有誤、以及欄位的錯誤訊息是否有正確傳遞？這是如何做到的？</li><li>成功送出表單後，成功訊息是否有正確傳遞？這是如何做到的？</li></ol><p>除了使用語意化 HTML 標籤以外，此範例還搭配了 <a href="https://react-hook-form.com/">react-hook-form</a>、<a href="https://zod.dev/">zod</a> 這兩個常見的套件來處理表單驗證，其中 react-hook-form 提供了驗證後將焦點移至錯誤欄位與即時驗證的功能，而 zod 則是簡化了 schema 與錯誤訊息設定的流程。</p><h3>結語：我的網站符合無障礙標章的規定，這樣就夠了嗎？</h3><p>在初學網頁開發的時候，課程中多少都會帶到一些無障礙基本概念，像是使用正確的 HTML 元素、&lt;img&gt; 要記得加上 alt 替代文字等，但是當了解越來越多無障礙知識、並實際在專案中實作後，就更深刻感受到無障礙不僅僅只是在一系列的標準和規定清單中打勾而已。</p><p>前面也有提到，很多 WCAG 中無障礙的重要指標：鍵盤操作、語意標籤完整性等是較難從單純的自動化測試中發現問題的，即便網站在 Google Lighthouse 的 Accessibility 指標是滿分，並不代表網站的無障礙體驗是沒有問題的。這就是為什麼無障礙標章審核除了機器自動審核以外，都還需要人工檢核的原因。</p><p>你可能會納悶，無障礙這麼多眉角、這麼麻煩，身為一個平常已經很多鳥事的開發者，到底該怎樣做才對？其實，無障礙本來就不只是開發者單方面的責任，從設計、測試甚至到管理端，整體流程的討論與建立才能為使用者與團隊帶來最大的效益。</p><p>在這篇與<a href="https://medium.com/a11yvillage/2128300bec92">產品設計師 Oly</a> 的訪談中提到，<strong>無障礙不只是技術的挑戰，更牽涉了整個公司組織文化的轉變</strong>；如果現實條件並不允許，可以從個人角度出發，像<a href="https://medium.com/a11yvillage/148ffa61c923">工程師 Jamie</a> 一樣參與無障礙 side project、在公司內部做推廣等，也能為數位無障礙貢獻一份心力。正如<a href="https://medium.com/a11yvillage/05b6e434ef2d">科技教育總監 Sally</a> 所強調的，<strong>無障礙不需要一開始就做到完美，只要開始著手執行，哪怕只是一點改善，都是向前邁進的一步。</strong></p><h4>參考資源</h4><ul><li><a href="https://www.youtube.com/watch?v=gxwJCF8dqh8">Kateryna Porshnieva — Building Accessible Forms in React</a></li><li><a href="https://www.w3.org/WAI/tutorials/forms/">WCAG Forms Tutorial</a></li><li><a href="https://www.boia.org/blog/is-placeholder-text-essential-for-form-accessibility">Is Placeholder Text Essential for Form Accessibility?</a></li></ul><h4>寫在後面</h4><p>最後的最後，也要感謝 Coseeing 團隊的發起人，Woody，讓我在學習與實踐無障礙的路上能有正確的指引，還能透過共同研究與撰寫文章的過程，拓展關於無障礙的知識和想像。這篇文章有點像是加入以來的學習心得，綜合了很多目前研究過的、開發方面的知識點。另外，聽說 Coseeing 正在招募新一波開發志工，看到這邊的你/妳，也歡迎一起加入無障礙的探索行列！</p><p>👉 <a href="https://docs.google.com/forms/d/e/1FAIpQLSfVqHCSYW2AEG0IJAKn9qbna7eKLjo3Kcci8ypaa0MXvfiDeg/viewform">招募連結</a> (2024 招募已截止囉~)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4cb277aa9db2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[打造高分作品集網站超簡單：Astro 框架基礎介紹]]></title>
            <link>https://medium.com/@Kelly_CHI/astrojs-new-javascript-framework-for-content-sites-1a802b6638f5?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/1a802b6638f5</guid>
            <category><![CDATA[blog]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[astrojs]]></category>
            <category><![CDATA[front-end-development]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Sun, 14 Jan 2024 15:10:00 GMT</pubDate>
            <atom:updated>2024-01-16T19:18:17.190Z</atom:updated>
            <content:encoded><![CDATA[<h4>想要開發作品集或部落格等靜態網站？來試試以內容為中心、SEO 友善且高效能的超人氣新框架 Astro 吧</h4><figure><img alt="Start building with Astro today" src="https://cdn-images-1.medium.com/max/1024/0*HdVn00gFCoIoeOvJ.png" /></figure><h4>目錄</h4><p>· <a href="#a56e">什麼是 Astro？</a><br>· <a href="#41d7">Island Architecture 島嶼架構</a><br>· <a href="#25ee">View Transition API</a><br>· <a href="#c7bc">開始開發吧！</a><br>· <a href="#69ea">結語</a></p><h3>前言</h3><p>在競爭激烈的 JavaScript 生態系中，各式各樣的框架如雨後春筍般不斷冒出，React、Vue 等「經典」框架已經不夠看了，更現代化的框架如 Svelte、Solid、Qwik 等等也受到越來越多開發者的青睞。其中，一個相當值得關注的框架就是我們今天要談的 <a href="https://astro.build/">Astro</a>。從 NPM 的下載紀錄可以看到，Astro 近年可說是獲得了爆炸性的成長，它的高效能和友善的開發者體驗，讓它在前後端開發社群中備受矚目。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*TyEecvHp2Dpii1cL.png" /><figcaption>Astro 推出後的兩年內，npm 下載次數持續成長</figcaption></figure><p>我之所以會接觸到 Astro 這個框架，也是因為看到開發者社群的討論以及 Youtube 上的大神推薦，並且也剛好也有製作作品集網站的需求，就趁著這個機會來好好的認識一下這個新框架！</p><figure><img alt="Snowpack、Astro 開發者 Fred K. Schott" src="https://cdn-images-1.medium.com/max/877/0*9ZqOlsinQTkQsVj4.png" /><figcaption>Snowpack、Astro 開發者 Fred K. Schott</figcaption></figure><h3>什麼是 Astro？</h3><h4>以內容為中心</h4><p>根據官方文件，<strong>Astro 將自己定位成一個旨在建立高效能、「以內容為中心 (content-focused)」的 JavaScript 框架</strong>。所謂「以內容為中心」的網頁，指的是像是部落格、行銷網站、接案公司形象網，或是電子商務平台等這種以內容展示為主、互動性較低的網頁。針對這些網頁，Astro 提供了許多常見功能的支援，例如多語系網站（i18n）、網站地圖、內容管理系統（CMS）和 Markdown/MDX 語法的原生支援。</p><figure><img alt="所謂「以內容為中心」的網頁，指的是像是部落格、行銷網站、接案公司形象網，或是電子商務平台等這種以內容展示為主、互動性較低的網頁" src="https://cdn-images-1.medium.com/max/960/0*odNfSQtcEDPFnrKY.png" /></figure><h4>0 JavaScript by Default</h4><p>在效能方面，Astro 將所謂的「<strong>島嶼架構 (Island Architecture)</strong>」發揚光大，並預設不會載入任何的 JavaScript，讓使用者可以在網頁載入後立即與網頁互動，而不用去經歷「Uncanny Valley」這個過程 (意即雖然網頁看起來是準備好的，但實際上卻無法與之互動)。也因為不需要載入任何 JavaScript，Astro 與其他 SSR 框架相比之下，效能表現更突出。有興趣進一步閱讀的人可以參考這篇官方文章：<a href="https://astro.build/blog/2023-web-framework-performance-report/">2023 Web Framework Performance Report</a>。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*FwGH2VpI1SWHHPS2.png" /><figcaption>Astro 可以帶來超級高的 Performance</figcaption></figure><h4>用任何你喜歡的框架</h4><p>Astro 另外一個很大的賣點是，它是 「<strong>框架不可知 (framework agnostic)</strong>」 的。不像用 Next.js 需要用 React，用 Nuxt.js 就要用 Vue，Astro 並沒有和任何框架綁定，我們可以依照喜好和需求自由地使用任何前端框架，或是乾脆不要使用任何的框架。這讓原本並非前端專業的開發者，或是正在學習開發的新手可以享受它帶來的好處，卻減少學習新前端框架的知識負擔。</p><figure><img alt="使用插件可以輕鬆將其他前端框架加入到 Astro 專案中" src="https://cdn-images-1.medium.com/max/960/0*Hzk9sQ4nL_mEES4X.png" /><figcaption>使用插件可以輕鬆將其他前端框架加入到 Astro 專案中</figcaption></figure><h3>Island Architecture 島嶼架構</h3><p>這邊要稍微介紹一下 Astro 的主要特色之一，「島嶼架構」。</p><p>「島嶼架構」其實並非 Astro 創造出來的概念，早在幾年前就已經有相關的討論和框架實現。之所以會被稱為「島嶼」，是因為<strong>我們可以把網頁中各個元件或是區域視為一個個獨立的「島嶼」</strong>，這些「島嶼」會各自處理內部的腳本載入且不會互相影響，就像是獨立的應用程式。</p><p>如下圖所示，一個網頁中可能包含了靜態的圖片、廣告，也包含了動態的側邊欄和圖片輪播，在「島嶼架構」之下，不需要與使用者進行互動的靜態內容區塊就不會經過 <a href="https://en.wikipedia.org/wiki/Hydration_(web_development)">Hydration</a> 的過程，我們就可以減少載入的 JavaScript 總量，提升網站的效能。動態區域的腳本也可以透過非同步的載入，讓網站更快能與使用者互動。</p><figure><img alt="一個網頁中可能包含了靜態的圖片、廣告，也包含了動態的側邊欄和圖片輪播，在「島嶼架構」之下，不需要與使用者進行互動的靜態內容區塊就不會經過 Hydration 的過程，我們就可以減少載入的 JavaScript 總量，提升網站的效能" src="https://cdn-images-1.medium.com/max/909/0*7TZilctK29V8JTMt.png" /><figcaption>「島嶼架構」示意圖</figcaption></figure><p>簡單來說，<strong>「島嶼架構」旨在尋求「高互動性的 CSR (Client-side Rendering) 應用程式」和「具有高度 SEO 表現的 SSG (Static Site Generation) 靜態網頁」之間的平衡，同時也解決 SSR (server-side rendering) 框架 Full Hydration 所帶來的問題。</strong></p><p>Astro 所主打的「以內容為中心」，就十分適合採取這個策略，因為大部分的部落格、電商網站中的內容都是靜態的，但我們也會需要像是切換深淺色、購物車等簡單的互動。島嶼架構可以讓這些網站保持高 SEO，也能帶給使用者舒適的互動體驗。</p><p>總之，這些渲染模式和他們所帶來的效能影響並非三言兩語可以說完的，想要閱讀更多關於島嶼架構的討論，可以參考 <a href="https://github.com/lxsmnsyc/awesome-islands">Awesome Islands GitHub</a> 這個 Repo，裡面集結了各種關於島嶼架構的文章和影片資源。若是對其它的渲染模式有興趣的話，也可以收藏 <a href="https://www.patterns.dev/">Patterns.dev</a> 這個網頁。</p><h3>View Transition API</h3><p>Astro 另外一個值得一提的特色是「View Transition API」的應用。</p><p>有開發過 SPA (Single-page Application) 網頁的朋友應該都知道，其如同原生應用程式 (native apps) 般的即時換頁體驗是 SPA 的一個強大優勢。而 Astro 採取了較為傳統的 MPA (Multi-page Application) 模式，每次切換頁面的時候都會重新載入一個全新的頁面，在使用者體驗上就沒有 SPA 那麼流暢。</p><p>為了解決這個先天缺陷，引入<a href="https://developer.chrome.com/docs/web-platform/view-transitions?hl=en">瀏覽器原生</a>的 View Transition API 可以在不增加 JS bundle 的前提之下，大大的提升 MPA 的使用者體驗。</p><p>在 Astro 3.0 版本中，View Transition API 正式成為了一個 stable feature，我們可以用<a href="https://docs.astro.build/en/guides/view-transitions/#adding-view-transitions-to-a-page">短短的兩行程式碼</a>，輕鬆將換頁過場動畫加入到我們的網頁中。從下面這個範例可以看到，MPA 要做到跟原生應用程式類似的體驗不是不可能的！建議可以直接到 <a href="https://spotify-astro-transitions.vercel.app/">Demo</a> 操作看看會更明白實際的效果。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8QH6BNq-90B04DmCj_84Dw.gif" /></figure><p>此外，如果想要更深入了解除了引入瀏覽器原生的 View Transition API 之外，Astro 還在底層做了哪些事來達成更好的使用者體驗，可以閱讀這篇文章：<a href="https://www.maxiferreira.com/blog/astro-page-transitions/">Experiments with Astro and the Shared Element Transition API</a>。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/895/0*kxeRoaTWHg0CnwDS.png" /></figure><h3>開始開發吧！</h3><h4>開始一個新的 Astro 專案</h4><p>首先在終端機執行以下指令來啟動一個新的 Astro 專案：</p><pre># create a new project with npm<br>npm create astro@latest</pre><p>接著他會問你一些問題，回答完後等待所有 dependencies 下載完畢後就有一個新的 Astro 專案啦。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/816/0*SHvNP_MUG90Gq3im.png" /></figure><h4>檔案架構與路由設定</h4><p>打開新的 Astro 專案，會發現到 src 資料夾下面有三個子資料夾：pages、layouts 和 components，以下針對這三個資料夾做簡單的介紹：</p><ul><li>pages：放在 pages 資料夾中的子資料夾會自動形成網站的路由，以我的作品集為例，以下的資料夾結構就會形成 https://rooturl、https://rooturl/fr、https://rooturl/zh 三個路徑。</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/230/0*mK9-biJa9NjNPiNy.png" /></figure><ul><li>layouts: 我們可以把要應用在頁面的 layout 放在這個資料夾中，主要內容的部分則使用 &lt;slot&gt; 作為替代。</li></ul><pre>// src/layouts/MySiteLayout.astro<br>---<br>import BaseHead from &#39;../components/BaseHead.astro&#39;;<br>import Footer from &#39;../components/Footer.astro&#39;;<br>const { title } = Astro.props;<br>---<br>&lt;html lang=&quot;en&quot;&gt;<br>  &lt;head&gt;<br>    &lt;meta charset=&quot;utf-8&quot;&gt;<br>    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;<br>    &lt;BaseHead title={title}/&gt;<br>  &lt;/head&gt;<br>  &lt;body&gt;<br>    &lt;nav&gt;<br>      &lt;a href=&quot;#&quot;&gt;Home&lt;/a&gt;<br>      &lt;a href=&quot;#&quot;&gt;Posts&lt;/a&gt;<br>      &lt;a href=&quot;#&quot;&gt;Contact&lt;/a&gt;<br>    &lt;/nav&gt;<br>    &lt;h1&gt;{title}&lt;/h1&gt;<br>    &lt;article&gt;<br>      &lt;slot /&gt; &lt;!-- 主要內容會在這邊 --&gt;<br>    &lt;/article&gt;<br>    &lt;Footer /&gt;<br>  &lt;/body&gt;<br>&lt;/html&gt;</pre><pre>// src/pages/index.astro<br>---<br>import MySiteLayout from &#39;../layouts/MySiteLayout.astro&#39;;<br>---<br>&lt;MySiteLayout title=&quot;Home Page&quot;&gt;<br>  &lt;p&gt;My page content, wrapped in a layout!&lt;/p&gt;<br>&lt;/MySiteLayout&gt;</pre><ul><li>components: 在這個資料夾中，我們可以放置 .astro 檔案或是其他 UI 框架的檔案 (例如 .vue, .jsx 等等)</li></ul><h4>.astro 特殊語法</h4><p>除了 0 JavaScript 所帶來的高速使用者體驗之外，Astro 團隊也在開發者體驗上下足了苦功，其中之一就是他們所設計的 .astro 語法。</p><p>在 .astro 檔案中，我們可以在兩個 --- 中間撰寫 JavaScript 變數，並在中間的 <strong>JSX-like</strong> HTML template 中使用。需要注意的是，在兩個 --- 中間的程式碼只會在伺服器端執行，因此我們無法在這段程式碼中撰寫互動性的效果。</p><p>若我們要為元素添加樣式，則可以直接將 css 樣式撰寫在 &lt;style&gt; tag 中。寫在 &lt;style&gt; 中的樣式預設都是 scoped，因此不需要擔心樣式全域汙染的問題。</p><pre>// src/components/MyAstroComponent.astro<br>---<br>const hello = &quot;world&quot;<br>const animals = [&quot;Dog&quot;, &quot;Cat&quot;, &quot;Rabbit&quot;];<br>const visible = true;<br>---<br>&lt;h1&gt;{hello}&lt;/h1&gt;<br>&lt;ul&gt;<br>  {animals.map((animal) =&gt; (<br>    &lt;li&gt;{animal}&lt;/li&gt;<br>  ))}<br>&lt;/ul&gt;<br>&lt;div&gt;<br>  {visible &amp;&amp; &lt;p&gt;Show me!&lt;/p&gt;}<br>  {visible ? &lt;p&gt;Show me!&lt;/p&gt; : &lt;p&gt;Else show me!&lt;/p&gt;}<br>&lt;/div&gt;<br><br>&lt;style&gt;<br>  h1 {<br>    color: red;<br>    font-size: 3rem;<br>  }<br>&lt;/style&gt;</pre><p>若要撰寫互動性的程式碼，例如添加事件監聽器，則可以使用 &lt;script&gt; tag 來撰寫客戶端 JavaScript：</p><pre>---<br>---<br>&lt;button id=&quot;button&quot;&gt;Click Me&lt;/button&gt;<br>&lt;script&gt;<br>  function handleClick () {<br>    console.log(&quot;button clicked!&quot;);<br>  }<br>  document.getElementById(&quot;button&quot;).addEventListener(&quot;click&quot;, handleClick);<br>&lt;/script&gt;</pre><p>使用過 Vue 的朋友會對這樣的 script、template、style 的設計感到熟悉，而與 JSX 相似的語法則會讓使用過 React 的朋友容易上手。</p><h4>Astro VSCode Extension</h4><p>針對特殊的語法設計，Astro 團隊也有推出<a href="https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode">專屬的 VScode 插件</a>，讓我們在開發 Astro 元件時可以有適當的 syntax highlight。</p><h4>引入喜歡的前端框架</h4><p>前面有提到，我們可以直接在 .astro 檔案中引入用其他框架所寫的元件，不過在引入之前，必須先安裝對應的 integration，假設我們要在專案中寫 React 元件：</p><ol><li>執行以下指令來新增 React intergration：</li></ol><pre>npx astro add react</pre><p>2. 寫好你的 React 元件，並在 .astro 檔案中引入：</p><pre>// src/pages/static-components.astro<br>---<br>import MyReactComponent from &#39;../components/MyReactComponent.jsx&#39;;<br>---<br>&lt;html&gt;<br>  &lt;body&gt;<br>    &lt;h1&gt;Use React components directly in Astro!&lt;/h1&gt;<br>    &lt;MyReactComponent /&gt;<br>  &lt;/body&gt;<br>&lt;/html&gt;</pre><p>3. 要注意的是，在 Astro 中，「<strong>所有的框架元件預設都只會在伺服器端渲染</strong>」以避免將不必要的 JS 傳送到客戶端，因此所有的元件預設都是「<strong>靜態元件</strong>」！但如果我們的元件是互動性的該怎麼辦？</p><p>Astro 提供了一些特殊的 client directives 來控制我們何時要載入該元件的 JavaScript：</p><ul><li>client:load：當頁面載入的時候，同時載入該元件的 JS。</li><li>client:visible：只有當使用者滑動頁面到該元件進入 viewport 時，才載入該元件的 JS。</li><li>client:only=&quot;framework&quot;：使用這個 directive 表示該元件並不會經歷在伺服器端渲染的過程，因此必須傳入對應的框架名稱以確保 JS 正確載入。</li></ul><pre>// src/pages/interactive-components.astro<br>---<br>import InteractiveButton from &#39;../components/InteractiveButton.jsx&#39;;<br>import InteractiveCounter from &#39;../components/InteractiveCounter.jsx&#39;;<br>import InteractiveModal from &quot;../components/InteractiveModal.svelte&quot;<br>---<br>&lt;InteractiveButton client:load /&gt;<br>&lt;InteractiveCounter client:visible /&gt;<br>&lt;InteractiveModal client:only=&quot;svelte&quot; /&gt;</pre><p>4. 如果需要的話，我們甚至可以在同一個專案中引入以不同 UI 框架撰寫的元件 (雖然好像通常不會有這樣做的情境 🤔)：</p><pre>---<br>import MyReactComponent from &#39;../components/MyReactComponent.jsx&#39;;<br>import MySvelteComponent from &#39;../components/MySvelteComponent.svelte&#39;;<br>import MyVueComponent from &#39;../components/MyVueComponent.vue&#39;;<br>---<br>&lt;div&gt;<br>  &lt;MySvelteComponent /&gt;<br>  &lt;MyReactComponent /&gt;<br>  &lt;MyVueComponent /&gt;<br>&lt;/div&gt;</pre><h4>貼心的錯誤提示畫面</h4><p>在開發者體驗方面，Astro 也很貼心的準備了友善的錯誤提示畫面，讓開發者面對錯誤時能不那麼感到懼怕！</p><pre>---<br>const hello = &quot;world&quot;;<br>const animals = [&quot;Dog&quot;, &quot;Cat&quot;, &quot;Rabbit&quot;];<br>---<br>&lt;!-- 這邊少打了一個字母 --&gt;<br>&lt;h1&gt;{hell}&lt;/h1&gt; <br>&lt;ul&gt;<br>  {animals.map((animal) =&gt; &lt;li&gt;{animal}&lt;/li&gt;)}<br>&lt;/ul&gt;</pre><figure><img alt="可愛友善的錯誤訊息畫面" src="https://cdn-images-1.medium.com/max/960/0*yYnNdS4xjfFH8GKe.png" /><figcaption>可愛友善的錯誤訊息畫面</figcaption></figure><h4>使用 markdown 格式文件</h4><p><strong>Markdown Frontmatter 與 Layout</strong></p><p>既然是標榜「內容」為中心的框架，處理 markdown 格式的文件是必備的功能，而 Astro 這個部分也整合得非常好，可以直接在資料夾中新增 markdown 格式文件並引入，不需要額外的設定。例如我們在 /src/pages/ 中直接新增一個 post-1.md 的文件如下：</p><pre>---<br>layout: ../../layouts/BlogPostLayout.astro<br>title: Astro in brief<br>author: Himanshu<br>description: Find out what makes Astro awesome!<br>---<br># Hi there!<br><br>This Markdown file creates a page at `your-domain.com/page-1/`<br>It probably isn&#39;t styled much, but Markdown does support:<br><br>- **bold** and _italics._<br>- lists<br>- [links](https://astro.build)<br>- and more!</pre><p>在兩個 --- 之間的是我們文章的 frontmatter，可以將文章的重要訊息與主要的內容分開，在下方我們則能直接使用 markdown 語法來撰寫文章內容。注意到最上面我們引入了一個 layout 檔案，它被我們定義在 /src/layouts 中：</p><pre>// src/layouts/BlogPostLayout.astro<br>---<br>const {frontmatter} = Astro.props;<br>---<br>&lt;html&gt;<br>  &lt;!-- ... --&gt;<br>  &lt;h1&gt;{frontmatter.title}&lt;/h1&gt;<br>  &lt;h2&gt;Post author: {frontmatter.author}&lt;/h2&gt;<br>  &lt;p&gt;{frontmatter.description}&lt;/p&gt;<br>  &lt;slot /&gt; &lt;!-- Markdown content is injected here --&gt;<br>   &lt;!-- ... --&gt;<br>&lt;/html&gt;</pre><p>定義在 markdown 文件上方的 frontmatter 可以透過 props 的形式取出，並在 layout 中使用。此外，我們也能直接在 &lt;style&gt; tag 中撰寫 <a href="https://docs.astro.build/en/guides/styling/#markdown-styling">markdown 文件的 CSS 樣式</a>。</p><p><strong>Content Collections</strong></p><p>在 Astro 2.0 推出了 <strong>Content Collections</strong> 的功能，整合了 <a href="https://zod.dev/"><strong>Zod</strong></a> Schema Validation，讓我們用 type safe 的方式處理 markdown 內容。若要使用 Content Collections 的方式來管理 markdown 文件，須將文件放置在特殊的資料夾 src/content 中，並指定該 Collection 的名稱如下：</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/912/0*H7qr6S10LOJbvI31.png" /></figure><p>接著，我們可以定義一個 src/content/config.ts 設定檔，為 Collection 加上 schema checking。如此一來，Astro 就會自動檢查文件內容是否符合 schema，在開發時也會有屬性的智慧提示。 (註：這個 config 檔案是非必要的，但如果要對文件採取檢查的話就需要設定！)：</p><pre>// 1. Import utilities from `astro:content`<br>import { z, defineCollection } from &#39;astro:content&#39;;<br><br>// 2. Define a `type` and `schema` for each collection<br>const blogCollection = defineCollection({<br>  type: &#39;content&#39;, // v2.5.0 and later<br>  schema: z.object({<br>    title: z.string(),<br>    tags: z.array(z.string()),<br>    image: z.string().optional(),<br>  }),<br>});<br><br>// 3. Export a single `collections` object to register your collection(s)<br>export const collections = {<br>  &#39;blog&#39;: blogCollection,<br>};</pre><h4>Build and Deploy</h4><p>因為預設是 SSG 靜態網頁，因此在打包建置完成後可以輕鬆的部屬到任何靜態部屬平台，如 github pages、Netlify 等等。如果要使用 SSR 產生動態內容的話，則必須額外整合 Adapter 並部屬到相關平台，詳情請見<a href="https://docs.astro.build/en/guides/server-side-rendering/">官方文件</a>。這邊將以 Netlify 為例，示範部屬靜態網頁的過程：</p><ol><li>至 Netlify 官方網站上註冊/登入，並進入帳號儀表板</li><li>在 Sites 區塊點選 Add new site，並在下拉選單選取 Import an existing project</li><li>選擇專案的 repository 引入，Netlify 會自動偵測專案內容並填入適當的部屬設定。我們要確認以下的設定正確無誤：</li></ol><ul><li>Build Command: astro build or npm run build</li><li>Publish directory: dist</li></ul><p>4. 接著等待網站部屬完成，就能在網站頁面看到公開網址、部屬紀錄等資訊，並且能在 Site configuration 中做進一步的設定</p><p>5. 下一次只要有新的 commit 被推上該 repo，Netlify 就會重新自動部屬</p><h4>其他</h4><p>礙於文章的篇幅，沒辦法在這邊介紹所有的 Astro 特色和開發基礎，若有任何疑問都建議先參考 <a href="https://docs.astro.build/en/getting-started/">Astro 的官方文件</a>，編寫的非常清晰易懂。此外這邊提幾個我在開發作品集網站時有參考的內容：</p><ul><li>整合 Tailwind CSS：<a href="https://docs.astro.build/en/guides/integrations-guide/tailwind/">https://docs.astro.build/en/guides/integrations-guide/tailwind/</a></li><li>圖片優化：<a href="https://docs.astro.build/en/guides/images/#_top">https://docs.astro.build/en/guides/images/#_top</a></li><li>Icon 插件：<a href="https://github.com/natemoo-re/astro-icon?tab=readme-ov-file">https://github.com/natemoo-re/astro-icon?tab=readme-ov-file</a></li><li>i18n 多語系開發：<a href="https://docs.astro.build/en/recipes/i18n/#_top">https://docs.astro.build/en/recipes/i18n/#_top</a></li><li>深色模式開發：<a href="https://www.kevinzunigacuellar.com/blog/dark-mode-in-astro/">https://www.kevinzunigacuellar.com/blog/dark-mode-in-astro/</a></li></ul><h3>結語</h3><h4>Astro 的未來發展</h4><p>Astro 1.0 最早在 2022 年推出，兩年後的今天已經推出了 4.0 版本，今年更計畫推出專屬的部屬服務 <a href="https://studio.astro.build/">Astro Studio</a>，未來發展相當值得期待。</p><p>之所以會有這麼快速的成長，一方面是找到了明確的定位 (以內容為中心) 以及相對應的技術策略 (0 JS、島嶼架構)，一方面也因為採取了「framework agnostic」，吸引了很多本來只專注在單一框架的前端工程師、或是未曾使用前端框架的其他網頁工程師。</p><p>此外，前端圈近期吹起的「back to server trend」(例如關於 <a href="https://nextjs.org/docs/app/building-your-application/rendering/server-components">React Server Components</a>, <a href="https://www.builder.io/blog/htmx-vs-react">HTMX</a> 的討論) 也讓人反思前端開發中，大量的 JS 是否有必要，畢竟除了少數的複雜網頁應用，例如 Facebook、Figma 等，這世界上大多數的網頁都是靜態網頁！雖然這並不代表未來前端工程師的職業就會消失或被取代，但身為前端工程師，需要謹記在心的是在 JavaSciprt、React 的世界之外還有好大的一片天地值得去探索。</p><h4>個人使用感想</h4><p>回到個人的使用體驗，我認為 Astro 對於初學者來說相當友善，就算只會原生的 HTML、CSS、JS 也可以掌握現代化的元件化開發流程，而不用先去鑽研各個框架的特殊語法和架構。</p><p>不過，雖然在基本的架構上可以很快速的開發高效能的靜態網站，但實際開發上仍有一些限制需要注意。例如，<strong>使用不同的框架時，相關套件未必相容，同一功能可能會需要不同的解決方案</strong>。例如，我的作品集的 i18n 套件只適用於 Astro 元件，無法在 React 元件中使用；或是 Astro 的專屬 Image 元件，在 React 元件中的圖片就無法享受該元件帶來的優化效果。</p><p>總而言之，Astro 仍然是個相當年輕的框架，生態系仍然在發展中，資源不像成熟框架如 Next、Nuxt 豐富，框架本身變化也很快，在一年內從 2.0 升到 4.0。但如果看完文章後，對於 Astro 的架構、效能和開發者體驗有興趣、或是正好有開發靜態網站需求的人，推薦現在就實際去開啟一個新的專案來試看看吧！</p><h4>參考文章與資源</h4><ul><li><a href="https://docs.astro.build/en/getting-started/">Astro 官方文件</a></li><li><a href="https://astro.build/blog/2023-web-framework-performance-report/">2023 Web Framework Performance Report</a></li><li><a href="https://github.com/lxsmnsyc/awesome-islands">Awesome Islands GitHub</a></li><li><a href="https://crystallize.com/blog/frontend-performance-react-ssr-and-the-uncanny-valley">Frontend Performance: React SSR and the Uncanny Valley</a></li><li><a href="https://www.patterns.dev/">Patterns.dev</a></li><li><a href="https://devmvpchen.com/posts/rendering-pattern">CSR、SSR、SSG: 你需要知道的三種網頁渲染方式</a></li><li><a href="https://developer.chrome.com/docs/web-platform/view-transitions?hl=en">Smooth and simple transitions with the View Transitions API</a></li><li><a href="https://www.maxiferreira.com/blog/astro-page-transitions/">Experiments with Astro and the Shared Element Transition API</a></li><li><a href="https://nextjs.org/docs/app/building-your-application/rendering/server-components">Server Components — Next.js</a></li><li><a href="https://www.builder.io/blog/htmx-vs-react">A First Look at HTMX and How it Compares to React</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1a802b6638f5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Tailwind CSS 新手上路：概念、安裝與工具推薦]]></title>
            <link>https://medium.com/@Kelly_CHI/tailwind-css-introduction-and-tools-68e770b2bf7f?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/68e770b2bf7f</guid>
            <category><![CDATA[tailwind-css]]></category>
            <category><![CDATA[css]]></category>
            <category><![CDATA[frontend-development]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[tools]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Mon, 20 Nov 2023 12:15:22 GMT</pubDate>
            <atom:updated>2023-11-20T12:25:03.313Z</atom:updated>
            <content:encoded><![CDATA[<h4>Tailwind CSS 到底在紅什麼？它有哪些優缺點？這篇文章我們要一起來看看 Tailwind CSS 是什麼、要如何使用它、以及有哪些方便的工具可以使用。</h4><figure><img alt="Tailwind CSS 好香" src="https://cdn-images-1.medium.com/max/627/1*QT5448nQy0qdUwsQKiCU_Q.png" /><figcaption>Tailwind CSS 好香</figcaption></figure><h4>目錄</h4><p>· <a href="#d057">Tailwind CSS 基本概念</a><br>· <a href="#9ad2">Tailwind CSS 的優點</a><br>· <a href="#a712">Tailwind CSS 的缺點</a><br>· <a href="#773a">如何學習 Tailwind CSS</a><br>· <a href="#eb76">安裝與使用 Tailwind CSS</a></p><h3>前言</h3><p>在開發網頁使用者介面的過程中，CSS 是不可或缺的元素。然而，隨著專案規模的擴大，僅使用原生 CSS 在開發效率和維護性上會面臨種種挑戰。這時候，導入一個合適的 CSS 框架就是一個常見的解決方案。</p><p>最早推出於 2017 年，Tailwind CSS 是一個採用了「<strong>Utility First</strong>」理念的 CSS 框架。相對於傳統的 CSS 框架如 Bootstrap 或 CSS-in-JS 解決方案，Tailwind CSS 有著其獨特的優勢和特色。近年來，隨著生態系發展日益成熟，Tailwind CSS 儼然已成為現代前端 UI 開發的默認選擇。官方團隊在今年六月的時候還舉辦了首次的 conference <a href="https://tailwindcss.com/blog/2023-07-18-tailwind-connect-2023-recap">Tailwind Connect</a>，顯示了 Tailwind 的未來前景不可限量。</p><p>對於初學者而言，剛開始使用 Tailwind CSS 或許會感到有些不習慣。但根據我的個人經驗，一旦掌握了基本概念，開發過程將變得越來越得心應手，甚至感到「再也回不去原生 CSS 了！」所以，我希望透過這篇文章來介紹 Tailwind CSS 的基本概念、安裝方法，以及建議的學習路徑和相關工具，讓更多人能夠感受到 Tailwind CSS 的魅力。</p><h3>Tailwind CSS 基本概念</h3><h4>Utility First Framework</h4><p>前面有提到 Tailwind CSS 是主打「<strong>Utility First</strong>」的 CSS 框架，這意味著它提供了<strong>大量已預先定義好的、單一用途的 CSS class</strong>，讓我們可以直接應用在 HTML 標籤上，而不需要額外撰寫 CSS 樣式。</p><p>以往，如果要為一個通知元件撰寫樣式，我們可能會這樣做：</p><pre>&lt;div class=&quot;chat-notification&quot;&gt;<br>  &lt;div class=&quot;chat-notification-logo-wrapper&quot;&gt;<br>    &lt;img class=&quot;chat-notification-logo&quot; src=&quot;/img/logo.svg&quot; alt=&quot;ChitChat Logo&quot;&gt;<br>  &lt;/div&gt;<br>  &lt;div class=&quot;chat-notification-content&quot;&gt;<br>    &lt;h4 class=&quot;chat-notification-title&quot;&gt;ChitChat&lt;/h4&gt;<br>    &lt;p class=&quot;chat-notification-message&quot;&gt;You have a new message!&lt;/p&gt;<br>  &lt;/div&gt;<br>&lt;/div&gt;<br><br>&lt;style&gt;<br>  .chat-notification {<br>    display: flex;<br>    max-width: 24rem;<br>    margin: 0 auto;<br>    padding: 1.5rem;<br>    border-radius: 0.5rem;<br>    background-color: #fff;<br>    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);<br>  }<br>  .chat-notification-logo-wrapper {<br>    flex-shrink: 0;<br>  }<br>  .chat-notification-logo {<br>    height: 3rem;<br>    width: 3rem;<br>  }<br>  .chat-notification-content {<br>    margin-left: 1.5rem;<br>    padding-top: 0.25rem;<br>  }<br>  .chat-notification-title {<br>    color: #1a202c;<br>    font-size: 1.25rem;<br>    line-height: 1.25;<br>  }<br>  .chat-notification-message {<br>    color: #718096;<br>    font-size: 1rem;<br>    line-height: 1.5;<br>  }<br>&lt;/style&gt;</pre><p>但如果使用 Tailwind CSS，我們的 markup 會變成這樣：</p><pre>&lt;div class=&quot;p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4&quot;&gt;<br>  &lt;div class=&quot;shrink-0&quot;&gt;<br>    &lt;img class=&quot;h-12 w-12&quot; src=&quot;/img/logo.svg&quot; alt=&quot;ChitChat Logo&quot;&gt;<br>  &lt;/div&gt;<br>  &lt;div&gt;<br>    &lt;div class=&quot;text-xl font-medium text-black&quot;&gt;ChitChat&lt;/div&gt;<br>    &lt;p class=&quot;text-slate-500&quot;&gt;You have a new message!&lt;/p&gt;<br>  &lt;/div&gt;<br>&lt;/div&gt;</pre><p>你可能會想說，那這樣<strong>跟直接寫 inline styles 有什麼不一樣</strong>？主要的差異有兩個：</p><p>第一，在 inline styles 中我們還是可以任意的撰寫想要的樣式，但是 Tailwind CSS 所提供的 utility class 背後是有一套經過深思熟慮的 Design System，讓你在有限的選擇中創造具有一致性、且容易維護的 UI。</p><p>第二，在 inline styles 我們沒有辦法設定 media query 樣式或是 hover、focus 等狀態的樣式，但是透過 Tailwind CSS 提供的 prefix 和 state modifier，我們可以輕鬆的在 HTML markup 中直接撰寫這些樣式。</p><p><em>💡若對於 utility first 框架的歷史發展有興趣的人，非常建議閱讀 Huli 大大的這篇 </em><a href="https://blog.huli.tw/2022/05/23/atomic-css-and-tailwind-css/"><em>淺談 Atomic CSS 的發展背景與 Tailwind CSS</em></a><em>，可以對這樣的設計有更全面的理解。</em></p><h4>與 Bootstrap、CSS-in-JS 的差異</h4><p>Bootstrap 雖然可以快速地為應用程式打造可用的 prototype，但他在客製化上缺乏彈性長期為人詬病，也會發生「<strong>Bootstrap 網站看起來就像是 Bootstrap 網站</strong>」的狀況。Tailwind CSS 則更注重自由度和彈性，不像 Bootstrap 提供了預先設計好的元件，透過複製貼上就可以在應用程式中使用，Tailwind CSS 僅提供了預先定義好的 utility class，需由開發者自行搭建所需的元件。</p><p>CSS-in-JS 解決方案 (例如 Styled-Components、Emotion 等) 提供了元件 markup 和 CSS 的綁定，並且可以利用 JavaScript 來撰寫動態樣式，然而，<strong>這樣的靈活性和方便性有時會伴隨著效能上的犧牲</strong>。而 Tailwind CSS 則會在 build time 時自動移除所有未使用的 CSS 樣式，這意味著最終生成的 CSS bundle 大小極小，這在效能上提供了顯著的優勢。</p><p><em>💡有興趣進一步閱讀 CSS-in-JS 在效能方面的探討以及與 Tailwind CSS 的比較可以參考這幾篇文章：</em></p><ol><li><a href="https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b"><em>Why We’re Breaking Up with CSS-in-JS</em></a></li><li><a href="https://daily.dev/blog/why-i-moved-from-styled-components-to-tailwind-css-and-whats-the-future-of-css-in-js"><em>Why I moved from styled-components to Tailwind CSS and what’s the future of CSS-in-JS?</em></a></li><li><a href="https://caisy.io/blog/tailwind-css-vs-emotion"><em>Tailwind CSS vs Emotion</em></a></li></ol><h3>Tailwind CSS 的優點</h3><h4>✅ 提升開發效率</h4><p>Tailwind CSS的「Utility First」設計風格使開發速度變得極快。開發者可以直接在 HTML markup 中使用預先定義好的 class，而不需要經常切換到樣式表中進行設定。Tailwind CSS 也提供了簡便的 media query、hover、focus 狀態、dark 模式等等的 prefix 和 state modifier 讓開發者更容易撰寫響應式介面和不同狀態的 UI。這種直觀的開發方式使得快速建立 prototype 和後續修改維護變得更加容易。</p><h4>✅ Design System</h4><p>使用 Tailwind CSS 有助於建構一致的設計系統，尤其在多人共同開發的專案中，每個開發者對於樣式的寫法都可能有自己的習慣，長期下來可能導致樣式的管理變得複雜。在 Tailwind CSS 中，由於所有樣式都是預先定義好的，整個專案中的樣式便能保持一致。這樣的一致性不僅提高了程式碼的維護性，也使得與設計師的協作變得更加容易。</p><figure><img alt="Tailwind 作者所出版的官方電子書 Refactoring UI" src="https://cdn-images-1.medium.com/max/1024/1*hc8NOpe2OsvGwG0b-K1hRw.png" /><figcaption>Tailwind 作者所出版的官方電子書 <a href="https://www.refactoringui.com/"><em>Refactoring UI</em></a></figcaption></figure><p><em>💡 Tailwind 官方有推出一本電子書：</em><a href="https://www.refactoringui.com/"><em>Refactoring UI</em></a><em>，裡面提到了 Tailwind 本身的設計系統背後的思考哲學，例如單位的設定、調色板 (color palette) 的設計等等，有興趣的人可以參考 Theo 的</em><a href="https://www.youtube.com/watch?v=ZuLn42merAg"><em>這支影片</em></a><em>。</em></p><h4>✅ 容易客製化</h4><p>對於需要製作高度客製化的網頁的人，或許會覺得這些預先定義好的 class 無法滿足這樣的需求，但 Tailwind CSS 提供了豐富的 config 選項，開發者可以根據專案的需求去定義顏色、字型、邊框等屬性，Tailwind 甚至還會根據我們的設定去自動產生相對應的各種客製化 class。此外，在 markup 中我們也直接透過特殊的 syntax 去宣告預設中沒有的屬性和值。</p><h4>✅ 極小的 CSS Bundle</h4><p>雖然 Tailwind CSS 提供了大量的 utility class，但是在 build time 時會自動將所有沒有用到的 class 移除，因此就算我們自行定義了許多客製化的 utility class，最終生成的 CSS 文件其實仍是相對較小的，這有助於提高網站的效能。</p><h4>✅ 廣大的社群和生態系</h4><p>自從 Tailwind CSS 推出以來，它的社群和生態系都在持續的擴展，形成了一個龐大而活躍的開發者社群。社群提供了廣泛的教學資源、方便的工具和插件，以及大量的技術討論，使得學習和使用 Tailwind CSS 變得更加容易。</p><h3>Tailwind CSS 的缺點</h3><h4>⚠️ HTML Markup 難以閱讀</h4><p>使用 Tailwind CSS 的一個明顯缺點是 <strong>HTML markup 中包含了大量且冗長的 class</strong>，這可能影響原始碼的可讀性，並增加除錯的困難度 (之前有一陣子推特上面出現了大量嘲諷 Tailwind 的迷因，詳情可參考<a href="https://www.builder.io/blog/the-tailwind-css-drama-your-users-don&#39;t-care-about">此篇文章</a>)。這個特色也違反了所謂「Seperation of Concern」的原則，這一原則強調 HTML、CSS 和 JavaScript 應該要盡可能處理獨立的職責，以提高原始碼的維護性和擴展性。</p><figure><img alt="超~~~~級多又長的 class，這樣是好是壞？" src="https://cdn-images-1.medium.com/max/892/1*AxRnwe6HTXmwJSBgn5zuGg.png" /><figcaption>超~~~~級多又長的 class，這樣是好是壞？</figcaption></figure><p>然而，在「元件化開發」已經成為主流的現在，何謂好的「Seperation of Concern」仍然是一個值得辯論的議題。在 Tailwind CSS 作者 2017 年的<a href="https://adamwathan.me/css-utility-classes-and-separation-of-concerns/">這篇文章</a>中就探討了「語意化 HTML 結構」與「CSS 複用性」之間的權衡，相當值得一讀。</p><h4>⚠️ 需要時間上手</h4><p>雖然 Tailwind CSS 的使用相對直觀，但初學者可能需要一些時間來習慣其獨特的開發方式，並熟悉特定語法的使用。特別是對於那些已經習慣傳統 CSS 或其他框架的開發者，需要一定的時間轉變思維。</p><h4>⚠️ 沒有預設元件</h4><p>與其他 CSS 框架如 Bootstrap 相比，Tailwind CSS 並沒有提供預設的元件。這意味著開發者需要自行按照設計需求來撰寫元件的樣式。對於一些喜歡快速開發並使用預設元件的開發者而言，這可能被視為一個不足之處。不過，隨著生態系的發展，相關的 Tailwind CSS 元件庫也越來越豐富，例如我之前<a href="https://medium.com/@Kelly_CHI/shadcn-ui-tailwind-components-6fd4f1959147">在文章中有介紹過的 Shadcn-ui</a>。</p><figure><img alt="Shadcn ui，近期快速獲得關注的 Tailwind CSS 元件「合集」" src="https://cdn-images-1.medium.com/max/1024/1*taCpGNNtoXLvNlQKjJXQww.png" /><figcaption><a href="https://ui.shadcn.com/">Shadcn ui</a>，近期快速獲得關注的 Tailwind CSS 元件「合集」</figcaption></figure><p>總而言之，Tailwind CSS 作為一個高度靈活的 CSS 框架，其優點在於開發速度、客製化彈性、設計系統的建立等方面，但同時也存在著一些需要開發者留意的缺點，如原始碼的可讀性和上手難度。是否選擇使用 Tailwind CSS 還是要根據具體的專案需求和團隊的開發習慣來進行權衡。</p><h3>如何學習 Tailwind CSS</h3><p>對於剛學習網頁開發的新手，可能會納悶，既然 Tailwind CSS 這麼好用又受歡迎，那我還要學原生的 CSS 嗎？答案是一個大大的 <strong>YES</strong>！</p><h4>1. 最重要的第一步：打好 CSS 基礎</h4><p>要記住的一點是，所有 Tailwind CSS 所提供的 utility class 都是<strong>原生 CSS 的抽象化</strong>罷了，例如 flex-direction: column; 會寫成 .flex-col；或是 max-width: 100%; 會寫成 .max-w-full，如果一開始並不知道如何使用這些 CSS 屬性，那麼在 Tailwind CSS 中你還是不知道該使用哪些 utility class。因此，在開始學習與使用 Tailwind 之前，先打好 CSS 的基礎是很重要的。推薦的學習資源有 <a href="https://www.youtube.com/@KevinPowell">Kevin Powell 的 YT 頻道</a>以及 Wes Bos 的 <a href="https://flexbox.io/">Flexbox</a>、<a href="https://cssgrid.io/">Grid</a> 課程。</p><h4>2. 官方文件與教學</h4><p>接著，我們可以透過閱讀<a href="https://tailwindcss.com/docs/utility-first">官方文件</a>與教學來了解 Tailwind CSS 的基本概念、核心特性和使用方式。在 Tailwind Lab 的 YT 頻道上面提供了<a href="https://www.youtube.com/playlist?list=PL5f_mz_zU5eXWYDXHUDOLBE0scnuJofO0">一系列的影片教學</a>，個人認為是入門的最佳指南。我們還可以在官方的 <a href="https://play.tailwindcss.com/">Tailwind Play</a> 線上編輯器中直接體驗撰寫 Tailwind CSS 的感覺，以熟悉基本的語法。</p><figure><img alt="雖然是 V2 的介紹 (現在已經是 V3) 但是主要的概念和做法都是延續的！" src="https://cdn-images-1.medium.com/max/1024/1*owExni8nHDGEC1t9gvlWug.png" /><figcaption>雖然是 V2 的介紹 (現在已經是 V3) 但是主要的概念和做法都是延續的！</figcaption></figure><h4>3. 在專案中實際應用</h4><p>最好的學習方式是實際將 Tailwind CSS 應用在專案中。我們可以從小型的專案開始，嘗試應用各種不同的 utility class 來還原設計稿。<a href="https://www.frontendmentor.io/challenges">Frontend Mentor</a> 網站中的大小挑戰都是值得拿來練習的素材。沒有聽過 Frontend Mentor 這個網站的朋友可以參考以前寫過的這篇文章：<a href="https://medium.com/@Kelly_CHI/use-frontend-mentor-to-train-your-frontend-skills-17303a62c38d">Frontend Mentor 前端切版練功坊：用實作來逃離 tutorial hell 吧！</a></p><h4>4. 參與社群</h4><p>最後，我們還可以關注與 Tailwind CSS 生態系有關的社群動態，了解相關工具、UI 元件庫等等，並參與討論，學習他人的使用經驗。</p><h3>安裝與使用 Tailwind CSS</h3><h4>搭配 Vite &amp; React 來安裝</h4><p>在大部分的情況下，要在專案中使用 Tailwind CSS 會建議搭配打包工具 (build tools) 一起使用，以達到最佳的效能與開發體驗，這邊將介紹搭配 <strong>Vite 和 React</strong> 的安裝方式，若你是使用其他的框架或是工具可以參考<a href="https://tailwindcss.com/docs/installation/framework-guides">官方的文件</a>。</p><ol><li>開啟一個新的 Vite 專案，並指定使用 React template</li></ol><pre>npm create vite@latest my-project -- --template react<br>cd my-project</pre><p>2. 透過 npm 下載 Tailwind CSS 以及相關的相依性 (dependencies)，再透過 init 指令來生成 tailwind.config.js 和 postcss.config.js 這兩個 config 檔案</p><pre>npm install -D tailwindcss postcss autoprefixer<br>npx tailwindcss init -p</pre><p>3. 在 tailwind.config.js 中指定在專案中會使用到 Tailwind CSS 的檔案路徑</p><pre>/** @type {import(&#39;tailwindcss&#39;).Config} */<br>export default {<br>  content: [<br>    &quot;./index.html&quot;,<br>    &quot;./src/**/*.{js,ts,jsx,tsx}&quot;,<br>  ],<br>  theme: {<br>    extend: {},<br>  },<br>  plugins: [],<br>}</pre><p>4. 在主要的 CSS 檔案 ./src/index.css 中加入 Tailwind CSS 各個層級的 utility class</p><pre>@tailwind base;<br>@tailwind components;<br>@tailwind utilities;</pre><p>5. 在專案中使用 Tailwind CSS utility class 來撰寫樣式</p><pre>export default function App() {<br>  return (<br>    &lt;h1 className=&quot;text-3xl font-bold underline&quot;&gt;<br>      Hello world!<br>    &lt;/h1&gt;<br>  )<br>}</pre><p>6. 透過終端機執行 build process，我們會在最終產出的 dist 資料夾中找到經過自動清除和壓縮的 CSS 檔案</p><pre>npm run dev</pre><h4>基本客製化設定</h4><p>我們可以在 tailwind.config.js 檔案中進行專案的各項基本設定，例如自定義顏色、字型、間距等。例如以下這個設定覆蓋了原本預設的 media breakpoints、色彩和字型。如果沒有要覆蓋原本的預設，可以使用下方的 extend 來擴充原本沒有的 utility class。此外，我們還可以使用 plugins 來新增各式各樣的實用插件。(參閱<a href="https://tailwindcss.com/docs/adding-custom-styles">官方文件說明</a>)</p><pre>/** @type {import(&#39;tailwindcss&#39;).Config} */<br>module.exports = {<br>  theme: {<br>    screens: {<br>      sm: &#39;480px&#39;,<br>      md: &#39;768px&#39;,<br>      lg: &#39;976px&#39;,<br>      xl: &#39;1440px&#39;,<br>    },<br>    colors: {<br>      &#39;blue&#39;: &#39;#1fb6ff&#39;,<br>      &#39;purple&#39;: &#39;#7e5bef&#39;,<br>      &#39;pink&#39;: &#39;#ff49db&#39;,<br>      &#39;orange&#39;: &#39;#ff7849&#39;,<br>      &#39;green&#39;: &#39;#13ce66&#39;,<br>      &#39;yellow&#39;: &#39;#ffc82c&#39;,<br>      &#39;gray-dark&#39;: &#39;#273444&#39;,<br>      &#39;gray&#39;: &#39;#8492a6&#39;,<br>      &#39;gray-light&#39;: &#39;#d3dce6&#39;,<br>    },<br>    fontFamily: {<br>      sans: [&#39;Graphik&#39;, &#39;sans-serif&#39;],<br>      serif: [&#39;Merriweather&#39;, &#39;serif&#39;],<br>    },<br>    extend: {<br>      spacing: {<br>        &#39;128&#39;: &#39;32rem&#39;,<br>        &#39;144&#39;: &#39;36rem&#39;,<br>      },<br>      borderRadius: {<br>        &#39;4xl&#39;: &#39;2rem&#39;,<br>      }<br>    }<br>  },<br>  plugins: [require(&#39;@tailwindcss/forms&#39;)]<br>}</pre><h4>⚙️ 推薦搭配使用的工具或套件</h4><h4><a href="https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss">Official VS Code IntelliSense</a></h4><p>Tailwind CSS 和 VS Code 合作的官方插件，幫助我們在開發的時候可以更方便地撰寫 utility class。這個插件提供了像是自動完成、錯誤提示和預覽最後生成的原生 CSS 樣式等功能，可以說是用 Tailwind CSS 開發的必備工具。</p><h4><a href="https://tailwindcss.com/blog/automatic-class-sorting-with-prettier">Automatic Class Sorting Prettier Plugin</a></h4><p>Prettier 是一個在開發的時侯常用的工具，幫助我們保持程式碼風格的一致性。在使用 Tailwind CSS 開發元件的時候，常常會遇到 class 太過冗長、雜亂而找不到想要修改的 class 的問題。這個插件可以自動整理 class 的順序，讓不同元件的樣式寫法保持一致，減少修改上的麻煩。</p><h4><a href="https://tailwindcomponents.com/cheatsheet/">Tailwind CSS Cheat Sheet</a></h4><p>由於 Tailwind CSS 有大量的 utility class，初學者可能難以迅速記住所有的語法。這時候，使用 cheatsheet 可以方便地查閱各種 class 的寫法，提升開發效率。</p><figure><img alt="使用 Cheatsheet 可以快速查詢 CSS 屬性和 Tailwind CSS class 的對照" src="https://cdn-images-1.medium.com/max/1024/1*im-2bZAbC3EhmfbMch-nOg.png" /><figcaption>使用 Cheatsheet 可以快速查詢 CSS 屬性和 Tailwind CSS class 的對照</figcaption></figure><h4><a href="https://www.npmjs.com/package/tailwind-merge">Tailwind Merge 套件</a></h4><p>在使用 Tailwind CSS 開發的時候有一個常見的陷阱，當我們在同一個元素上面為同一個 CSS 屬性設定了不同的值 (例如同時設定了 bg-blue-500 和 bg-green-500)，根據直覺可能會覺得應該是寫在後面的那個值會反映到該元素上，但實際上在 Tailwind CSS 中並不是這樣！最後反映在元素上的樣式是<strong>根據 source CSS 中的順序來決定的</strong>。因此，使用 Tailwind Merge 這個套件可以確保有衝突的 class 可以確實的套用到該元素上。(可進一步參考<a href="https://www.youtube.com/watch?v=tfgLd5ZSNPc">這個影片</a>的說明)</p><h4><a href="https://www.npmjs.com/package/clsx">clsx 套件</a></h4><p>clsx 套件則是協助我們撰寫條件式的樣式的好用工具，例如以下的範例，classes 在任何時候都會套用到該元素上，但是 classes1 只會在 condition1 為真的時候套用，而在 condition2、condition3 皆為真的時候則是套用 classes2。</p><pre>clsx(&#39;classes&#39;, {<br>    &#39;classes1&#39;: condition1,<br>    &#39;classes2&#39;: condition2 &amp;&amp; condition3<br>})</pre><p>我們也可以將這兩個常用的 package 結合為同一個 utility function，讓使用更方便。</p><pre>import { clsx } from &quot;clsx&quot;;<br>import { twMerge } from &quot;tailwind-merge&quot;;<br> <br>function cn(...args) {<br>  return twMerge(clsx(args));<br>}</pre><h4><a href="https://cva.style/docs">CVA (Class Variance Authority) 套件</a></h4><p>在開發 UI 的過程中，我們時常要處理同一個 UI 的不同「狀態」，而依據這些狀態我們的 UI 會有不同的「變化 (variants)」。最常見的例子是，一個按鈕元件可能會有「主要」、「次要」、「警告」、「禁用」等等不同的變化。而 CVA 這個套件就是為了<strong>讓我們可以更方便的撰寫與管理這些變化的樣式</strong>，同時它也完全支援 TypeScript，幫助我們在使用這些按鈕時可以有充分的智慧提示。更詳盡的介紹與使用方式可以參考<a href="https://cva.style/docs">官方文件</a>與 Coding in Public 的<a href="https://www.youtube.com/watch?v=kHQNK2jU_TQ">這支影片</a>。</p><figure><img alt="Carbon (IBM 的開源設計系統) 的按鈕元件" src="https://cdn-images-1.medium.com/max/1024/0*zadJyEiy1OjWNsBC.png" /><figcaption>Carbon (IBM 的開源設計系統) 的按鈕元件</figcaption></figure><pre>// 以 Shadcn-ui 的 button 元件為例<br>const buttonVariants = cva(<br>  &quot;inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50&quot;,<br>  {<br>    variants: {<br>      variant: {<br>        default: &quot;bg-primary text-primary-foreground hover:bg-primary/90&quot;,<br>        destructive:<br>          &quot;bg-destructive text-destructive-foreground hover:bg-destructive/90&quot;,<br>        outline:<br>          &quot;border border-input bg-background hover:bg-accent hover:text-accent-foreground&quot;,<br>        secondary:<br>          &quot;bg-secondary text-secondary-foreground hover:bg-secondary/80&quot;,<br>        ghost: &quot;hover:bg-accent hover:text-accent-foreground&quot;,<br>        link: &quot;text-primary underline-offset-4 hover:underline&quot;,<br>      },<br>      size: {<br>        default: &quot;h-10 px-4 py-2&quot;,<br>        sm: &quot;h-9 rounded-md px-3&quot;,<br>        lg: &quot;h-11 rounded-md px-8&quot;,<br>        icon: &quot;h-10 w-10&quot;,<br>      },<br>    },<br>    defaultVariants: {<br>      variant: &quot;default&quot;,<br>      size: &quot;default&quot;,<br>    },<br>  }<br>)</pre><p>除了上述所提到的工具和套件之外，Tailwind CSS 還有許多<a href="https://tailwindcss.com/docs/plugins">實用的插件</a>可供使用，像是用來處理 markdown 文件樣式的 Typography 插件、為表單提供基本樣式的 Form 插件和 Container Queries 插件等等，都可以為我們的開發過程提供不小的幫助。</p><h3>結語</h3><p>Tailwind CSS 推出至今已在前端開發領域贏得了相當的地位，甚至成為許多框架的默認 styling 選擇。儘管如同所有工具一樣，它未必適用於每個專案或每位開發者，但我相信學習 Tailwind CSS 無論是在製作 Side Project 或導入公司未來專案的技術中，都將是一個極具價值的選擇。因此，擇日不如撞日，看完文章的你，趕快著手使用 Tailwind 來開發新專案吧！</p><h4>參考資源整理</h4><ol><li><a href="https://tailwindcss.com/docs/utility-first">Tailwind CSS 官方文件</a></li><li><a href="https://play.tailwindcss.com/">Tailwind Play 官方線上編輯器</a></li><li><a href="https://tailwindcss.com/blog/2023-07-18-tailwind-connect-2023-recap">Tailwind Connect</a>：首次官方 conference 的文字記錄</li><li><a href="https://www.refactoringui.com/">Refactoring UI</a>：介紹設計系統背後的思考哲學的電子書</li><li><a href="https://www.youtube.com/playlist?list=PL5f_mz_zU5eXWYDXHUDOLBE0scnuJofO0">Tailwind CSS v2.0: From Zero to Production</a>：官方影片教學系列</li><li><a href="https://blog.huli.tw/2022/05/23/atomic-css-and-tailwind-css/">淺談 Atomic CSS 的發展背景與 Tailwind CSS</a> by Huli</li><li><a href="https://adamwathan.me/css-utility-classes-and-separation-of-concerns/">CSS Utility Classes and “Separation of Concerns”</a> by Adam Wathan</li><li><a href="https://www.youtube.com/watch?v=ZuLn42merAg">I didn’t realize THIS about Tailwind…</a> by Theo — t3․gg</li><li><a href="https://www.builder.io/blog/the-tailwind-css-drama-your-users-don&#39;t-care-about">The Tailwind CSS Drama Your Users Don’t Care About</a> by <a href="http://builder.io/">Builder.io</a></li><li><a href="https://medium.com/@Kelly_CHI/shadcn-ui-tailwind-components-6fd4f1959147">Shadcn-ui : 美觀、無障礙、又能 100 % 客製化的「元件合集」</a> by Kelly CHI</li><li><a href="https://www.youtube.com/watch?v=tfgLd5ZSNPc">Tailwind-Merge Is Incredibly Useful — And Here’s Why!</a> by Simon Swiss</li><li><a href="https://www.youtube.com/watch?v=kHQNK2jU_TQ">Class Variance Authority (CVA) Quickstart</a> by Coding in Public</li><li><a href="https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b">Why We’re Breaking Up with CSS-in-JS</a> by Sam Magura</li><li><a href="https://daily.dev/blog/why-i-moved-from-styled-components-to-tailwind-css-and-whats-the-future-of-css-in-js">Why I moved from styled-components to Tailwind CSS and what’s the future of CSS-in-JS?</a> by Ido Shamun</li><li><a href="https://caisy.io/blog/tailwind-css-vs-emotion">Tailwind CSS vs Emotion</a> by Irelia Codeheart</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=68e770b2bf7f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[前端開發資源推薦 (三) Podcast 節目篇]]></title>
            <link>https://medium.com/@Kelly_CHI/best-frontend-podcast-recommendations-874ee1b167cc?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/874ee1b167cc</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[podcast]]></category>
            <category><![CDATA[recommendations]]></category>
            <category><![CDATA[front-end-development]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Wed, 01 Nov 2023 14:43:12 GMT</pubDate>
            <atom:updated>2023-11-01T14:43:12.804Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/650/1*dFrEaixUVeRrvLXa0QAATw.png" /><figcaption>每天都有新的前端技術在門後等著折磨前端工程師</figcaption></figure><p>身為苦命的前端工程師，每天不但要面對千奇百怪的需求，還要被閃亮亮的新技術追著跑，如果能更輕鬆地接收新知，或許人生會輕鬆一點吧！在先前的文章中，我有介紹過：<a href="https://medium.com/@Kelly_CHI/recommended-frontend-youtube-channel-4c148eddbdb">前端開發資源推薦 (一) Youtube 頻道篇</a>和<a href="https://medium.com/@Kelly_CHI/frontend-newsletter-recommendation-1e53e618c05a">前端開發資源推薦 (二) Newsletter 篇</a>，今天要跟大家分享的是和前端有關的 podcast 節目。</p><p>Podcast 一直以來都是我很喜歡的知識媒介，最大的原因在於我們可以在任何時間地點吸收這些知識，不管在煮飯、運動還是通勤的時候，都可以來聽個一兩集節目。此外，在一整天長時間盯著電腦螢幕後，聽 podcast 換一個方式接收資訊還能舒緩眼睛的疲勞。</p><p>雖然在 podcast 中我們沒辦法看到具體程式碼的實作或是範例，但其實前端開發有很多的概念與想法是超越程式碼本身的。以下許多節目中的與談人都是網頁開發界的大神，很多都有公開的 conference talk 可以看，但如果覺得直接看演講太硬的話，podcast 的對談方式可以讓我們更輕鬆的了解大神們的所思所想。</p><h3>十一個不容錯過的前端開發 Podcast 節目</h3><h4><a href="https://podrocket.logrocket.com/">1. PodRocket</a></h4><p>由 <a href="https://logrocket.com/">LogRocket</a> 所推出的節目。邀請許多套件作者和前端領域的專家來討論各式各樣的主題，主持人和講者的對談品質非常好，更新頻率高，值得推薦。</p><ul><li><a href="https://podrocket.logrocket.com/creating-reusable-components">Creating reusable components with Cory House</a></li><li><a href="https://podrocket.logrocket.com/react-and-frontend-development">React and frontend development with Josh Comeau</a></li></ul><figure><img alt="Podrocket podcast cover" src="https://cdn-images-1.medium.com/max/462/1*8Bu8ti_5e3PbhSIL5DYNPQ.png" /></figure><h4><a href="https://syntax.fm/">2. Syntax</a></h4><p>由 <a href="https://javascript30.com/">JavaScript 30</a> 這個著名課程的作者 Wes Bos 和 <a href="https://levelup.video/">Level Up Tutorials</a> 的創始者 Scott Tolinski 共同主持的 podcast 節目，主題涵蓋前、後端開發的大小事，Wes Bos 鮮明的個人風格讓節目輕鬆有趣。最近萬聖節到了，他們推出的 <a href="https://syntax.fm/show/683/spooky-coding-horror-stories-2023-part-1">Spooky Coding Horror Stories 上下集</a>真是讓人冷汗直流、嚇到想要離開網頁開發領域呢。</p><figure><img alt="Syntax podcast cover" src="https://cdn-images-1.medium.com/max/464/1*v54KKWkl3D88kHApf7rv9g.png" /></figure><h4><a href="https://www.buzzsprout.com/2226499">3. Front-End Fire</a></h4><p>由工程師 TJ VanToll、Paige Niedringhaus 和也有<a href="https://www.youtube.com/@jherr">自己的 Youtube 頻道</a>的 Jack Herrington 所主持的 podcast 節目，內容聚焦在前端生態圈的最新大小事，若想要知道前端世界每週有哪些值得關注的議題，聽這個節目準沒錯。</p><ul><li><a href="https://www.buzzsprout.com/2226499/13521453-astro-partners-with-vercel-lightning-css-gets-adopted-by-tailwind-and-chatgpt-goes-enterprise-edition">Astro partners with Vercel, Lightning CSS gets adopted by Tailwind, and ChatGPT goes Enterprise Edition</a></li></ul><figure><img alt="Frontend Fire podcast cover" src="https://cdn-images-1.medium.com/max/459/1*HHK5_V1Y_xlLg2wc6cGjyw.png" /></figure><h4><a href="https://www.htmlallthethings.com/">4. HTML all the things</a></h4><p>由 Matt Lawrence 和 Mike Karan 兩人共同主持的 podcast 節目，主題圍繞在網頁開發、網頁設計和自由工作者的管理經營，也有許多針對新手開發者的討論。例如以下這兩集討論了新手初入職場可能會遇到的任務和困難，十分推薦給轉職的夥伴：</p><ul><li><a href="https://www.htmlallthethings.com/podcasts/what-id-expect-from-a-junior-developer">What I’d Expect From a Junior Developer</a></li><li><a href="https://www.htmlallthethings.com/podcasts/succeeding-in-your-first-week-as-a-junior-developer">Succeeding in Your First Week as a Junior Developer</a></li></ul><figure><img alt="HTML All The Things podcast cover" src="https://cdn-images-1.medium.com/max/464/1*FRfPxlevwVhVdsQXgAOB_g.png" /></figure><h4><a href="https://changelog.com/jsparty">5. JS Party</a></h4><p>由 <a href="https://changelog.com/">ChangeLog</a> 所推出的 podcast 節目之一，聚焦在 JavaScript 生態圈和網頁開發的大小事，包含 CSS、React、Node.js 等等主題。除了這個節目之外，Changelog 還推出了講軟體開發時事的 <a href="https://changelog.com/podcast">The Changelog</a>、訪問大小軟體公司 CTO 的 <a href="https://changelog.com/founderstalk">Founders Talk</a>、討論 AI 話題的 <a href="https://changelog.com/practicalai">Pratical AI</a> 以及<a href="https://changelog.com/">其他</a>，有興趣的朋友不妨都訂閱起來！</p><ul><li><a href="https://changelog.com/jsparty/267">The future of React</a></li><li><a href="https://changelog.com/jsparty/224">Were SPAs a big mistake?</a></li></ul><figure><img alt="JS Party podcast cover" src="https://cdn-images-1.medium.com/max/465/1*7QCLRWtLH-mzDjEaXgbV4A.png" /></figure><h4><a href="https://www.youtube.com/@GeneralMusings/about">6. General Musing</a>s</h4><p>由江湖人稱 CSS 之王的 Youtuber <a href="https://www.youtube.com/channel/UCJZv4d5rbIKd4QHMPkcABCw">Kevin Powell</a> 新推出的 podcast 節目。和 YT 以教學為主的內容不同，podcast 著重在前端學習心法和一些相關主題的討論，如果喜歡 Kevin 的 YT 頻道的朋友，也很推薦聽一聽他的 podcast。不知道為什麼，Kevin 的聲音語調總是有種很讓人安心的心靈導師感呢。</p><ul><li><a href="https://podcasts.apple.com/us/podcast/keeping-up-momentum-with-self-paced-learning/id1705267112?i=1000632167566">Keeping up momentum with self-paced learning</a></li><li><a href="https://podcasts.apple.com/us/podcast/the-css-mindset/id1705267112?i=1000628960936">The CSS Mindset</a></li></ul><figure><img alt="General Musings with Kevin Powell podcast cover" src="https://cdn-images-1.medium.com/max/462/1*E4TWGnMxNCpz30vaUCZWfw.png" /></figure><h4><a href="https://frontendfirst.fm/">7. Frontend First</a></h4><p>由兩位工程師 Sam Selikoff 和 Ryan Toronto 共同主持的節目，主題聚焦在以 React 生態系為主的前端開發議題。近期有許多關於 React Server Components 的討論，有興趣的朋友不妨聽聽以下幾集節目：</p><ul><li><a href="https://frontendfirst.fm/episodes/server-components-and-the-react-paradigm">Server Components and the React paradigm</a></li><li><a href="https://frontendfirst.fm/episodes/what-problems-do-react-server-components-solve">What problems do React Server Components solve?</a></li></ul><figure><img alt="Frontend First podcast cover" src="https://cdn-images-1.medium.com/max/459/1*SzlmP0GYvTyo93akpnWXtg.png" /></figure><h4><a href="https://modernweb.podbean.com/">8. Modern Web</a></h4><p>和 Podrocket 同樣是以訪談為主的節目，主題圍繞在前後端開發的各種面向。</p><ul><li><a href="https://modernweb.podbean.com/e/modern-web-podcast-s11e4-frameworks-vs-fundamentals-striking-the-right-balance/">Frameworks vs. Fundamentals: Striking the Right Balance</a></li><li><a href="https://modernweb.podbean.com/e/modern-web-podcast-s11e3-design-system-engineering-at-scale-with-kathleen-mcmahon/">Design System Engineering at Scale with Kathleen McMahon</a></li></ul><figure><img alt="Modern Web podcast cover" src="https://cdn-images-1.medium.com/max/457/1*rBl2YLmENgpRLOh7lKLXxA.png" /></figure><h4><a href="https://topenddevs.com/podcasts/javascript-jabber">9. JavaScript Jabber</a></h4><p>以 JavaScript 和網頁開發相關議題為主的節目。內容包括專家訪談，以及各種有關 JavaScript 套件、框架的見解和討論。</p><ul><li><a href="https://topenddevs.com/podcasts/javascript-jabber/episodes/is-javascript-on-the-backend-a-mistake-jsj-596">Is JavaScript on the Backend a Mistake?</a></li><li><a href="https://topenddevs.com/podcasts/javascript-jabber/episodes/what-if-your-javascript-validations-looked-like-tests-jsj-597">What if your JavaScript Validations Looked like Tests?</a></li></ul><figure><img alt="JavaScript Jabber podcast cover" src="https://cdn-images-1.medium.com/max/453/1*AhOyE3LSo3dtKi441R_MqA.png" /></figure><h4><a href="https://www.frontendhappyhour.com/">10. Front-end Happy Hour</a></h4><p>由一組來自矽谷科技公司 (包括 Netflix、Twitch、Atlassian、Evernote 和 LinkedIn) 的固定成員組成，他們經常邀請來賓一起小酌一杯並討論各種與前端、JavaScript、軟體工程和職業發展相關的主題。</p><ul><li><a href="https://www.frontendhappyhour.com/episodes/component-libraries-cocktail-ingredients/">Component libraries — cocktail ingredients</a></li><li><a href="https://www.frontendhappyhour.com/episodes/learning-time-to-wine-down-and-learn/">Learning — time to wine down and learn</a></li></ul><figure><img alt="Frontend Happy Hour podcast cover" src="https://cdn-images-1.medium.com/max/457/1*iNAJUUOTM8E7Klp3KTAa0A.png" /></figure><h4><a href="https://bento.me/fetalkpodcast">11. 前端輕鬆聊</a></h4><p>由在溫哥華工作的台灣工程師 Eric 所主持的中文節目，每週以專業且容易消化的方式介紹各式各樣的前端技術與經驗。他也有推出分享精選開發文章的個人<a href="https://breakpointfordevs.substack.com/">電子報</a>。</p><ul><li><a href="https://podcasts.apple.com/us/podcast/ep17-staff-software-engineer-%E9%9D%A2%E8%A9%A6%E7%B6%93%E9%A9%97/id1692293198?i=1000632452095">Staff Software Engineer 面試經驗</a></li><li><a href="https://podcasts.apple.com/us/podcast/ep13-%E5%89%8D%E7%AB%AF%E5%B7%A5%E7%A8%8B%E5%B8%AB%E6%80%8E%E9%BA%BC%E8%B7%9F%E8%A8%AD%E8%A8%88%E5%B8%AB%E5%B7%A5%E4%BD%9C/id1692293198?i=1000628530260">前端工程師怎麼跟設計師工作</a></li></ul><figure><img alt="前端輕鬆聊 podcast cover" src="https://cdn-images-1.medium.com/max/460/1*BxmgooA5NHSTgk4jO_hHtw.png" /></figure><p>以上就是我推薦的 11 個前端開發 podcast 節目，若有其他有趣的節目也歡迎在留言跟大家分享！😁</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=874ee1b167cc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Shadcn-ui : 美觀、無障礙、又能 100 % 客製化的「元件合集」]]></title>
            <link>https://medium.com/@Kelly_CHI/shadcn-ui-tailwind-components-6fd4f1959147?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/6fd4f1959147</guid>
            <category><![CDATA[component-libraries]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[tailwind-css]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[shadcn]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Wed, 18 Oct 2023 16:58:10 GMT</pubDate>
            <atom:updated>2024-06-13T14:35:21.702Z</atom:updated>
            <content:encoded><![CDATA[<h3>Shadcn-ui : 美觀、無障礙、又能 100 % 客製化的「元件合集」</h3><h4>2023 年三月釋出，截至目前已超過 60K Github 星星，更獲得了 <a href="https://risingstars.js.org/2023/en">2023 JavaScript Rising Stars</a> 調查年度第一名 ⭐</h4><h4>建議先備知識</h4><ul><li>Tailwind CSS 基本概念</li><li>React 基本概念與實作經驗</li></ul><h3>前言</h3><p>在開發前端介面時，總是會遇到像是按鈕、輸入框、警告視窗等等這些一再出現的元件，若每次都要從頭開始造輪子，想必要花費大量的時間和精力，尤其在無障礙體驗方面，靠一己之力很難做到面面俱到。這時候，運用元件庫就能有效提升產品品質和開發速度。市面上常見到 React 元件庫有 <a href="https://mui.com/">Material UI</a>、<a href="https://ant.design/">Ant Design</a>、<a href="https://chakra-ui.com/">Chakra UI</a> 等等，而 Vue 生態系則有 <a href="https://quasar.dev/">Quasar</a>、<a href="https://vuetifyjs.com/en/">Vuetify</a> 等等。</p><p>今天要來介紹的是一個由 Vercel 的 design engineer 所推出的「元件合集」(component collection)，<a href="https://ui.shadcn.com/"><strong>Shadcn-ui</strong></a> (不是 shad-CDN 🫠)。根據<a href="https://ui.shadcn.com/docs">官方的說法</a>，之所以將自己定位成「元件合集」而非「元件庫 (component library)」的原因在於：與一般的元件庫不同，Shadcn-ui 並非以 dependency 的形式安裝在專案中，相反的，<strong>所有元件的程式碼都會直接存放在該專案的元件資料夾中，可以任意的修改並客製化</strong>。</p><figure><img alt="Shadcn ui 首頁截圖" src="https://cdn-images-1.medium.com/max/1024/1*DAkbzGTxuseWZfvo6waG8w.png" /></figure><p>值得一提的是，Shadcn-ui 其實是建立於另外一個元件庫 <a href="https://www.radix-ui.com/primitives"><strong>Radix UI</strong></a> 的 primitive 元件上 (意指沒有提供預設樣式的元件)，這些 primitive 元件提供了完整的無障礙體驗與元件基礎 API，而 Shadcn-ui 在這個基礎上透過 <strong>Tailwind CSS</strong> 為這些元件包裝了基礎樣式，讓開發者能更快速的打造兼具美感和實用性的 prototype。</p><h3>Shadcn UI 的一些特色</h3><h4>完整的無障礙體驗</h4><p>Shadcn UI 是建立於 Radix UI 上，而 Radix UI 所標榜的最大特色之一就是他們的 Accessibility：<strong>所有元件都遵守 WAI-ARIA 標準規範，且有通過跨瀏覽器及多種輔助科技的測試</strong>。有興趣了解更多的人可以讀一讀 Radix UI 的<a href="https://www.radix-ui.com/primitives/docs/overview/accessibility">文件</a>。</p><h4>程式碼完全由你控制</h4><p>前面有提到 Shadcn ui 與一般的元件庫最大的不同在於，<strong>所有的元件都可以直接在專案中進行編輯</strong>。以下面這個 button 元件為例，當我們透過 CLI 指令將 button 新增到我們的專案中，會看到在 components 資料夾下面多了一個 ui 資料夾，其中就能找到剛剛新增的 button 元件。</p><p>如同我們自行定義的任何元件，我們可以針對這個 button 進行任何修改，例如加上新的 variant 等等。此外，Shadcn ui 是由 TypeScript 編寫，我們新增的樣式也都會在自動完成的下拉選單中出現。</p><figure><img alt="我們可以在專案中，根據需求自由地修改元件的內容" src="https://cdn-images-1.medium.com/max/1024/1*Ba2I-xwpsxuQ5RjXcYycFA.png" /><figcaption>我們可以在專案中，根據需求自由地修改元件的內容</figcaption></figure><h4>複製貼上不是問題</h4><p>Shadcn ui 首頁上面擺明了寫著：這是一個你可以輕鬆 <strong>copy and paste</strong> 的元件合集。不只所有的元件都是開源的、可以一鍵複製，在「<strong>Examples</strong>」這個頁面中還提供了儀表版 (dashboard)、多種卡片、資料表格、登入頁面等等精美實用的範例。<strong>這些全部都能透過「複製貼上」來應用到自己的專案中</strong>，省下從頭設計 UI 的麻煩，對於獨自開發 side project 的人來說簡直是天上掉下來的禮物✨。</p><figure><img alt="在「Examples」這個頁面中還提供了儀表版、多種卡片、資料表格、登入頁面等等精美實用的範例" src="https://cdn-images-1.medium.com/max/1024/1*MQlTn-Bgwib50rz3xr_hPA.png" /><figcaption>在「<strong>Examples</strong>」這個頁面中提供了儀表版、多種卡片、資料表格、登入頁面等等精美實用的範例</figcaption></figure><h4>多種主題可直接套用</h4><p>除了有許多精美範例可以使用，在「<strong>Themes</strong>」頁面我們可以選擇<strong>要套用在專案中的色彩主題</strong>，並即時的看到這些主題應用在元件上的模樣。只要點選「Copy code」並將 CSS variables 的設定貼到我們的 CSS 檔案中，就套用完畢啦！</p><figure><img alt="在「Themes」頁面我們可以選擇要套用在專案中的色彩主題，並即時的看到這些主題應用在元件上的模樣" src="https://cdn-images-1.medium.com/max/1024/1*taCpGNNtoXLvNlQKjJXQww.png" /><figcaption>在「<strong>Themes</strong>」頁面我們可以選擇<strong>要套用在專案中的色彩主題</strong>，並即時的看到這些主題應用在元件上的模樣</figcaption></figure><figure><img alt="Shadcn ui Themes 中提供了完整的 CSS variables 設定" src="https://cdn-images-1.medium.com/max/1024/1*QVgIsOtZtUhEqb4KwPuPhA.png" /><figcaption>Shadcn ui Themes 中提供了完整的 CSS variables 設定</figcaption></figure><h4>結合 React Hook Form 和 Zod 的表單</h4><p>雖然 Shadcn ui 主要是建立在 Radix UI 上，但對於某些元件的處理，他仍提供了一套 <strong>opinionated</strong> 的做法。例如前端常見的 Form，在實務上通常會結合一些表單驗證 library 或是 schema validation library 來做更完善的資料和錯誤處理。</p><p>在<a href="https://ui.shadcn.com/docs/components/form">文件</a>中，他們提到一個好的表單應該具有以下幾個基本要求：合理的結構與語意、易於操作(尤其針對鍵盤使用者)、提供正確的 ARIA 屬性與標籤、支援客戶端及伺服器端驗證、風格與網頁其他部分保持一致。Shadcn ui 在這方面選擇使用 <strong>React Hook Form</strong> 和 <strong>Zod</strong> 這兩個 library 來讓它的表單元件更加 production-ready。</p><p><a href="https://react-hook-form.com/">React Hook Form</a> 是 npm 上下載次數最高的 React 表單驗證套件，提供一套簡易的 API 來讓在 React 中操作 uncontrolled components 變得更容易，若要使用第三方套件的 controlled component 也有相關的 API 能使用。RHF 更提供了完整的 resolvers 套件與超過 10 種不同的 schema validation library 做整合。</p><p><a href="https://zod.dev/">Zod</a>，根據作者的說明，是一個 TypeScript-first 的驗證、定義 schema 的函式庫。它會依據你給定的格式創造 schema，還能自動推斷出靜態的 typescript type。以表單的 schema 為例，在撰寫表單資料的相關程式碼時，就會有型別提示與自動完成的功能。它所提供的驗證 API 相當多樣化，也能輕易地客製化錯誤訊息。</p><figure><img alt="表單元件鍵盤操作範例" src="https://cdn-images-1.medium.com/max/693/1*IbMYdr4QFk1rYAc_jUtRwg.gif" /></figure><p>從上方的鍵盤操作範例可以看到，Shadcn ui 所提供的表單元件已經整合了焦點控制、錯誤訊息的顯示與錯誤狀態時的基本樣式變化，我們只需要定義好自己的 schema 並串接好 API 就能完成美觀及實用兼具的表單。</p><h4>結合 Tanstack Table 的表格</h4><p>另外一個值得一提的則是 Table 元件。從樣式設定、無障礙操作、排序過濾搜尋等等，Table 無疑是大部分前端工程師的噩夢，想到要自己從頭開始做就覺得頭痛🤯。大多數的元件庫都會提供已經做好基本功能的 Table，不過，Shadcn ui 有點不同，若仔細觀察它所提供的程式碼，Table 元件只不過是經過樣式包裝的原生 HTML 元素罷了。</p><p>但是在<a href="https://ui.shadcn.com/docs/components/data-table">文件</a>中，<strong>他們提供了簡單易懂的教學，手把手帶你整合</strong> <a href="https://tanstack.com/table/v8"><strong>Tanstack Table</strong></a>，<strong>告訴你如何定義表格欄位、樣式設定、加入分頁、搜尋、過濾等功能</strong>。Tanstack Table 本身是一個用來製作複雜表格和資料欄位的 Headless UI (前身為 React Table，不過現在整合了各框架的 package)，功能非常強大，有內建的分頁、搜尋、排序功能，並能做到高度客製化。不過必須要說的是，他們的官方文檔對於新手來說不太友善，API 的解釋都蠻簡略的，且很難找到自己當下需要的內容🥲。</p><p>幸好，Shadcn ui 提供的教學，以及 Examples 中的表格範例，已大大降低了 Tanstack Table 的上手門檻，並足夠讓人做出具有多種功能的基本表格，只需要在卡關的時刻額外搜尋資源就好。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*94koc7t_nCZ0zGll_gNusA.gif" /><figcaption>在 Examples 頁面中所提供的 Data Table 範例</figcaption></figure><h3>開始使用 Shadcn ui</h3><h4>基本安裝設定 (Vite)</h4><ol><li>以一個 <a href="https://vitejs.dev/">Vite</a> 專案為例，我們必須先開啟一個新的 Vite 專案 (其他框架文檔請往👉<a href="https://ui.shadcn.com/docs/installation">這邊</a>)</li></ol><pre>npm create vite@latest</pre><p>2. 接著下載 Tailwind CSS 以及相關的套件，並生成 config 檔案</p><pre>npm install -D tailwindcss postcss autoprefixer<br> <br>npx tailwindcss init -p</pre><p>3. 在你的 tsconfig.json 檔案中新增以下設定，確保解析元件路徑時不會出錯</p><pre>&quot;baseUrl&quot;: &quot;.&quot;,<br>&quot;paths&quot;: {<br>  &quot;@/*&quot;: [&quot;./src/*&quot;]<br>}</pre><p>4. 更新你的 vite.config.ts 檔案，確保解析元件路徑時不會出錯</p><pre># (so you can import &quot;path&quot; without error)<br>npm i -D @types/node</pre><pre>import path from &quot;path&quot;<br>import react from &quot;@vitejs/plugin-react&quot;<br>import { defineConfig } from &quot;vite&quot;<br> <br>export default defineConfig({<br>  plugins: [react()],<br>  resolve: {<br>    alias: {<br>      &quot;@&quot;: path.resolve(__dirname, &quot;./src&quot;),<br>    },<br>  },<br>})</pre><p>5. 執行 shadcn-ui CLI 指令來初始化 Shadcn ui</p><pre>npx shadcn-ui@latest init</pre><p>6. 根據需求回答以下問題以完成初始化</p><pre>Would you like to use TypeScript (recommended)? no / yes<br>Which style would you like to use? › Default<br>Which color would you like to use as base color? › Slate<br>Where is your global CSS file? › › src/index.css<br>Do you want to use CSS variables for colors? › no / yes<br>Where is your tailwind.config.js located? › tailwind.config.js<br>Configure the import alias for components: › @/components<br>Configure the import alias for utils: › @/lib/utils<br>Are you using React Server Components? › no / yes (no)</pre><p>7. 完成設定後就能開始新增元件</p><p>舉例來說以下的指令會將 button 元件檔案新增到你的 components/ui 資料夾中：</p><pre>npx shadcn-ui@latest add button</pre><p>我們可以在頁面中 import 剛剛新增的 Button 元件如下：</p><pre>import { Button } from &quot;@/components/ui/button&quot;<br> <br>export default function Home() {<br>  return (<br>    &lt;div&gt;<br>      &lt;Button&gt;Click me&lt;/Button&gt;<br>    &lt;/div&gt;<br>  )<br>}</pre><h4>設定暗色模式 (Vite)</h4><p>Shadcn ui 的所有元件都已經有內建的暗色模式的樣式設定，我們不需要再額外新增暗色模式的樣式。搭配 「Themes」中的 CSS Variables 設定，只要再加入以下幾個簡單的步驟就可以有美美的暗色模式可以用啦。</p><p>(以下以 Vite 專案為例，官方還有提供 <a href="https://ui.shadcn.com/docs/dark-mode/next">Next.js</a> 和 <a href="https://ui.shadcn.com/docs/dark-mode/astro">Astro</a> 文檔)</p><ol><li>設定 theme-provider檔案如下</li></ol><pre>import { createContext, useContext, useEffect, useState } from &quot;react&quot;<br><br>// 預設有三種模式設定<br>type Theme = &quot;dark&quot; | &quot;light&quot; | &quot;system&quot;<br><br>type ThemeProviderProps = {<br>  children: React.ReactNode<br>  defaultTheme?: Theme<br>  storageKey?: string<br>}<br><br>type ThemeProviderState = {<br>  theme: Theme<br>  setTheme: (theme: Theme) =&gt; void<br>}<br><br>const initialState: ThemeProviderState = {<br>  theme: &quot;system&quot;,<br>  setTheme: () =&gt; null,<br>}<br><br>const ThemeProviderContext = createContext&lt;ThemeProviderState&gt;(initialState)<br><br>export function ThemeProvider({<br>  children,<br>  defaultTheme = &quot;system&quot;,<br>  storageKey = &quot;vite-ui-theme&quot;,<br>  ...props<br>}: ThemeProviderProps) {<br>  const [theme, setTheme] = useState&lt;Theme&gt;(<br>    () =&gt; (localStorage.getItem(storageKey) as Theme) || defaultTheme<br>  )<br>  // 初始化的時候會依據客戶端是否有設定模式偏好來決定顯示的模式<br>  useEffect(() =&gt; {<br>    const root = window.document.documentElement<br>    root.classList.remove(&quot;light&quot;, &quot;dark&quot;)<br>    if (theme === &quot;system&quot;) {<br>      const systemTheme = window.matchMedia(&quot;(prefers-color-scheme: dark)&quot;)<br>        .matches<br>        ? &quot;dark&quot;<br>        : &quot;light&quot;<br>      root.classList.add(systemTheme)<br>      return<br>    }<br>    root.classList.add(theme)<br>  }, [theme])<br>  const value = {<br>    theme,<br>    setTheme: (theme: Theme) =&gt; {<br>      localStorage.setItem(storageKey, theme)<br>      setTheme(theme)<br>    },<br>  }<br>  return (<br>    &lt;ThemeProviderContext.Provider {...props} value={value}&gt;<br>      {children}<br>    &lt;/ThemeProviderContext.Provider&gt;<br>  )<br>}<br><br>export const useTheme = () =&gt; {<br>  const context = useContext(ThemeProviderContext)<br>  if (context === undefined)<br>    throw new Error(&quot;useTheme must be used within a ThemeProvider&quot;)<br>  return context<br>}</pre><p>2. 在 App.tsx 新增 ThemeProvider，傳入預設模式以及用來儲存主題的 storage key 名稱</p><pre>import { ThemeProvider } from &quot;@/components/theme-provider&quot;<br><br>function App() {<br>  return (<br>    &lt;ThemeProvider defaultTheme=&quot;dark&quot; storageKey=&quot;vite-ui-theme&quot;&gt;<br>      {children}<br>    &lt;/ThemeProvider&gt;<br>  )<br>}<br><br>export default App</pre><p>3. 新增 mode-toggle 元件，讓使用者在應用程式中切換模式</p><pre>// 也可以換成任何喜歡的 icon 包<br>import { Moon, Sun } from &quot;lucide-react&quot;<br>import { Button } from &quot;@/components/ui/button&quot;<br><br>// 預設的 mode toggle 元件是有下拉選單的<br>// 因此會需要載入 dropdown-menu 元件，不過可依照需求修改<br>import {<br>  DropdownMenu,<br>  DropdownMenuContent,<br>  DropdownMenuItem,<br>  DropdownMenuTrigger,<br>} from &quot;@/components/ui/dropdown-menu&quot;<br><br>// 載入剛剛在 theme-provider 中設定的 custom hook<br>import { useTheme } from &quot;@/components/theme-provider&quot;<br><br>export function ModeToggle() {<br>  const { setTheme } = useTheme()<br>  return (<br>    &lt;DropdownMenu&gt;<br>      &lt;DropdownMenuTrigger asChild&gt;<br>        &lt;Button variant=&quot;outline&quot; size=&quot;icon&quot;&gt;<br>          &lt;Sun className=&quot;h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0&quot; /&gt;<br>          &lt;Moon className=&quot;absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100&quot; /&gt;<br>          &lt;span className=&quot;sr-only&quot;&gt;Toggle theme&lt;/span&gt;<br>        &lt;/Button&gt;<br>      &lt;/DropdownMenuTrigger&gt;<br>      &lt;DropdownMenuContent align=&quot;end&quot;&gt;<br>        &lt;DropdownMenuItem onClick={() =&gt; setTheme(&quot;light&quot;)}&gt;<br>          Light<br>        &lt;/DropdownMenuItem&gt;<br>        &lt;DropdownMenuItem onClick={() =&gt; setTheme(&quot;dark&quot;)}&gt;<br>          Dark<br>        &lt;/DropdownMenuItem&gt;<br>        &lt;DropdownMenuItem onClick={() =&gt; setTheme(&quot;system&quot;)}&gt;<br>          System<br>        &lt;/DropdownMenuItem&gt;<br>      &lt;/DropdownMenuContent&gt;<br>    &lt;/DropdownMenu&gt;<br>  )<br>}</pre><h4>我的 side project</h4><p>我的第三個 side project <a href="https://github.com/KellyCHI22/Issuezy">Issuezy</a> 就是用 Shadcn ui 打造的！比起在第一個 side project 中，花了將近 1/3 的開發時間在設計和開發 UI 樣式，第三個 project 只花不到一周的時間就組裝了大部分的元件，剩下的時間就可以專注在串接功能上👌。歡迎到 Github Repo 上面參考 Readme 中的截圖，或是到 <a href="https://issuezy.netlify.app/">這邊</a> 玩玩看 Live Demo。</p><figure><img alt="Issuezy 專案截圖：桌機版 Table" src="https://cdn-images-1.medium.com/max/1024/1*0eeQcUWN8K_5uvJhaSFgbw.png" /><figcaption>Issuezy 專案截圖：桌機版 Table</figcaption></figure><figure><img alt="Issuezy 專案截圖：手機版" src="https://cdn-images-1.medium.com/max/1024/1*ssTKigaKNFhTJx4CzJ1qMQ.png" /><figcaption>Issuezy 專案截圖：手機版</figcaption></figure><h3>結語</h3><p>除了上述提到的特點，在<a href="https://blog.typeart.cc/shadcn-ui-a-game-changer/">這篇文章</a>中網友還提到 Shadcn ui 不像其他元件庫，若要使用單一元件的話就要一次導入整包 package，可以直接透過 CLI 工具新增需要的元件，並無痛整合到現有的專案中。唯一的限制大概就是專案必須使用 Tailwind CSS。</p><p>近幾年 Tailwind CSS 的崛起催生了許多建立於 Tailwind CSS 之上的元件庫 (例如本文所提到的 Shadcn-ui，還有 <a href="https://daisyui.com/">Daisy UI</a>、<a href="https://tailwindui.com/">Tailwind UI</a>、<a href="https://flowbite.com/">Flowbite</a> 等等族繁不及備載)，它易於客製化與複製的特性，還逐漸與生成式 AI 工具的風潮結合，例如 versel 所推出的 <a href="https://v0.dev/">v0</a>，可以透過指令來讓 AI 直接生成需要的元件。</p><p>就個人的使用經驗與觀察，隨著工具鍊的成熟和元件庫的擴展，Tailwind CSS 很有可能變成未來主流的 CSS 解決方案，而我也樂見其成。Tailwind 團隊在今年六月的時候還辦了一場實體 conference (<a href="https://tailwindcss.com/blog/2023-07-18-tailwind-connect-2023-recap">Tailwind Connect</a>)，就知道這股潮流只有越滾越大的趨勢。還沒有跟上 Tailwind 風潮的你，在等什麼呢？😌</p><p>(結果變成了 Tailwind 推坑文章了嗎…)</p><h4>參考資源</h4><ul><li><a href="https://ui.shadcn.com/docs">官方文檔</a></li><li>【文章】<a href="https://www.builder.io/blog/25-plus-ui-component-libraries">An Overview of 25+ UI Component Libraries in 2023</a></li><li>【影片教學】<a href="https://www.youtube.com/watch?v=DTGRIaAJYIo">The Best UI Components that EVERYONE is Using!</a></li><li>【文章】<a href="https://medium.com/@Kelly_CHI/tailwind-css-introduction-and-tools-68e770b2bf7f">Tailwind CSS 新手上路：概念、安裝與工具推薦</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6fd4f1959147" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to side project? 關於 side project 的小小經驗談]]></title>
            <link>https://medium.com/@Kelly_CHI/how-to-side-project-my-experience-65b160f331b3?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/65b160f331b3</guid>
            <category><![CDATA[side-project]]></category>
            <category><![CDATA[backend]]></category>
            <category><![CDATA[ideas]]></category>
            <category><![CDATA[frontend]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Wed, 04 Oct 2023 12:37:50 GMT</pubDate>
            <atom:updated>2023-10-04T19:42:20.901Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BW7Ira3e7xCKcku4" /><figcaption>Photo by <a href="https://unsplash.com/@medbadrc?utm_source=medium&amp;utm_medium=referral">Med Badr Chemmaoui</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><blockquote>⚠️ 寫在前面：本文寫作的主要對象是已經學習網頁開發一段時間、想要知道如何做 side project 的人，或是目前在正在找尋第一份網頁開發工作、想要透過製作 side project 來幫助求職的人。</blockquote><p><strong>目錄</strong></p><p>· <a href="#1ac6">前言: Side Project 為什麼那麼重要？</a><br>· <a href="#996d">Side Project 的靈感從哪裡來</a><br>· <a href="#7e7d">如何選擇專案使用的技術</a><br>· <a href="#0286">如何規劃專案的細節和執行</a><br>· <a href="#afea">Side Project 成果展示</a><br>· <a href="#47b8">結語</a><br> ∘ <a href="#5a81">資源整理</a><br> ∘ <a href="#9229">推薦閱讀</a></p><h3>前言: Side Project 為什麼那麼重要？</h3><p>在網頁開發領域，我常常聽到人們鼓勵工程師保持開發 side project 的習慣，畢竟工作上所用到的技術變化性不大，礙於種種考量也無法隨意在工作中應用最新最閃亮的技術。想要持續精進自己的技術能力並趕上時代的潮流(?)，就必須花時間做 side project。</p><p>對於新手更是如此，畢竟在缺乏實戰經驗的情況下，開發 side project 是求職者最佳的學習方式，也是累積經驗的主要管道。當然也有人建議參與 open source 專案，但是實際情況往往是，要對 open source 專案有程式上的貢獻，對新手來說難度仍然太高了。</p><p>目前的我也處在新手轉職階段，並完成了超過 3 個 side project。寫這篇文章的目的，是希望透過分享我的經驗來幫助到和我有類似處境的人們。(未來會繼續推出與這幾個 side project 相關的文章，我保證 XD)</p><h3>Side Project 的靈感從哪裡來</h3><p>對於想開發 side project 的人來說，最困難的一個問題應該就是：啊，可是我不知道要做什麼！</p><p>在同為 AC 畢業生的同學 Johnny 所寫的 <a href="https://medium.com/@johnnyfang_11536/side-project-ideas-5b0899225acc">side project 要做什麼？</a> 這篇文章中，提到了很多實用的發想方向，包括<strong>觀察生活中所遇到的痛點</strong>、<strong>從專業或興趣延伸</strong>、以及<strong>模仿知名網站</strong>等等，這些都是很棒的切入點。</p><p>在構思 side project 的時候，我還會去參考<strong>同樣也是 bootcamp 訓練出來的學員所做出的作品</strong>，因為在技術選擇和能力水準上基本上不會差太多，從他們的作品中可以觀察到一個作品應該要具備哪些功能、具有怎樣的完整度，才能展現出一個合格的初階工程師該有的能力。(參考 <a href="https://school.appworks.tw/outcome/">Appworks School 學員作品</a>、<a href="https://wehelp.tw/bootcamp/achievement">Wehelp bootcamp 訓練成果</a>、<a href="https://works.hexschool.io/#/">六角學院學員作品集</a>)</p><p>另外一個也常常遇到的困難點是，<strong>我不會設計，要怎麼樣才能做出不難看的 side project</strong>？我非常推薦 <a href="https://mobbin.com/browse/web/apps">Mobbin</a> 這個網站，上面集結了各式各樣已經上線的產品詳細操作截圖，對於想像自己專案該有哪些畫面或元件非常有幫助。另外像是 <a href="https://dribbble.com/">Dribble</a>、<a href="https://www.pinterest.com/">Pinterest</a> 這類網站也是蒐集設計靈感的好去處。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*TYPReCesSs0GEPtL.png" /><figcaption>Mobbin 這個網站上集結了很多上線產品的詳細操作截圖</figcaption></figure><p>當然，即便有他人的設計能夠參考，從頭開始設計也是相當耗費心力的一件事情，因此，若時間有限的話，使用像是 <a href="https://mui.com/">Material UI</a>、<a href="https://chakra-ui.com/">Chakra UI</a>、<a href="https://ui.shadcn.com/">Shadcn UI</a> 等等的元件庫也是值得嘗試的方式。我在開發第一個 side project 的時候，花了超過 1/3 的時間在設計 UI，到了第三個專案的時候決定使用元件庫，開發速度加快了三倍以上。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*TY_W7QwAEaV_Kkxg.png" /><figcaption>Shadcn-ui 提供了各種具有基本樣式和功能的原件，幫助加速前端 UI 的開發</figcaption></figure><h3>如何選擇專案使用的技術</h3><p>既然是以求職為目的的 side project，那<strong>專案所使用的技術也要盡量與業界需求有相呼應</strong>。若把公司大致上分為：接案公司、自有產品公司 (其中又分 toB or toC)，所需要的技能都會有所不同。在專案的發想階段，可以在人力平台上面瀏覽職缺訊息，掌握目前市場上需要的能力有哪些，並將提到的技術應用在專案中。</p><p>此外，side project 的目的除了是為了展現過去學習的成果之外，也不失為一個探索新技能和工具的好機會，因此，我會建議同樣是從 bootcamp 畢業的夥伴，<strong>side project 所運用的技術要比課程所教的再多推出去一些</strong>，例如，學前端的同學可以學習使用 <a href="https://firebase.google.com/">Firebase</a>、<a href="https://supabase.com/">Supabase</a> 等 BaaS (後端即服務) 平台來處理諸如使用者驗證、資料儲存的問題。或是在學完 React 之後繼續學習其他 React 生態系的工具，像是 <a href="https://redux-toolkit.js.org/">Redux Toolkit</a>、<a href="https://tanstack.com/query/v3/">React Query</a>、<a href="https://reactrouter.com/en/main">React Router</a> 等等。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fN8CtJ3gG1abSjVl.png" /><figcaption>Firebase 提供了資料庫、使用者驗證、靜態資源儲存和網頁佈署等服務</figcaption></figure><p>以我的經驗為例，我在第一個 side project 中學習了 Firebase 各項服務的使用，在還不會後端的情況下打造完整的專案；在第二個 side project (個人作品集) 中，我嘗試了一個新的框架 <a href="https://astro.build/">Astro</a>，並研究靜態網站常見的 i18n、聯絡表單等功能；而第三個 side project，則是從頭打造一個完整的全端專案，透過學習後端知識來更全面地理解網頁開發。</p><h3>如何規劃專案的細節和執行</h3><p>開始一個新的 side project 時，前期規劃是很重要的步驟。將專案目標切割成以週為單位小任務，心裡也會比較踏實，不會陷入不知道該從哪裡開始的窘境。<strong>我通常會使用像是 Notion 等筆記軟體來紀錄我的開發過程</strong>，這不但有助於保持自律，讓我能跟蹤任務和目前進度，也是記錄自己成長的一份重要文件。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*x1WmQBYgjfYMHiDB.png" /><figcaption>分門別類將想法記錄起來，並使用 task board 追蹤每週進度</figcaption></figure><p>一個很實用的指導原則是<strong>採用 MVP（Minimum viable product）的概念來思考專案的邊界</strong>。在進行開發的時候，這些想法會一再冒出來：「這裡應該可以再加一個 XX 功能」或是「這裡再微調一下就完美了」，然而，各種想法累積起來的結果就是，我們永遠無法「完成」這個專案。</p><p>MVP 意味著「最小可行產品」，它是專案的最初始版本，具有足夠的功能來<strong>實現專案的核心目標</strong>。正如現實世界中的各種產品本來就會隨著時間進行擴展與迭代，用這種方式來規劃並完成專案的「MVC」也是避免「挖太深填不了坑」的好方法。</p><p>在 AI 時代，ChatGPT 等工具已經成為開發者解決各種程式上的疑難雜症的好幫手，不過，<strong>AI 不只能幫我們解 bug，還能當我們的專案規劃助理</strong>！從最一開始的概念發想、user story 的列舉、到專案的每週進度規劃，透過和 ChatGPT 一來一往的討論，專案的雛型也呼之欲出。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sRYoORHh6zbsDzhK.png" /><figcaption>和 ChatGPT 討論專案的時程規劃和每週的目標</figcaption></figure><p>總之，規劃是開發 Side Project 很重要的一個環節。使用適當的工具和方法，可以加快前期規劃的速度，專心在功能的開發上，並確保最後能真正將專案畫下句點。</p><h3>Side Project 成果展示</h3><p>在辛辛苦苦完成 side project 後，如果沒有人能夠看到你的專案，豈不是太可惜了？因此，這邊提供幾個展示 side project 成果的方法：</p><p><strong>將專案上傳到雲端</strong>：專案的程式碼可以保存在 GitHub 或類似平台上。這樣做不僅可以讓其他人檢視你的程式碼，也確保這個專案並非從其他人的手中剽竊而來。此外，也需要將網頁或服務部屬到 <a href="https://pages.github.com/">GitHub pages</a>、<a href="https://www.netlify.com/">Netlify</a>、<a href="https://render.com/">Render</a> 或是 <a href="https://railway.app/">Railway</a> 等平台上，讓他人可以透過公開連結來看到你的網站。</p><p><strong>寫 README</strong>： <strong>一篇詳細的 README 可以讓人感受到你對專案的用心，也能節省潛在雇主實際去操作網頁的時間 </strong>(他們通常沒那個時間去創帳號還有登入)。README 的內容會包括 side project 的核心理念、demo 連結、主要功能介紹、使用指南和一些畫面的截圖。可以參考我<a href="https://github.com/KellyCHI22/Issuezy">第三個 side project</a> 的 README。</p><p><strong>整理成作品集網站</strong>： 如果有多個 side project，可以考慮<strong>將它們整理到個人作品集網站上</strong>。這樣一來，可以將所有專案集中展示給潛在的雇主或合作夥伴。而作品集網站本身也很值得當作另一個 side project 來經營 (參考我的<a href="https://kellychi-dev.netlify.app/">個人作品集網站</a>)。雖然製作個人網頁在台灣似乎沒那麼常見，但還是很推薦去<a href="https://github.com/emmabostian/developer-portfolios">這個 repo</a> 看看網友們的作品集網站。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*h_EiaJE3cfIh3End.png" /><figcaption>在作品列表中，列出專案主要技術、專案簡介、demo 連結與 GitHub 連結</figcaption></figure><p><strong>寫文章分享</strong>： 在 Medium、個人部落格或是 Linkedin 上分享 side project 的開發過程與挑戰。這有助於記錄自己在專案中的成長和反思，也是建立個人品牌和形象的機會。雖然自己可能覺得專案微不足道、沒什麼值得說的，但我信任何經驗總會有發揮它價值的一天。</p><h3>結語</h3><p>其實，在寫文章之前，我也總是在懷疑自己的經驗到底有沒有值得拿出來說的價值，畢竟就結果論來說，我到現在仍然還在求職中，所以這些經驗絕對不是什麼「必勝寶典」，只是個人對於所謂一個好的 side project 該是什麼樣子的一點 murmur。也很感謝 AC 社群同學們的提問與回饋，這讓我了解到我的經驗是有價值的。</p><p>開發 side project 是一個持續學習和成長的旅程。特別對於新手開發者來說，它是一個寶貴的學習機會，還可以讓你在求職的過程中為自己的能力背書。但它絕非一件簡單的事，需要花費好幾周甚至數月的時間，以及數不清的無助和崩潰，因此，只要最後能完成 side project，就是一個很值得慶祝的里程碑。</p><p>希望這篇文章能夠幫助到和我有類似處境的人們，並鼓勵更多人開始自己的 side project。無論你選擇開發什麼樣的專案，重要的是保持節奏與自律，並堅持到完成的那一天。歡迎處在類似情況中的朋友和我聊聊、並分享你的困難和經驗。</p><h4>資源整理</h4><ul><li>Johnny Fang — <a href="https://medium.com/@johnnyfang_11536/side-project-ideas-5b0899225acc">side project 要做什麼？</a></li><li>Bootcamp 學員畢業作品：<a href="https://school.appworks.tw/outcome/">Appworks School 學員作品</a>、<a href="https://wehelp.tw/bootcamp/achievement">Wehelp bootcamp 訓練成果</a>、<a href="https://works.hexschool.io/#/">六角學院學員作品集</a></li><li>設計資源推薦：<a href="https://mobbin.com/browse/web/apps">Mobbin</a>、<a href="https://dribbble.com/">Dribble</a>、<a href="https://www.pinterest.com/">Pinterest</a></li><li>元件庫推薦：<a href="https://mui.com/">Material UI</a>、<a href="https://chakra-ui.com/">Chakra UI</a>、<a href="https://ui.shadcn.com/">Shadcn UI</a></li><li>後端即服務平台：<a href="https://firebase.google.com/">Firebase</a>、<a href="https://supabase.com/">Supabase</a></li><li>React 生態系工具：<a href="https://redux-toolkit.js.org/">Redux Toolkit</a>、<a href="https://tanstack.com/query/v3/">React Query</a>、<a href="https://reactrouter.com/en/main">React Router</a></li><li>佈署平台：<a href="https://pages.github.com/">GitHub pages</a>、<a href="https://www.netlify.com/">Netlify</a>、<a href="https://render.com/">Render</a>、<a href="https://railway.app/">Railway</a></li><li>網友的作品集網站清單：<a href="https://github.com/emmabostian/developer-portfolios">developer-portfolios</a></li><li>三個 side project 的 README：<a href="https://github.com/KellyCHI22/HowTo">HowTo</a>、<a href="https://github.com/KellyCHI22/portfolio">portfolio</a>、<a href="https://github.com/KellyCHI22/Issuezy">Issuezy</a></li><li><a href="https://kellychi-dev.netlify.app/">個人作品集網站</a></li></ul><h4>推薦閱讀</h4><ul><li><a href="https://hahow.in/contents/articles/606d712646100a65262ed24e">你也想做 Side Project？9 個你千萬要避開的大坑</a></li><li><a href="https://tw.alphacamp.co/blog/side-project-demoday">Side Project 作品集怎麼做？程式初學者就從解決生活問題開始！</a></li><li><a href="https://tw.alphacamp.co/blog/front-end-engineer-portfolio-web-developer-job">前端作品集如何準備：7 種累積作品的方法</a></li><li><a href="https://tw.alphacamp.co/blog/backend-engineer-job-winning-portfolio">後端工程師面試必看，我該準備什麼作品集？</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=65b160f331b3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[給前端菜鳥的 15+ 個 newsletter 推薦清單]]></title>
            <link>https://medium.com/@Kelly_CHI/frontend-newsletter-recommendation-1e53e618c05a?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/1e53e618c05a</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[newsletter]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Wed, 02 Aug 2023 20:09:25 GMT</pubDate>
            <atom:updated>2023-10-31T21:54:40.578Z</atom:updated>
            <content:encoded><![CDATA[<h3>前端開發資源推薦 (二) Newsletter 篇</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/727/0*TQM6Dt2bOV62WSps.png" /><figcaption>每天都有新的 JavaScript framework 長出來</figcaption></figure><p>在變化莫測的前端領域，持續不斷的學習是非常重要的，然而，要怎麼有效地學習並跟上最新的技術趨勢是一個令人頭痛的問題。閱讀技術文章當然是不錯的方式，但是要找到真正有價值且不過時的資訊，仍需要花費大量的心力。</p><p>那到底該如何時常接收新知，而不被時代的潮流給吞沒呢？我認為，Youtube 頻道和電子報是最輕鬆的方式，因為，人家都把重點給整理好了，我們只要負責看就好 👀 以下就來看看電子報的部分吧！</p><p><em>Youtube 頻道推薦請往這邊走 ➡️ </em><a href="https://medium.com/@Kelly_CHI/recommended-frontend-youtube-channel-4c148eddbdb"><em>前端開發資源推薦 (一) Youtube 頻道篇</em></a></p><h3>Design / UI / UX</h3><ol><li><a href="https://tympanus.net/codrops/collective/">Codrops</a>: 每周一次的精選文章，配圖精美，內容包含前端新工具、UI/UX 和創意前端開發等。最喜歡他們分享的 Inspirational Website of the Week，每次都讓人大開眼界！最新一期文章還包含：Core Web Vitals for Search Engine Optimisation: What Do We Need to Know?, CSS View Transitions</li><li><a href="https://sidebar.io/">Sidebar</a>: 每天都會有五篇設計、UI/UX 精選文章或是最新實用工具資訊送到你的信箱。近期內容包含：The future of design systems is semantic, Rethinking Window Management</li><li><a href="https://heydesigner.com/newsletter/">HeyDesigner</a>: 可以選擇每日收信或是每周一次，主題包含 Product design、Design engineering、相關工具與資源分享。最新一期內容包含：The UX Cookbook, User driven UI</li><li><a href="https://codepen.io/spark">Codepen Spark</a>: 前端朋友一定都知道的 codepen 網站所推出的電子報，分享各種精選強者的 codepen 創作，身為創始人之一 Chris Coyier 也會在電子報中分享自己在設計和前端開發的新知和想法。</li></ol><h3>Frontend Development</h3><ol><li><a href="https://ui.dev/">ui.dev</a>: React 為主的課程網站，雖然沒上過他們的課程，但是他們的電子報肯定是 top notch! 用迷因化的輕鬆風格來了解 JS/React 生態系的最新發展，每週還有一個小小的測驗來考驗你的前端實力。</li><li><a href="https://webweekly.email/">Web Weekly by Stefan Judis</a>: 如果我要推出自己的電子報，那肯定會選擇類似 Stefan Judis 的風格：他不但分享精選的文章，還分享他讀過後的想法，或是為何其他人也該讀讀這篇文章。這讓電子報更個人化、更像與朋友分享資訊，並能從文字中讀到他對網頁開發的熱情。</li><li><a href="https://www.smashingmagazine.com/the-smashing-newsletter/">Smashing Magazine Newsletter</a>: Smashing Magazine 是一個蠻知名的線上出版品，專門為設計師和前端開發者提供高品質的資訊和靈感。他們的電子報每週都會選定一個主題，並分享與該主題有關的文章，近期主題包括：Figma Tools and Workflow, UX Workflow 和 Writing CSS in 2023</li><li><a href="https://gomakethings.com/articles/">Daily Developer Tips — Go Make Things</a>: Daily Developer Tips 每次都會用淺顯易懂的風格談論各式各樣的前端主題，例如 The joy of simplicity in web development、How to unit test vanilla JavaScript 等等。此外，因為著重於 vanilla 技術，對於還未接觸框架的新手來說也很容易吸收。</li><li><a href="https://frontendfoc.us/">Frontend Focus</a>: 前端知識大補帖，每次電子報的內容包含：每周精選文章、重要 update、推薦教學文章、實用工具分享等等。</li><li><a href="https://thisweekinreact.com/">This week in React</a>: React 生態圈太過紛亂總覺得霧裡看花？這個電子報幫你整理每周 React 生態系大事，讓你輕鬆跟上最新的潮流話題和 library updates！除了 React 之外也包含了 React Native 生態系的消息。</li><li><a href="https://breakpointfordevs.substack.com/">Breakpoint</a>: 在溫哥華的台灣工程師所推出的電子報，分享值得閱讀的前端開發文章，以及對文章的所思所想。</li></ol><h3>Weekly 系列</h3><p>各式各樣的 weekly newsletter 系列，以下分享最新一期 newsletter 中提到的內容。</p><ol><li><a href="https://web-design-weekly.com/">Web Design Weekly</a>: How to Adapt Long-Page Designs for Better Scanning、New Viewport Units</li><li><a href="https://css-weekly.com/">CSS Weekly</a>: State of CSS 2023、Do not drop Sass for CSS</li><li><a href="https://javascriptweekly.com/">JavaScript Weekly</a>: Good Code is Like a Love Letter to The Next Developer Who Will Maintain It、How to Build a GPT-3 App with Next.js, React, and GitHub Copilot</li><li><a href="https://nodeweekly.com/">Node Weekly</a>: Migrating a TypeScript App from Node to Bun、Node.js Toolbox: A Way to Find Node.js Packages</li><li><a href="https://tailwindweekly.com/">Tailwind Weekly</a>: 10 Tailwind Tricks You NEED To Know!、Randomness in CSS</li><li><a href="https://webtoolsweekly.com/">Web Tools Weekly</a>: 分享實用 JS 套件或開發工具</li></ol><p>以上就是我推薦給前端工程師的電子報們，這些電子報不僅提供高品質、經過篩選的資訊，有些還帶有獨特的觀點和趣味，絕對能為你的學習和開發之路助一臂之力！如果還有任何推薦的電子報，也歡迎在留言與大家分享 😀</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1e53e618c05a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[現在才是真正的起點：Alpha Camp 全學期完課回顧]]></title>
            <link>https://medium.com/@Kelly_CHI/alpha-camp-what-i-learned-in-coding-bootcamp-14382c1b541e?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/14382c1b541e</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[bootcamp]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[alphacamp]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Sun, 09 Apr 2023 15:54:14 GMT</pubDate>
            <atom:updated>2023-04-09T15:54:14.801Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FWFL8FaOaoMWhU0o" /><figcaption>Photo by <a href="https://unsplash.com/@vladbagacian?utm_source=medium&amp;utm_medium=referral">Vlad Bagacian</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>從懵懂的程式小白，到可以與後端夥伴完成有模有樣的團體專案，這七個月以來的修練，如今回想起來仍歷歷在目。推特專案結束後一週的此刻，我還是對 Alpha Camp 課程已經結束了的這件事感到不踏實，但是我相信，這段時間所鍛鍊出的思考與自學能力，會陪伴我繼續攻克未來的挑戰。</p><h3>從依樣畫葫蘆到用創意解決問題</h3><blockquote><em>在心境上，從對一切都感到陌生，到對自己開始有點信心可以完成某些小任務，再到可以準備投入職場更嚴苛的試煉，好像終於相信自己可以配得上「junior 前端工程師」這個稱號了。</em></blockquote><p>前幾個學期，我們只是依樣畫葫蘆，運用教案的內容完成一個個小課題；到了學期三，學習 React 的過程簡直像是被丟到知識的大海中，需要靠自己的力量學會游泳、甚至是造船。而我們居然也真的辦到了！在推特專案中活用知識，用力擠出創意解方突破一個個未知的問題，打造出幾乎可上線的產品。</p><p>儘管已經是一句老話，在學期三的時候我深刻地感受到「在實作中學習」真的是進步最快的方式。一路摸索 React 官方文件、在專案中實作功能、到初次與後端串接 API…沒有了教案一步步的帶領，我們必須花揮創意在有限的時間內解決問題。雖然現在已經很難細數過程中遇到的所有問題，但是我明顯地感覺到自己解決問題的速度和正確度都比剛開始學習的時候好很多。</p><p>在心境上，也從對一切都感到陌生，到對自己開始有點信心可以完成某些小任務，再到可以準備投入職場更嚴苛的試煉，好像終於相信自己可以配得上「junior 前端工程師」這個稱號了。當然，AC 的課程結束絕對不是學習之路的終點，我們只不過走完了新手村的訓練，真實的試煉還在未來等著我們。</p><h3>寫程式最重要的不是程式本身而是人</h3><blockquote><em>當初的我以為寫程式就是去記憶語法的組合，然而實際上工程師最重要的任務是「解決問題」，而所謂的解決問題則包含了解決程式的問題還有人的問題。</em></blockquote><p>當初的我也和很多人一樣以為，寫程式就是去記憶語法的組合，完成一個 todolist 就是這個指令加那個指令拼拼湊湊就結束，但實際上完全不是這樣。AC 很強調一個觀念就是，工程師的工作是解決問題，不是寫程式，(實際上很多工程師真正寫程式的時間只占工作時間的一半甚至三分之一) 而所謂的解決問題則包含了解決程式的問題還有人的問題。</p><p>學到後來會發現，同樣問題的解方可能有四五種，每一種在理論上都是正解，但是在實務上要考慮的因素有非常多。以要不要在專案中導入 B 工具的情境來說：我們的團隊夥伴對 B 工具有足夠的理解嗎？要花多久的時間上手這個工具？我們有多少的時間可以運用？在時間壓力之下要不要先使用較熟悉的 A 工具？B 工具真的會比 A 工具對我們的專案提供更多的效益嗎？</p><p>我的小組在進行推特專案時，也遇到很多需要抉擇的時刻：例如前端需要的資料和後端提供的資料格式不同時，就要考量資料格式能否從後端修改？後端是否有其他更重要的任務要進行？若有，那在資料格式不變的情況下，前端有沒有其他應變的方式？</p><p>在這些情境裡，就可以察覺「人」在這些抉擇中的重要性，每種問題都有 N 種解方，但當某解方牽涉的不只你一個人的時候，就要考量其他人的處境。在真實的專案中，除了團隊夥伴之外可能還有各式各樣的角色(競爭對手、老闆、客戶、PM…)會左右著最後的決定，反而寫程式這件事只占問題的一小部分而已。</p><p>打造一個優秀的產品絕非一個人能夠單打獨鬥完成的，而當我們需要團隊時，知道如何處理人的問題就是很關鍵的事。我很高興能在 AC 體會到這些，這是看完再多 udemy 教學影片也無法領悟到的。</p><h3>同儕讓學習之路不孤單、更有動力</h3><blockquote><em>班級制度提供大家與同學切磋的機會，很多一路從學期一到學期三的同學也慢慢在腦海中留下印象，就好像是真正在一個學校的班級裡。</em></blockquote><p>因為是在國外遠端學習，所以沒辦法像實體課程那樣和同學在現實中見面互動，但是 AC 提供的班級制度和社群都讓我在這段學習的過程中感覺到自己並非孤單一人。</p><p>班級制度提供大家觀摩同學作業、討論的機會，從這些觀摩當中學習到很多，也透過同學的心得再反過來思考自己的學習模式和經驗。很多一路從學期一到學期三的同學也慢慢在腦海中留下印象，就好像是真正在一個學校的班級裡。</p><p>學期 2–2 和學期三時都有參與讀書會，其中有同學也變成了最後推特專案的隊友。我很享受這種每周一次的聚會，能在切磋課程內容和知識的同時放心閒聊，紓解一下學習的壓力，也享受一下生活中難得可以說中文的時刻。雖然讀書會的執行方式還有待優化，但希望自己還有機會能發起其他的讀書會，發揮社群的共學精神！</p><p>除此之外還有不斷進步中的 discord 社群，隨時都有一些厲害的學長姐潛伏其中，提供學弟妹寶貴的建議，或是發起活動，真的很感謝這些雖然已經畢業但還持續在為 AC 社群付出的人！</p><h3>結語：現在才是真正的起點</h3><p>經過了七個月的學習，好像學會了很多，但我明白這只是整個領域中極其微小的一部分罷了。在任何的知識領域中，當你知道得越多，反而越會意識到自己的渺小和不足，更何況是每天日新月異的程式開發領域，永遠會有你沒看過、不懂的東西如雨後春筍般冒出。</p><p>不過，我很喜歡 React 核心團隊成員之一的 Dan Abramov 在他的文章 <a href="https://overreacted.io/things-i-dont-know-as-of-2018/">Things I Don’t Know as of 2018</a> 中所說的：</p><blockquote><em>No matter how experienced you get, you may still find yourself switching between feeling capable, inadequate, and overconfident. It depends on your environment, job, personality, teammates, mental state, time of day, and so on.</em></blockquote><p>即便像他一樣如此天賦異稟的開發者都有這麼多不懂的事，對於一個 junior 來說，「想要什麼都懂」簡直是不可能的任務。我們能做的，就是把目前的基礎踩穩，再慢慢依據興趣延伸出自己的專才。同時，保持對各種新事物的好奇心，先不要焦慮「這個我還不會」，而是去理解某個工具、語言之所以會被創造出來的原因。</p><p>總而言之，現在才是真正的起點，我們不再有明確的路標可以跟隨，而是要靠著自己的力量掌舵，航向一個個未知的挑戰，並開拓出獨一無二的旅程。不管是與我一同畢業，或是還在學習路上的學弟妹們，大家共勉之！</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/694/1*koqvGxVhvG0fUsKvPAxClg.png" /></figure><h4>其他 Alpha Camp 課程回顧心得…</h4><ul><li><a href="https://medium.com/@Kelly_CHI/alpha-camp-session-1-review-9c11065754fb">我在coding的路上：Alpha Camp 學期一回顧</a></li><li><a href="https://medium.com/@Kelly_CHI/alpha-camp-2-2-review-fc98bda0885c">不只是寫 code：Alpha Camp 學期 2–2 回顧</a></li><li><a href="https://medium.com/@Kelly_CHI/alpha-camp-simple-twitter-reflections-5455bcc57bd9">協作初體驗：Alpha Camp 期末推特專案回顧</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=14382c1b541e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[協作初體驗：Alpha Camp 期末推特專案回顧]]></title>
            <link>https://medium.com/@Kelly_CHI/alpha-camp-simple-twitter-reflections-5455bcc57bd9?source=rss-f907fafd4899------2</link>
            <guid isPermaLink="false">https://medium.com/p/5455bcc57bd9</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[teamwork]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[twitter-clone]]></category>
            <dc:creator><![CDATA[Kelly CHI]]></dc:creator>
            <pubDate>Sat, 08 Apr 2023 21:21:19 GMT</pubDate>
            <atom:updated>2023-04-08T21:21:43.218Z</atom:updated>
            <content:encoded><![CDATA[<h3>前言</h3><p>前一天還在想著搞懂 HTML、CSS 和 JS 之間的互動，沒想到轉眼之間就走到這個最後的大魔王關卡，要在短短兩周內用才剛學沒多久的 React 框架打造出完整的網頁。七個月學習成果在此見真章，雖然學習的一路上都還算順利，但真正要面對規模更大的專案時，我還是緊張焦慮了好幾晚。心想著，我們真的能辦到嗎？</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*T6Ouq7ycr7mePyQV.png" /><figcaption>首頁截圖</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Wh7og7X3yEkVvIZz.jpg" /><figcaption>手機版截圖</figcaption></figure><h4><em>什麼是推特專案？</em></h4><p>推特專案是 Alpha Camp 學期三最後的畢業團體專案，分為前後端協作以及全端開發兩種模式。我們需要在短暫的兩周期限內打造出可以進行登入、發文、回覆、追蹤、換頭像等功能的仿推特網頁。全程依據真實企業內的開發模式進行，包含 scrum 流程的導入、前期 acceptence criteria 規劃、專業的 Figma 設計稿、後端測試檔案、技術主管驗收…這些都讓我們得以體驗真實世界中的開發模樣。</p><h3>專案準備期</h3><p>我的小組是以前後端分離的模式進行開發，前端成員有我、夥伴 weii，還有兩位後端夥伴 Frank 和 Wei，其中前端所使用的主要技術為 React 和 styled components。此外，因為我們的成員散落各地，所以是以全線上遠端開發為主。</p><p>在開發正式開始之前，我們就針對各種面向進行了討論，包括要使用哪個平台作為團隊的主要協作空間 (我們選擇了 Notion)、git 分支和 commit 的命名規範、每日 standup meeting 的時間、每次 sprint 需要繳交的內容、前後端需要哪些文件以便溝通等等。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KsmGo51VrXAd8pQH.png" /><figcaption><em>小組共同討論的 acceptence criteria 清單</em></figcaption></figure><p>前端內部的文件我們也花了些時間討論，包含元件如何切分、元件資料規劃、前端環境設置、切版的規範等等。雖然規劃稱不上十全十美，但這些前期的準備也讓我們的開發順利很多。經過討論後，我是負責與主頁面相關的切版和功能 (包含推文、回覆、個人頁)，夥伴 weii 則是負責登入、帳戶設定以及後台的相關切版和功能。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PBtDPNExt1T8pK4h.png" /><figcaption><em>前端元件資料分析簡報：這個簡報也是前期與後端溝通理想資料格式的重要文件</em></figcaption></figure><h3>專案進行過程</h3><p>由於和前端夥伴 weii 從學期 2–2 讀書會的時候就已經認識，幾乎不用太多溝通磨合就可以著手開發，另外也因為我和其他人有七小時時差的關係，開發變得像是一場接力賽，weii 開發完後會跟我說她進行了哪些部分，遇到哪些問題，當我們一同解決問題後，我會繼續進行其他部分的開發，睡覺前再發 PR、留言跟她說明我的進度。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/987/0*-vJcZux1HjmnMLmy.png" /><figcaption><em>前端 task list 列表，分為基本、次要、優化三個優先等級</em></figcaption></figure><p>頁面和功能分工拆得明確、加上有時間差，我們在開發的過程中幾乎沒有遇到任何 conflit，彼此的成果也是順順的就合併在一起。</p><p>和後端夥伴的合作也沒有遇到太多的阻礙，每日的 standup meeting 我們都會互相分享各自的進度，並提醒目前實作的優先順序。依照學習教練的提醒，我們也在第五天就完成了前後端部屬和初次的串接，看到前後端 api 順利串接成功的那一刻，真的是無比的感動！</p><p>比起學長姊在心得中提到的種種困難，我們組開發之順暢讓我懷疑我們是不是有甚麼神明在默默保佑。</p><h3>專案後期</h3><p>在開始專案的一週後，後端組的開發差不多就已經告個段落，開始進行優化並根據前端的需求調整 api 回傳資料格式，前端則是持續在進行 api 串接和功能實作的部分。到了第二周的第三天左右，前端的基本功能也都順利串接和實作完成，開始進行細節修正和優化。</p><p>由於時間還算充裕，所以我們也實作了手機板的樣式，確認網頁在不同螢幕大小都不會發生破版的問題。週四進行了 sprint #3 的 demo，操作過程都很流暢也沒有太多問題需要修正。最後，周五的我們寫完 README 並確認 acceptence criteria 都達成後，就在第二週週末小小休了個假，放鬆這兩周以來緊張的情緒。</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*e_9H6LR5dl4k0eyq.png" /><figcaption><em>Demo 操作順序演練</em></figcaption></figure><h3>開發過程反思</h3><h4>寫程式不是重點，人才是</h4><p>這次合作的經驗讓我很深刻的體會到，工程師這份工作絕對不是只有自己埋頭苦幹寫出一行行程式碼而已。</p><p>例如在選擇要使用哪個工具來進行樣式的開發時，考慮到夥伴需要額外時間上手 Tailwind CSS，且 Tailwind 的明顯缺點尚不確定該如何解決，最後決定使用我們兩個都熟悉的 styled components 進行樣式開發。另一個例子是，當前端發現後端 api 所提供的資料格式並不完全符合需求時，到底是要自己想辦法調整元件設計還是去要求後端夥伴修改資料格式？</p><p>在真實的專案中，除了時間壓力、團隊夥伴之外可能還有各式各樣的角色 (競爭對手、老闆、客戶、PM…) 會左右著最後的決定，反而寫程式這件事只占問題的一小部分而已。</p><h4>前期準備的重要性</h4><p>我認為我們這組之所以會如此順利的原因，很大一部分是由於前期準備的完善，包含前後端如何溝通、需要哪些文件，以及前端自己的內部分工和規範，我們都事先準備好並隨著實作的過程不斷調整。當這些文件都齊全時，花在開會、理解彼此的時間會下降很多，只要確認任務和方向後就能專心開發。</p><p>當然，也有很大一部分是出於幸運，遇到溝通合作都非常順利且有一致目標的隊友們，在前期的討論我們就找到了適當的合作方式，遇到問題時也都很積極地去思考解決方案，之後到職場上未必會這麼幸運呢！</p><h4>可以優化的地方</h4><p>因為沒有進行過類似的專案，其實對於預估任務所需時間這件事是非常不確定的。例如前期為了趕工，並沒有將手機板的樣式放入規劃中，導致後來撰寫手機版樣式時，修改較不方便，若能早點知道我們其實有充裕的時間，可以將手機板樣式先實作完成，遵從 mobile-first 的準則。</p><p>另外，挑戰功能的部份我們也沒有在兩周的專案時間內完成，雖然專案完成後的下週有嘗試進行挑戰功能開發，但最後決定只做到公開聊天室的部分。一方面是經過兩周的開發後大家有點疲乏了，沒有明確的任務進程，導致開發變得比較鬆散，一方面是還有其他作業要趕工，只能先把挑戰功能放一邊。</p><h3>結語</h3><p>從一開始的焦慮不安、擔心是否能如期完成，到後來提前完成、還有時間跑去休假，這短短兩周的推特專案就像是跑了一場有高低起伏的馬拉松，雖然有難搞的陡坡，但每天還是穩穩地往前進。在打字的當下，開始有點懷念每天早上打開 github review 隊友的 PR，接著打開 vscode，git fetch 最新進度然後 git branch 開始努力燒腦完成一個個功能的日子。儘管這麼高度緊繃的狀態如果變成常態會對身心造成負面影響，但短期的合作與衝刺還是一場難能可貴的體驗。</p><h4>致謝</h4><p>兩周的開發過程中，真的很感謝我強大的夥伴們，首先是前端的 weii 擔當全組 PM 的角色，協助規劃與檢視每次 sprint 需要繳交的內容和擔任前後端的橋梁，如果沒有妳，我們的開發一定不會如此順利。此外，從學期 2–2 讀書會以來就培養的默契，也讓我們的溝通非常順暢、不用太多的解釋就可以完成合作目標。(給妳一個大愛心)</p><p>也要謝謝兩位後端夥伴 Frank 和 Wei，總是能在前端提出需求、或是發現問題後超快速地修正，製作的 API 文件也都寫得很清楚明瞭，讓前端開發沒有什麼後顧之憂！</p><p>此外還要特別提及學長姐所留下的文件和心得，這些寶貴的經驗都變成了我們進行任務時的養分，你們的無私分享真的幫助我們很多！總之，很感謝我的夥伴們還有 AC 學長姐、團隊，陪我走完這趟旅程的最後一個挑戰！</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5455bcc57bd9" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>