重新整理 Pan.blog……

把 pan.blog 重新翻新了一下,主要是: 換成 Hugo,提升編譯速度 圖床放到 CDN 上,不跟 GitHub 放在一起了 其實 pan.blog 我前一陣子就想重新整理了,只是一直沒有動力來做。 不過 ChatGPT 開始支援 Web Search,讓我覺得「把文章寫在 Google 可以索引的地方,之後也能幫到自己」, 再加上 X 的走向讓人不太樂觀,所以我打算把一些有價值的東西用 Blog 的方式留存。 這個新 Blog 有把一些我覺得值得留存的東西從老的 Hexo 站移過來,之後也會寫一些技術短篇~

November 22, 2024 · pan93412

從個人網站學習專案管理的方法論

背景 最近在做一個有簡歷功能的個人網站。 大學的網頁課程要上傳一個 styled 的 profile。起初兩週我想了許多種方案,比如「直接把之前超前進度的作業1 改成亮色系,然後繳出去」、「用 ChatGPT 幫我寫一份 styled 的網頁。」但我覺得都太敷衍,再加上當時有一些事情要處理,所以我就先放著——直到繳交前 3 天。 繳交前夕,我突然有個打算:「要不要試著超前上課進度2?」如果作業還繼續用 Vanilla JS 也實在太沒有新意,而且我這時突然想到一個很有意思的主意:做出一個可以分享給別人(也方便自我介紹)的簡歷。 我面試的時候常常被問到「你的作品集在哪裡」、「你的簡歷在哪」。我是有個人形象頁面,但幾乎沒有說明自己的經歷:這也就導致沒有人——包括我自己——知曉我究竟參與了哪些專案、製作了哪些 projects,以及設計了什麼東西。如果能藉由這次作業的機會打造出一個可以分享給別人(也方便自我介紹)的簡歷,那肯定會讓這個作業更有價值。 「做一個好看的簡歷網站」和「用現代前端工程標準製作專案」,便成為這個專案的兩大目的。 「滾動式開發」:逐步趨近完美 專案本身沒有用到傳統意義上的敏捷開發,但我在這個專案實踐了一些敏捷開發的「滾動式」精神。 「滾動式」的概念其實就是「慢慢達成趨近完美」:應該要先專注在核心的部分(比如這次的專案就是以個人介紹為核心),然後再慢慢地把其他的東西(比如作品集、開源貢獻)加進去。重構也是:一開始不用追求到完全的 best practice——細節可以留待日後再來改善,但如果為了細節而導致核心部分的缺失,便是本末倒置。 時間安排的重要性 雖然這麼說,但我仍然想追求完美主義:我很討厭承認一個長得超醜、超難維護的 snippet 是我寫的,我希望可以帶給閱聽者極其完美的體驗。正是因為如此,這次的作業依然是花了相當多的時間重構。可是比起細節,內容的完善明顯比較重要——更何況我因為這個 project 荒廢了太多其他的事情,排除掉學習到的經驗,投入的時間成本其實早就超出了這個專案可以帶來的價值。 **「時間安排」,在無論是在專案管理、還是日常生活的方方面面都十分重要。**安排任務的優先級、並且專注在完成最核心的事情,為專案的管理之道。我覺得我時間管理一直都做得不太好——想法太多,時間卻是有限的——是時候逼迫自己從無限的想法中切分,而不是讓一個想法佔據掉太多的時間。 勇於發問,明白自己的不足 寫網站的時候我就有和好幾位朋友共同研討「如何做出舒適的設計」,並且共同討論如何做出優秀的動效設計。這次我就和一位有著不小聲望的專業前端工程師和設計師,共同討論網頁每一處細節的設計。 另外,網站在開發後期也有遇到以及在遇到效能問題時與幾位更專業的前端工程師共同查出問題。在網頁撰寫末尾,我就有遇到一個很嚴重的效能問題:滑到卡片的時候會嚴重掉幀,但 Profile 裡面並沒有指出具體是哪個函數導致問題。後來和朋友討論之後,鎖定是 shadow 動效導致的問題,而在解決之後,效能問題也就臨刃而解。 不要過度工程化 (over-engineering) 之前看過一篇文章,說:「Best Practice 是總結出來的,不代表一開始就得導入這些東西。」工程更像是事情在遇到事情或需要擴充時的解決方法,而不是在沒必要的時候就無止境導入的玩意。 另外,不完美是難免的:像是我的 codebase 就重構了數次,即將發起的一次是發現自己違背了 Tailwind CSS 的 Atomic CSS 理念,打算全數改回 Component 的形式。重構是個學習,不要害怕不完美——不完美才能學習,學習才能成長。 目前 App 還會繼續改進的地方 除了上面提到的 bad smell 之外,我還打算加上一些更多 GitHub 的元素(比如個人的貢獻狀況、以及貢獻圖表)。不過把 bad smell 做完之後應該就是直接 promote 然後暫時放著了——有更多更重要的專案得做啊。 ...

December 16, 2022 · pan93412

什麼時候該引入 Lockfile?

原文撰於 Twitter。 撰文初衷 第一次看到沒有 commit package-lock.json 的 repo TL;DR 事實上這樣在 library 上沒有什麼問題。Lockfile 的追蹤有個小原則: 應用程式建議追蹤 lockfile:不追蹤,下次 npm install 就無法確定具體的依賴版本是什麼。 函式庫可以不用追蹤,因為使用者安裝套件時,套件管理器會根據依賴自動選取最適合的版本,而你自己的 lockfile 會被忽略1。不過建議追蹤,見下文。 函式庫「該不該」追蹤 lockfile? 假如函式庫有用到諸如 ESLint 的工具,追蹤一下可以避免之後設定開發依賴的麻煩, 所以像 NPM 官方就是推薦 無論如何都追蹤 lockfile。 不過也有預設不推薦在 library 情境下追蹤 lock 的例子,比如 Rust 的 Cargo 套件管理器2。不過 Cargo 的開發工具主要都是作為 submodule 安裝在系統中,通常不會跟著 repo 一起追蹤,所以不太適合放在一起比較。 不過要注意:這時候的 lockfile 就不是追給下游應用程式看的,主要是為了自己開發方便。 為什麼「應用程式」就該追蹤 lockfile? package.json 通常不是描述固定的版本,而是一個版本區間:舉個例子:你可能在 package.json 裡面描述 vue: "^2.4.0",但實際上 NPM 幫你選了 2.7.13。這個行為是可以預測的,可以參考 NPM 官方的 Semver 計算機:https://semver.npmjs.com。 ...

October 18, 2022 · pan93412

#Mac #軟體 威注音 v2.8.5:比原廠注音更智慧、比競品更好看的注音輸入法

原文撰於 Dcard。 Abstract 「威注音」是一款主打智慧 🤖、美觀 🎨、高自訂性 🔧,且追求完美  的注音輸入法。正在為錯字百出的選字、操作習慣、簡體輸入,甚至是原廠注音遲遲不修正的 bug 所苦嗎?威注音或許可以讓你對注音打字改觀 🥳。 威注音自己覺得有八個值得你使用的理由(建議搭配宣傳海報閱讀): 最佳化打字體驗 ⌨️ 還再打出錯字擺出的句子,成為朋友對話之間的笑柄、公司討論之間的尷尬嗎 😅?或許你可以試試看威注音輸入法。 威注音輸入法的詞庫收錄了三千餘條(且持續增加中的)常用詞組,因此輸入常用詞彙時可以減少選字的次數 🙌🏼。 目前威注音的詞庫仍在持續更新、拓展,因此威注音將會變得愈來愈智慧。如果你有任何想納入官方詞庫的常用字彙,也可以在這篇底下(或到 GitHub 下)留言提議加入~ 可以自訂語彙 💬 覺得每次輸入自己或朋友的名字,或者是科系名稱都得選字很煩嗎?威注音提供了一套非常簡單的自訂詞彙新增方式,簡而言之就是「選字後選取,按 Return 存檔。」可以看看下方影片的操作: 原生繁簡輸入、零轉換 蘋果內建的輸入法「不支援簡體輸出模式」——想像每次跟對岸朋友洽談事情,每一句都得使用特色選單裡面的簡體轉換功能轉換 😱……就算你不煩,觸控板應該也挺累的 😰。 威注音除了提供原生的簡體輸出模式,輸出簡體只要切換輸入法即可一步到位之外,威注音的詞庫也是簡體中文與繁體中文各自一份的:方便簡體中文母語者「在不熟悉台澎金馬的審音與習慣讀音的前提下」也可以順利使用威注音敲字。 P.S.: 威注音的繁體中文輸入模式可以使用「轉換至康熙繁體」「轉換至 JIS 繁體」功能。 精緻選字窗(框) 我覺得這是威注音和其他競品比較下的最直觀第一感受了。當其他競品的選字窗還停留在 Windows XP 的土裡土氣、甚至沒有暗色模式的時候;威注音的選字窗已經和蘋果原生相當相似,甚至可以啟用「IMK 選字窗」來得到和原生注音同款的介面效果 🧑‍🎨。 IMK 選字窗可以在威注音的「開發道場」開啟。不過威注音自己做的田所矩陣選字框,我覺得已經很接近蘋果的 UI 效果了。 極高自訂、可玩性 你想用 Shift 切換中英文嗎?預設開啟 🎉;你只想用「中/英」切換鍵切換語言嗎?也可以關閉 Shift 的切換。 你想要輸入罕見到原廠注音打不出來的字嗎?威注音可以讓你啟用「CNS11643 全字庫」,在安裝正確字體後即可直接打出符合政府編碼標準的罕見字 🎉。 覺得選字窗的候選字太小,看不清楚嗎?威注音支援把選字窗文字放到原先 6 倍大 (96px) 的大小 🎉。 ...

October 2, 2022 · pan93412

The comparison of Linter and Formatter

Motivation src: https://twitter.com/bystartw/status/1568217424658583553?s=61&t=UVzhpuQaGcgZkGpySz_yVQ Noticing some developers are confused with “Linter” and “Formatter,” I made a simple figure showing what messages Linter and Formatter prefer to print. Thanks to @nonoesp for his incisive introduction to Linter and Formatter!

September 9, 2022 · pan93412

vChewing 出了 2.4.0 SP2 了!

src: https://twitter.com/bystartw/status/1567200310430662656?s=61&t=UVzhpuQaGcgZkGpySz_yVQ vChewing 出了 2.4.0 SP2 了!🎉 自己覺得 vChewing 是除了官方注音之外,長得最好看(因為有 IMK 加持),而且功能跟選字功能也很棒的輸入法,真的很推薦想嘗試第三方輸入法的朋友試試看!(連結見引文) Figure 1: vChewing 提交很活躍! 資安疑慮 另外關於 vChewing (下稱 vC) 的資安或隱私疑慮: vC 在 2.3.0 之後引入 Apple 官方的沙盒機制,因此只要你沒有授予授權,輸入法本身是看不到你的資料夾的。 雖然我沒有完全閱讀 vC 的 src,但至少它的 Shift 是靠旁敲的方式偵測的,不是記錄所有鍵盤輸入 vC 只有更新和網站相關有連到個人站台 稽核方式 如果有興趣稽核 vChewing 外連的情況,可以自己 clone 回來用 regex 查,或者是直接用這個第三方網站看: sourcegraph ** 如果還是信不過(認為作者會混淆連結)的話,也可以自己掛一個抓包軟體偵測 vC 的所有請求啦…… 雖然我是找不到除了更新以外的請求 code:sourcegraph

September 7, 2022 · pan93412

善用 Swift 的字串擷取功能簡化 I18n 流程

撰文原由 在 威注音 2.1.0 SP1 的更新日誌 下看到了這麼一段話: Interface Builder 給每個標籤的命名都是隨機的,手動改起來又低效又容易改壞,對多語言本地化而言簡直是天災。 事實上在 WWDC21 中,Apple 就為 Xcode 推出了一項可以解決這項痛點的新功能:「使用編譯器擷取字串」。與早期透過從 Swift 原始碼拉取可翻譯字串,經常漏掉一些字串的方式不同——這個功能會先編譯原始碼,然後從編譯出的檔案中判斷可以翻譯的字串。 啟用功能 這項功能在新專案是預設啟用的,但舊專案可以 opt-in:點開專案設定,進入 “Build Settings”,展開所有功能(All),尋找 “Swift” 然後找到 Localization 的 “Use Compiler to Extract Swift Strings”,將其設定為 Yes 即可。 匯出字串 開啟之後的國際化與本地化方式,跟先前會不太一樣。以往需要手動改 strings 檔案,現在可以先到 “Product” > “Export Localization…” 匯出編譯器擷取出的所有字串: 接下來指定匯出的路徑,然後等待 Swift 完成編譯並擷取字串。若是從舊專案 opt-in,擷取字串的過程中可能會拋出一些錯誤,這個時候就得修正(如果只是警告的話也可以忽略): 翻譯流程 接下來就可以進入選擇好的資料夾,使用 Xcode 點開對應語系的 xcloc 檔案: ...

August 27, 2022 · pan93412

Rust for everything

src: https://redd.it/wllpa4 (https://t.me/programmer_humor/38462) low-level programming Rust game development Rust high performance code Rust scientific programming Rust machine learning Rust front-end web development Rust back-end web development Rust You only need ONE languages for everything: Rust. You don’t need more.

August 12, 2022 · pan93412

文科生也能懂的 Rust async 机制

背景 https://twitter.com/repsiace/status/1554103778994900992/ 修改一下:work stealing, thread-per-core, waker, mpsc, task queue 只有他们懂… 正常人不可能看懂 – @twicemoemoe, 22-08-02 作为一个文科生,其实觉得 async 真的没有想象中的这么困难 ⋯⋯ 😂 或许搭配一些图片会好懂很多吧。 TL;DR 不废话版本 Sync(同步):一件事情做完之后,再做下一件事情。 blocking(堵塞):指“等一件事情”的行为。 Async(异步):一件事情还没完成,可以做其他不冲突的事情。 concurrency(并发):程序 架构 中,各个任务可以 独立运行 的特性。 future:Rust 中的一个异步任务的表示。 polling:不停地询问任务,确认事情是否已经完成。 event-driven:事情完成后,任务自己发通知表明完成。 parallelism(并行):同时 运行 数个程序的行为。 thread(线程、线程):系统进程(任务集)的基本单元。thread 通常是交由 CPU 内核运行。 spawn(生成):指产生 thread 的行为。 thread pool(线程池):将 thread 高效分配给每个任务的地方。 Async runtime: 以 tokio 为例 join (macro):并发运行 async 函数,并在全部完成后回传。 select (macro):哪个 async 函数快,回传那个 async 函数的结果。 main (attribute macro):在 main() 初始化 runtime。 block_on:在 sync 上运行 async 函数。 spawn:并行运行 async 函数。 spawn_blocking:在异步函数里面,为一个高耗时且同步 (blocking) 的函数另辟新线程 (thread)。 同步 (Synchronous) 跟异步 (Asynchoronous) “同步”就是整个程序等一件事情完成(blocking,堵塞)。“异步”则是一件事情还没完成,可以做其他不冲突的事情。 ...

August 7, 2022 · pan93412

文組也能懂的 Rust async 機制

背景 https://twitter.com/repsiace/status/1554103778994900992/ 修改一下:work stealing, thread-per-core, waker, mpsc, task queue 只有他们懂… 正常人不可能看懂 – @twicemoemoe, 22-08-02 作為一個文組,其實覺得 async 真的沒有想像中的這麼困難 ⋯⋯ 😂 或許搭配一些圖片會好懂很多吧。 TL;DR 不廢話版本 Sync(同步):一件事情做完之後,再做下一件事情。 blocking(堵塞):指「等一件事情」的行為。 Async(非同步):一件事情還沒完成,可以做其他不衝突的事情。 concurrency(並行、併發):程式 架構 中,各個任務可以 獨立執行 的特性。 future:Rust 中的一個非同步任務的表示。 polling:不停地詢問任務,確認事情是否已經完成。 event-driven:事情完成後,任務自己發通知表明完成。 parallelism(平行):同時 執行 數個程式的行為。 thread(執行緒、線程):系統處理程式(任務集)的基本單元。thread 通常是交由 CPU 核心執行。 spawn(生成):指產生 thread 的行為。 thread pool(執行緒池):將 thread 高效分配給每個任務的地方。 Async runtime: 以 tokio 為例 join (macro):並行執行 async 函數,並在全部完成後回傳。 select (macro):哪個 async 函數快,回傳那個 async 函數的結果。 main (attribute macro):在 main() 初始化 runtime。 block_on:在 sync 上執行 async 函數。 spawn:平行執行 async 函數。 spawn_blocking:在非同步函數裡面,為一個高耗時且同步 (blocking) 的函數另闢新執行緒 (thread)。 同步 (Synchronous) 跟非同步 (Asynchoronous) 「同步」就是整個程式等一件事情完成(blocking,堵塞)。「非同步」則是一件事情還沒完成,可以做其他不衝突的事情。 ...

August 7, 2022 · pan93412