├── .gitignore ├── web └── README.md ├── _config.yml ├── network ├── README.md ├── 03-router.md ├── 04-switch.md ├── 06-static-route.md ├── 08-data-plane-and-control-plane.md ├── 01-ca-certificate.md ├── 07-dns.md └── 05-vxlan.md ├── python ├── README.md ├── 02-serial-number.md └── 04-uv.md ├── svelte ├── images │ ├── change-duplicate-code-fragment-01.png │ ├── change-duplicate-code-fragment-02.png │ ├── change-duplicate-code-fragment-03.png │ └── change-duplicate-code-fragment-04.png ├── 18-miscellaneous.md ├── 10-animations.md ├── 15-context-api.md ├── 20-global-state.md ├── 19-webstorm-settings.md ├── 08-motion.md ├── 11-actions.md ├── 21-dynamic-attributes-component.md ├── 02-props.md ├── 17-module-context.md ├── 14-component-composition.md ├── 01-reactivity.md ├── 06-lifecycle.md └── README.md ├── .markdownlint.json ├── git ├── README.md ├── 05-revert.md ├── 04-reset.md ├── 01-config.md ├── 02-stash.md ├── 06-update-from-original-repo.md ├── 03-angular-commit-message-format.md └── 07-revert-merged-commit.md ├── linux ├── README.md ├── 07-sockets.md ├── 05-last.md ├── 03-ram-disk.md ├── 04-file-and-directory-permission.md ├── 06-disk-command.md └── 01-lsof.md ├── aws ├── 09-aws-shield.md ├── 13-x-ray.md ├── 19-sns.md ├── README.md ├── 23-cloudtrail.md ├── 29-sts.md ├── 10-firewall.md ├── 03-region-and-availability-zone.md ├── 08-certificate.md ├── 21-cloudfront.md ├── 14-auto-scaling-group.md ├── 12-api-gateway.md ├── 01-aws-cli.md ├── 07-route53.md ├── 16-storage.md ├── 28-coe.md ├── 22-cloudwatch.md ├── 18-sqs.md ├── 26-sigv4.md ├── 04-elastic-load-balancer.md ├── 24-ecs.md └── 11-vpc.md ├── fitness ├── README.md └── 01-fat-loss.md ├── database ├── README.md ├── 01-master-data-and-transcation-data.md ├── 06-check.md ├── 05-languages.md ├── 07-foreign-key.md ├── 08-isolation-level.md └── 02-generated-columns.md ├── azure ├── README.md ├── 05-service-principal.md ├── 06-data-explorer.md ├── 08-private-link-service.md ├── 07-policy.md └── 02-blob-storage.md ├── docker ├── README.md ├── 03-prune.md ├── 05-proxy.md ├── 08-logging-drivers.md ├── 06-custom-command.md ├── 02-build.md ├── 04-noninteractive.md └── 07-mount.md ├── cloudflare ├── README.md └── 01-november-2025-outage.md ├── fluent-bit ├── README.md ├── 01-send-log-to-the-cloud.md └── 02-buffering-and-storage.md ├── google-cloud-platform ├── README.md ├── 02-projects.md └── 03-service-account.md ├── php ├── README.md ├── 02-deploy-laravel-on-ubuntu.md ├── 02-static-analysis.md ├── 04-shell-exec.md ├── 05-install-php.md ├── 08-phpstorm.md ├── 06-install-local-packages.md └── 01-swoole-confuse.md ├── laravel ├── README.md ├── 06-laravel-pennant.md └── 05-defensive-laravel.md ├── windows ├── README.md └── 02-set-alias.md ├── github ├── README.md ├── 02-outputs.md ├── 03-markdown-syntax.md └── 04-use-schedule-to-bakcup-postgresql.md ├── terraform ├── README.md └── 02-time-rotating.md ├── warp ├── 01-install.md ├── README.md ├── 04-starship-integration.md ├── 03-feature.md └── 02-theme.md ├── vim ├── 02-console.md ├── 03-map.md └── README.md ├── pest ├── README.md ├── 13-parallel.md ├── 05-custom-function.md ├── 09-groups.md ├── 02-ide-plugin.md ├── 10-exception.md ├── 04-refreash-database-trait.md ├── 06-faker.md ├── 11-skip.md ├── 01-installation-and-setup.md └── 03-lifecycle-hooks.md ├── grafana ├── README.md ├── 03.promql.md └── 01-node-exporter.md ├── zed └── README.md ├── rust ├── README.md ├── 05-comment.md ├── 21-common-collection.md ├── 41-interior-mutability-pattern.md ├── 02-variable.md ├── 32-control-how-tests-are-run.md ├── 37-box.md ├── 16-package-and-crates.md ├── 15-if-let.md ├── 40-reference-counted-smart-pointer.md ├── 20-separating-modules-into-different-files.md ├── 04-function.md ├── 39-drop.md ├── 36-thiserror.md ├── 27-panic-or-not-panic.md └── 09-slice.md ├── typescript └── README.md ├── ansible ├── README.md ├── 05-handlers.md ├── 07-template.md ├── 03-variables.md ├── 06-set-fact.md ├── 02-playbooks.md └── 04-conditionals.md ├── tailwind-css ├── README.md ├── 01-rounding-corners-tips.md └── 02-make-button-bigger-in-mobile.md ├── k8s ├── 03-roloader.md └── README.md ├── argocd └── 01-resource-hooks.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | .zed/ 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 24 5 | --- 6 | 7 | # Web 8 | 9 | 記錄網路相關知識。 10 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: just-the-docs/just-the-docs 2 | title: Allen's Note 3 | description: Record the learning 4 | color_scheme: dark 5 | -------------------------------------------------------------------------------- /network/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 10 5 | --- 6 | 7 | # Network 8 | 9 | 紀錄網路相關知識。 10 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 17 5 | --- 6 | 7 | # Python 8 | 9 | Python 相關的筆記 10 | -------------------------------------------------------------------------------- /svelte/images/change-duplicate-code-fragment-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilanboy/note/main/svelte/images/change-duplicate-code-fragment-01.png -------------------------------------------------------------------------------- /svelte/images/change-duplicate-code-fragment-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilanboy/note/main/svelte/images/change-duplicate-code-fragment-02.png -------------------------------------------------------------------------------- /svelte/images/change-duplicate-code-fragment-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilanboy/note/main/svelte/images/change-duplicate-code-fragment-03.png -------------------------------------------------------------------------------- /svelte/images/change-duplicate-code-fragment-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilanboy/note/main/svelte/images/change-duplicate-code-fragment-04.png -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD033": { 3 | "allowed_elements": ["img"] 4 | }, 5 | "MD013": false, 6 | "MD024": false, 7 | "MD026": false 8 | } 9 | -------------------------------------------------------------------------------- /git/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 20 5 | --- 6 | 7 | # Git 8 | 9 | 紀錄 Git 的一些使用方法與團隊上該如何使用 Git 進行協作。 10 | -------------------------------------------------------------------------------- /linux/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 11 5 | --- 6 | 7 | # Linux 8 | 9 | 紀錄一些 Linux 的實用指令與 Debug 日常。 10 | -------------------------------------------------------------------------------- /aws/09-aws-shield.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 9 5 | --- 6 | 7 | # AWS Shield 8 | 9 | AWS Shield 可以用來保護網站避免 DDoS 攻擊。 10 | -------------------------------------------------------------------------------- /fitness/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 28 5 | --- 6 | 7 | # Fitness 8 | 9 | 最近想認真開始健身與減脂,紀錄一下目前學習到的相關知識與經驗。 10 | -------------------------------------------------------------------------------- /aws/13-x-ray.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 13 5 | --- 6 | 7 | # X-Ray 8 | 9 | - X-Ray 可以用來追蹤微服務架構中應用程式的流程,並且可以看到每個流程的耗時 10 | - 非常貴的服務 11 | -------------------------------------------------------------------------------- /database/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 13 5 | --- 6 | 7 | # Database 8 | 9 | 紀錄資料庫相關知識,目前不限定特定的資料庫,所以可能包含 RMDBS 與 NoSQL 等筆記。 10 | -------------------------------------------------------------------------------- /azure/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 2 5 | --- 6 | 7 | # Azure 8 | 9 | 微軟提供的雲端服務,為目前世界上市占率第二高的雲端服務,僅次於 AWS。這裡簡單紀錄使用 Azure 的心得與踩過的坑。 10 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 6 5 | --- 6 | 7 | # Docker 8 | 9 | 容器化標準的先驅。Docker 相當好用的容器化技術,可以讓我們快速的建立開發環境,並且可以快速的部署到各種環境上。 10 | -------------------------------------------------------------------------------- /cloudflare/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 29 5 | --- 6 | 7 | # Cloudflare 8 | 9 | Cloudflare 是一家提供內容傳遞網路 (CDN)、分布式域名解析、計算與存儲服務的公司。Cloudflare 的服務旨在提升網站的效能和安全性,保護網站免受各種網路攻擊,如 DDoS 攻擊。 10 | -------------------------------------------------------------------------------- /fluent-bit/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 26 5 | --- 6 | 7 | # Fluent Bit 8 | 9 | Fluent Bit 是一個輕量級且高效能的日誌收集和處理工具,常用於容器化環境中,如 Kubernetes。它能夠從多種來源收集日誌,並將其轉發到多種目的地,如 S3、Elasticsearch、Splunk、Kafka 等。 10 | -------------------------------------------------------------------------------- /google-cloud-platform/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 3 5 | --- 6 | 7 | # Google Cloud Platform 8 | 9 | Google 的雲端平台,簡稱 GCP。之前曾試著在上面架設自己的網站,使用上相當舒服。 10 | 11 | 目前服務並不多,BigQuery 是該平台的明星產品,好用但也不便宜。 12 | -------------------------------------------------------------------------------- /php/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 14 5 | --- 6 | 7 | # PHP 8 | 9 | 用來開發網站後端十分方便,也有許多好用的框架可以使用。**是世界上最好的語言 (反串要註明!)**。 10 | 11 | 主要是用來記錄 PHP 的一些基本觀念與一些好用的套件。 12 | 13 | 最近在寫 PHP 套件,應該寫更多有關於 PHP 的筆記。 14 | -------------------------------------------------------------------------------- /laravel/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 16 5 | --- 6 | 7 | # Laravel 8 | 9 | PHP 上面最熱門的後端框架之ㄧ,也是我很喜歡的框架。我的部落格就是使用 Laravel 所開發。 10 | 11 | Laravel 受 Ruby on Rails 與 ASP.NET 等框架的啟發,其軟體架構也採用 MVC (Model、View 與 Controller)。 12 | -------------------------------------------------------------------------------- /windows/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 12 5 | --- 6 | 7 | # Windows 8 | 9 | 某天心血來潮,想要在 Windows 上面設定開發環境,但是又不想使用 WSL2,所以就嘗試一下不使用 WSL2,直接在 Windows 上面設定開發環境。 10 | 11 | > [!NOTE] 12 | > 13 | > 本筆記使用的 Windows 版本為 Windows 11。 14 | -------------------------------------------------------------------------------- /github/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 8 5 | --- 6 | 7 | # GitHub 8 | 9 | GitHub 是一個線上軟體原始碼代管服務平台,可以用來存放程式或軟體的代碼。 10 | 11 | 除了存放程式碼,GitHub 也提供了用來執行 CI/CD 流程的 GitHub Action 服務。用戶可以使用 GitHub Action 來執行自動測試或是建立容器映像檔案等流程。相當方便。 12 | -------------------------------------------------------------------------------- /terraform/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 4 5 | --- 6 | 7 | # Terraform 8 | 9 | 十分好用的 IaC (Infrastructure as Code ) 工具,可以用代碼來紀錄基礎建設資源。 10 | 11 | Terraform 使用 HashiCorp 發明的語言 HCL (HashiCorp Configuration Language) 來書寫,是一種宣告式語言。 12 | -------------------------------------------------------------------------------- /warp/01-install.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Warp 4 | nav_order: 1 5 | --- 6 | 7 | # 安裝 Warp 8 | 9 | Mac 用戶可以使用 Homebrew 安裝 warp 10 | 11 | ```bash 12 | brew install warp --cask 13 | ``` 14 | 15 | > 根據官方所說,Windows 與 Linux 正在開發中 16 | 17 | Warp **需要申請帳號才能使用**,不需要密碼,登入方式為信箱驗證 18 | -------------------------------------------------------------------------------- /vim/02-console.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Vim 4 | nav_order: 2 5 | --- 6 | 7 | # 指令 8 | 9 | 在 normal mode 輸入 `:` 即可開始輸入指令 10 | 11 | - `:/keyword` : 在當前檔案中搜尋 12 | - `:% s/target/replace/gc` : 在當前檔案中搜尋並取代,取代有多種模式 (y/n/a/q/l) 13 | - `:help key-notation` : 查詢 key notation,方便你在設定檔案中設定快捷鍵 14 | -------------------------------------------------------------------------------- /warp/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 22 5 | --- 6 | 7 | # Warp 8 | 9 | Warp 是一款由 Rust 所開發的 Mac 終端機 10 | 11 | Warp 的優點在於提供如編輯器一般的操作,讓指令輸入可以輕鬆斷行或是一次編輯多行,此外還提供指令提示與 AI 指令搜尋,十分方便 12 | 13 | ## 參考資料 14 | 15 | - [warp official website](https://www.warp.dev/) 16 | -------------------------------------------------------------------------------- /pest/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 15 5 | --- 6 | 7 | # Pest 8 | 9 | Pest 是一個 PHP 的測試框架,由 Laravel 維護團隊中的 Nuno 所開發。 10 | 11 | Pest 可以視為 PHPUnit 的再包裝版本,在測試寫法上與 PHPUnit 差異不大,但提供許多更優雅的測試寫法。 12 | 13 | ## 參考資料 14 | 15 | - [Laracasts - Pest From Scratch](https://laracasts.com/series/pest-from-scratch) 16 | -------------------------------------------------------------------------------- /warp/04-starship-integration.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Warp 4 | nav_order: 4 5 | --- 6 | 7 | # 整合 Starship 8 | 9 | 如果你有使用 [starship](https://starship.rs/) 客製命令提示字元 (prompt) 的話 10 | 11 | 在安裝 warp 之後會發現 starship 的命令提示字元會失效 12 | 13 | 可以使用快捷鍵 `Cmd` + `,` 開啟設定,選擇 Features,並開啟 **Honor user's custom prompt (PS1)**,此時 starship 的效果應該就會恢復 14 | -------------------------------------------------------------------------------- /grafana/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 9 5 | --- 6 | 7 | # Grafana 8 | 9 | 主要由 Grafana Labs 開發,是一個開源的監控與分析平台,可以將各種監控資料整合在一起,並且透過 Dashboard 的方式呈現。是做 O11y (Observability) 的知名工具。 10 | 11 | ## 參考資料 12 | 13 | - [你以為你在學 Grafana 其實你建立了 Kubernetes 可觀測性宇宙](https://ithelp.ithome.com.tw/users/20149562/ironman/6674) 14 | -------------------------------------------------------------------------------- /svelte/18-miscellaneous.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 18 5 | --- 6 | 7 | # Miscellaneous 8 | 9 | ## The `@debug` tag 10 | 11 | 除了可以使用 `console.log` 來 debug,Svelte 還提供了 `@debug` tag,可以用來觸發瀏覽器的 Debugger。 12 | 13 | ```svelte 14 | 17 | 18 | 19 | {@debug foo} 20 | ``` 21 | -------------------------------------------------------------------------------- /aws/19-sns.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 19 5 | --- 6 | 7 | # Simple Notification Service (SNS) 8 | 9 | - SNS 是一個全託管的消息訂閱服務,訂閱者可以是 AWS SQS、Lambda、HTTP endpoint、email address 或是 mobile SMS (簡訊)。 10 | - 使用 Pub/Sub 模式,想要接收消息請訂閱 (Subscription)。 11 | - SNS 可以做到 fan out,也就是當 publisher 產生消息時,SNS 會將其複製並推送給所有的訂閱者。 12 | - SNS 可以設定 filter policy,讓訂閱者只接收他們感興趣的消息。 13 | -------------------------------------------------------------------------------- /aws/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 1 5 | --- 6 | 7 | # AWS 8 | 9 | 為最早發跡,也是目前市佔率最高的雲端服務。這裡簡單紀錄日常工作上使用 AWS 服務的心得與踩過的坑。 10 | 11 | 前陣子有去考 AWS Solution Architect Associate 的證照,所以會將考試學到內容與心得記錄在這裡。這個筆記有很多內容是根據 Udemy 上面的 [AWS SAA 題庫](https://www.udemy.com/share/1064nS3@b8XfLZVooUNk-TBkYcN-qajkDhtjwumZVvf4TQnVylrB6OeC2eVHB6rUcYdLFFG-/)所做的重點整理。 12 | -------------------------------------------------------------------------------- /aws/23-cloudtrail.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 23 5 | --- 6 | 7 | # CloudTrail 8 | 9 | - 紀錄 AWS API 的呼叫紀錄,並且可以將紀錄送至 S3 或是 CloudWatch 10 | - 預設會對 Log 加密 11 | - Event 有兩種 12 | - Management event:管理事件,例如設定安全性的 IAM AttachRolePolicy API 操作。也包含非 API 的事件,例如登入 AWS Console 13 | - Data event:資料事件,例如對 S3 Bucket 內資料的操作,例如呼叫 GetObject、DeleteObject 或是 PutObject 的 API 14 | -------------------------------------------------------------------------------- /zed/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 27 5 | --- 6 | 7 | # Zed 8 | 9 | Zed 是一個現代化的文字編輯器,專為程式設計師設計,提供高效能和直觀的使用體驗。它支援多種程式語言,並且具有強大的擴展性,允許用戶根據自己的需求自訂功能和外觀。Zed 整合了 AI 功能,幫助用戶更快地編寫和修改程式碼。 10 | 11 | Zed 在 2025 年 8 月推出了 ACP(Agent/Client Protocol),並與 Google 合作,以 Gemini CLI 作為參考實作,用以驗證並推進 ACP 的設計。ACP 是由 Zed 主導設計的一套開放協定,目標在於提供統一的介面,讓第三方人工智慧代理人能以一致方式介接程式碼編輯器。 12 | -------------------------------------------------------------------------------- /fitness/01-fat-loss.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Fitness 4 | nav_order: 1 5 | --- 6 | 7 | # 減脂 8 | 9 | 想要減脂的話,最重要的是創造熱量赤字,也就是消耗的熱量要多於攝取的熱量。 10 | 11 | 可以透過控制飲食與增加運動量來達成這個目標。 12 | 13 | ## 建議 14 | 15 | - 推薦使用跑步機進行爬坡,在時速 4-6 公里的速度下,持續 30 分鐘以上。 16 | - 飲食比運動更為重要,建議控制每日熱量攝取在基礎代謝率以上 500 大卡以內。 17 | - 想避免重量反彈的話,建議進行力量訓練來增加肌肉量,以此增加基礎代謝率。 18 | - 建議在力量訓練後進行有氧運動,這樣可以更有效的燃燒脂肪,但不要在力量訓練前進行有氧運動,以免影響力量訓練的表現。 19 | -------------------------------------------------------------------------------- /rust/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 18 5 | --- 6 | 7 | # Rust 8 | 9 | 學習 Rust 語言,希望使用 Tauri 框架寫出一個計算機 App 10 | 11 | ## 學習資源 12 | 13 | - [The Rust Programming Language](https://doc.rust-lang.org/book/title-page.html) 14 | - [The Rust Programming Language - 正體中文版本](https://github.com/rust-tw/book-tw) 15 | - [Rust By Practice](https://practice.rs/why-exercise.html) 16 | -------------------------------------------------------------------------------- /rust/05-comment.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Rust 4 | nav_order: 5 5 | --- 6 | 7 | # 註解 8 | 9 | 註解可以讓你的程式碼更容易理解,**但切勿濫用**,更多時候好的變數與方法名稱就可以取代註解。 10 | 11 | 在 Rust 中,是使用 `//` 在程式碼中添加註解,被註解的區塊並不會被編譯器給執行。 12 | 13 | 註解可以可以用來稍微描述複雜程式碼的商業邏輯,讓後續接手開發的人可以更快速的理解。 14 | 15 | ```rust 16 | // hello, world 17 | 18 | fn main() { 19 | // I'm feeling lucky today 20 | let lucky_number = 7; 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /typescript/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 25 5 | --- 6 | 7 | # TypeScript 8 | 9 | 由微軟開發的靜態強型別語言,目的在優化前端開發。 10 | 11 | TypeScript 為 JavaScript 的超集,幫 JavaScript 加上類型提示、介面與枚舉 ... 等功能。 12 | 13 | 因為瀏覽器看不懂 TypeScript,所以 TypeScript 需要編譯成 JavaScript 才能在網頁中執行。 14 | 15 | 2025 年 3 月,[微軟宣布將 TypeScript 編譯器移植到 Go 語言](https://devblogs.microsoft.com/typescript/typescript-native-port/),編譯速度可以達到過往的 10 倍。 16 | -------------------------------------------------------------------------------- /rust/21-common-collection.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Rust 4 | nav_order: 21 5 | --- 6 | 7 | # 通用集合類型 8 | 9 | Rust 標準函式庫中有一系列被稱為**集合 (collections)** 資料結構,非常有用。 10 | 11 | 集合可以包含多個值,不同於內建的陣列與元組,集合中的所指向的資料是儲存在 Heap 上的, 12 | 因此不需要在編譯時就確定其內容,可以隨著程式執行時動態增長或減少。 13 | 14 | 廣泛被使用的集合有以下三種: 15 | 16 | - vector : 可以一個接著一個儲存一系列數量可變的值。 17 | - string : 是一個字符的集合。 18 | - hash map : 將一個值 (value) 與一個特定的鍵 (key) 相關聯,這是 map 這種特定資料結構的實現,且更為通用。 19 | -------------------------------------------------------------------------------- /pest/13-parallel.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Pest 4 | nav_order: 13 5 | --- 6 | 7 | # Parallel 8 | 9 | Pest 的測試預設都是使用單線程 (Single process) 10 | 11 | Pest 提供 parallel 套件,讓你可以使用多線程的方式執行測試,縮短測試時間 12 | 13 | 透過 composer 安裝 14 | 15 | ```bash 16 | composer require pestphp/pest-plugin-parallel --dev --with-all-dependencies 17 | ``` 18 | 19 | 安裝好在執行測試時就可以使用 `--parallel` 這個參數 20 | 21 | ```bash 22 | php artisan test --parallel 23 | ``` 24 | -------------------------------------------------------------------------------- /ansible/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 5 5 | --- 6 | 7 | # Ansible 8 | 9 | Ansible 是一套知名的 IaC (Infrastructure as Code) 工具 10 | 11 | 有別於用來建立資源的 Terraform,Ansible 主要用在設定機器上的環境 12 | 13 | Ansible 最大的特點在於它是 Agentless 的,你不需要在遠端主機上安裝任何 Agent 就能操作遠端主機 14 | 15 | ## 參考資料 16 | 17 | - [Ansible](https://www.ansible.com/) 18 | - [Ansible tips and tricks](https://docs.ansible.com/ansible/latest/tips_tricks/index.html) 19 | -------------------------------------------------------------------------------- /aws/29-sts.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 29 5 | --- 6 | 7 | # AWS STS (Security Token Service) 8 | 9 | STS 是 AWS 非常基礎的一項服務,主要用來產生臨時的安全認證 (Temporary Security Credentials),這些認證可以用來存取 AWS 資源。 10 | 11 | 基本上 AWS 中跨服務的存取控制,都是透過 IAM (Identity and Access Management) 來管理,而 IAM 會透過 STS 的臨時認證來實現這些存取控制。 12 | 13 | ## 參考資料 14 | 15 | - [IAM 中的暫時安全憑證](https://docs.aws.amazon.com/zh_tw/IAM/latest/UserGuide/id_credentials_temp.html) 16 | -------------------------------------------------------------------------------- /network/03-router.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Network 4 | nav_order: 3 5 | --- 6 | 7 | # Router 8 | 9 | 路由器是一個網路設備,用於在不同網路之間轉發數據包。路由器在 OSI 模型的第三層(網路層)上工作,並且可以在不同網路之間轉發數據封包。大多數路由器會在 LAN(區域網路)和 WAN(廣域網路)之間傳遞資料。 10 | 11 | 家裡常見的 WIFI 分享器就是一種路由器,他會有一個 WAN 接口連接網際網路,剩下的 LAN 接口連接家裡的設備,同時提供 WIFI 分享服務。每一個連接 LAN 接口與連上 WIFI 的設備,都會被分配一個 IP 12 | 13 | ## 參考資料 14 | 15 | - [什麽是路由器?](https://www.cloudflare.com/zh-tw/learning/network-layer/what-is-a-router/) 16 | -------------------------------------------------------------------------------- /git/05-revert.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Git 4 | nav_order: 5 5 | --- 6 | 7 | # Revert 8 | 9 | 與 `git reset` 不同,你可以用新增一個 commit 的方式來取消上一次 commit 的修改。 10 | 11 | ## 只想取消部分檔案的修改 12 | 13 | 這個操作與 `git reset` 的概念類似,可以使用 `git checkout` 來將部分檔案改回指定 commit 的內容。 14 | 15 | ```bash 16 | git checkout COMMIT_ID -- /path/to/file1 /path/to/file2 17 | ``` 18 | 19 | 然後將這些檔案 commit 一個版本即可。 20 | 21 | ```bash 22 | git add -A 23 | git commit "revert the file change in COMMIT_ID" 24 | ``` 25 | -------------------------------------------------------------------------------- /rust/41-interior-mutability-pattern.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Rust 4 | nav_order: 41 5 | --- 6 | 7 | # `RefCell` 與內部可變性模式 8 | 9 | 因為 Rust 編譯器較為保守的關係, 10 | 在某些情況下,即使你知道程式碼的借用方式沒有問題,但還是有可能無法通過 Rust 的編譯。 11 | 這時候就可以考慮使用 `RefCell`。 12 | 13 | `RefCell` 允許在執行時檢查可變參考,你可以改變 `RefCell` 內部的數值,就算 `RefCell` 是不可變的。 14 | 15 | > 類似於 `Rc`,`RefCell` 也只能用於單一執行緒(Single-Threaded)的場合。 16 | 17 | 在某些特定情況,我們會想要有一個可以改變數值的方法,但該數值對其他程式碼而言仍然是不可變的。 18 | 例如撰寫測試時常用到的模擬物件 (Mock Objects)。 19 | -------------------------------------------------------------------------------- /windows/02-set-alias.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Windows 4 | nav_order: 2 5 | --- 6 | 7 | # 設定指令的 Alias 8 | 9 | 在 Linux 的 Bash 中,你可以用 `alias` 來設定指令的別名。 10 | 11 | ```bash 12 | alias art="php artisan" 13 | ``` 14 | 15 | 而在 Windows 的 Powershell 中,雖然也有 `Set-Alias` 指令,不過只能使用單一指令, 16 | 組合指令會出現錯誤。 17 | 18 | ```powershell 19 | # 錯誤 20 | Set-Alias -Name "art" -Value "php artisan" 21 | ``` 22 | 23 | 你可以使用函式來設定組合指令。 24 | 25 | ```powershell 26 | function art { 27 | & php artisan $args 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /git/04-reset.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Git 4 | nav_order: 4 5 | --- 6 | 7 | # Reset 8 | 9 | 如果你想移除所有尚未 commit 的修改時,可以使用 `git reset` 指令。 10 | 11 | ```bash 12 | git reset --hard 13 | ``` 14 | 15 | 但其實你想移除上一個 commit 也可以。 16 | 17 | ```bash 18 | # 刪除最新的 commit 回到上一個版本的程式碼 19 | git reset --hard HEAD^ 20 | ``` 21 | 22 | 使用 `--hard` 有些粗暴,如果只是單純的想拆掉 commit 並保留修改,可以使用 `--soft`。 23 | 24 | ```bash 25 | git reset --soft HEAD^ 26 | ``` 27 | 28 | > [!IMPORTANT] 29 | > 30 | > 請勿拿這個指令來拆掉別人的 commit。如果想要修改別人 commit 內容,建議使用 `git revert`。 31 | -------------------------------------------------------------------------------- /database/01-master-data-and-transcation-data.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Database 4 | nav_order: 1 5 | --- 6 | 7 | # Master Data (主資料) and Transaction Data (交易資料) 8 | 9 | 主資料用來描述一個組織的基本資訊,例如客戶、產品、供應商、員工等。交易資料則是指組織的日常運作,例如銷售、採購、生產等。舉一個簡單的例子,說明主資料和交易資料的差異。 10 | 11 | 假設有一個客戶在一個商店向店員買了起司,那麼主資料關心的是客戶資訊、商店資訊以及購買產品,也就是起司的資訊。交易資料則是指這筆交易的時間、金額、付款方式等。 12 | 13 | 主資料描述的內容傾向名詞,而交易資料則是動詞。主資料通常是靜態的,而交易資料則是動態的。主資料通常是組織的基礎,交易資料則是組織的運作。 14 | 15 | ## 參考資料 16 | 17 | - [Master Data vs Transaction Data](https://www.youtube.com/watch?v=Iv9P5D6yj30) 18 | -------------------------------------------------------------------------------- /aws/10-firewall.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 10 5 | --- 6 | 7 | # WAF (Firewall) 8 | 9 | AWS 相關的防火牆服務,可以對訪問服務的請求做各種過濾。 10 | 11 | ## WAF 12 | 13 | - WAF 可以設定 rate-based rule 來過濾流量 14 | - WAF 可以過濾 SQL injection 攻擊 15 | - WAF 可以使用 Web ACL 過濾: 16 | - 特定來源 IP 17 | - 特定國家 18 | - request 的內容 19 | - AWS Firewall Manager 簡化跨多個帳戶和資源的管理和維護任務 (包含 WAF 與 AWS Shield) 20 | - AWS WAF 可以與 CloudFront、ALB 還有 API Gateway 一起使用 21 | 22 | ## Network Firewall 23 | 24 | - 可以設定 domain list rule 過濾掉來自惡意 domain 的請求,作用在 HTTP 與 HTTPS 上 25 | -------------------------------------------------------------------------------- /warp/03-feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Warp 4 | nav_order: 3 5 | --- 6 | 7 | # Warp 相關功能 8 | 9 | ## Autosuggestions 與 Syntax Highlighting 10 | 11 | 如果你是 oh my zsh 的使用者,你可能會安裝 autosuggestions 與 syntax highlighting 等 plugin 12 | 13 | 但這些功能 warp 本身就支援,所以建議可以移除 14 | 15 | ## AI 搜尋指令 16 | 17 | 可以輸入快捷鍵 `Ctrl` + `` ` ``,使用 AI 搜尋指令 18 | 19 | 例如我想知道我現在處於哪個路徑,可以使用英文搜尋 20 | 21 | ```text 22 | # where am i 23 | ``` 24 | 25 | 輸入完畢之後按下 `Enter`,應該就會出現搜尋結果 26 | 27 | ```bash 28 | pwd 29 | ``` 30 | 31 | 如果搜尋結果正確的話,可以使用 `Cmd` + `Enter`,將指令複製到輸入框中 32 | -------------------------------------------------------------------------------- /database/06-check.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Database 4 | nav_order: 6 5 | --- 6 | 7 | # Check 8 | 9 | 在 PostgreSQL 中,可以使用 `CHECK` 來避免某些錯誤的資料被寫入。 10 | 11 | 以多階段留言系統為例,留言的 `parent_id` 不應該等於自己的 `id` (即自己的父留言不應該是留言自己本身)。我們可以在 PostgreSQL 中使用 `CHECK` 來確認這個規則。 12 | 13 | ```sql 14 | ALTER TABLE comments 15 | ADD CONSTRAINT parent_id_cannot_be_its_own_id CHECK (comments.id <> comments.parent_id); 16 | ``` 17 | 18 | 如果想移除這個 `CONSTRAINT`,可以使用 `DROP` 來移除這個規則。 19 | 20 | ```sql 21 | ALTER TABLE comments 22 | DROP CONSTRAINT parent_id_cannot_be_its_own_id; 23 | ``` 24 | -------------------------------------------------------------------------------- /network/04-switch.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Network 4 | nav_order: 4 5 | --- 6 | 7 | # Switch 8 | 9 | 網路交換器(Switch)是一種網路裝置,用於連接多個裝置,例如電腦、印表機、伺服器等,以便這些裝置之間可以互相通信。Switch 是一種二層(Data Link Layer)裝置,主要負責將數據包(Data Frame)從來源裝置轉發到目的裝置。 10 | 11 | ## 交換器和路由器有什麼區別? 12 | 13 | 路由器為資料封包選擇路徑以穿過網路並到達其目的地。路由器透過連接不同的網路並在網路之間轉寄資料來實現這一點,這些網路包括 LAN、廣域網路 (WAN) 或自主系統,後者是構成網際網路的大型網路。 14 | 15 | 實際上,**路由器對於網際網路連線是必需的,而交換器僅用於互連裝置**。家庭和小型辦公室需要路由器來存取網際網路,但大多數不需要網路交換器。 16 | 17 | ## 參考資料 18 | 19 | - [什麽是網路交換器?| 交換器與路由器](https://www.cloudflare.com/zh-tw/learning/network-layer/what-is-a-network-switch/) 20 | -------------------------------------------------------------------------------- /git/01-config.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Git 4 | nav_order: 1 5 | --- 6 | 7 | # Config 8 | 9 | 查看全域設定。 10 | 11 | ```bash 12 | git config --global --list 13 | ``` 14 | 15 | 查看目前專案的設定。 16 | 17 | ```bash 18 | git config --local --list 19 | ``` 20 | 21 | 設定 username 與 email。 22 | 23 | ```bash 24 | # 全域設定 25 | git config --global user.email "allen@example.com" 26 | git config --global user.name "allen" 27 | 28 | # 目前專案設定 29 | git config --local user.email "allen@example.com" 30 | git config --local user.name "allen" 31 | ``` 32 | 33 | 使用編輯期來編輯設定。 34 | 35 | ```bash 36 | git config --global --edit 37 | ``` 38 | -------------------------------------------------------------------------------- /terraform/02-time-rotating.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Terraform 4 | nav_order: 2 5 | --- 6 | 7 | # Time Rotating 8 | 9 | Terraform 中有提供一個叫做 `time_rotating` 的資源,讓你可以超過一定時間後,重新部署資源。 10 | 11 | ```hcl 12 | resource "time_rotating" "rotate_every_15_days" { 13 | rotation_days = 15 14 | } 15 | ``` 16 | 17 | 假設你想要讓 IAM Access Key 超過 15 天後就重新建立,就可以在 `lifecycle` 設定超過天數就重新建立。 18 | 19 | ```hcl 20 | resource "aws_iam_access_key" "example" { 21 | user = aws_iam_user.example.name 22 | 23 | lifecycle { 24 | replace_triggered_by = [time_rotating.rotate_every_15_days.rotation_rfc3339] 25 | } 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /php/02-deploy-laravel-on-ubuntu.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: PHP 4 | nav_order: 2 5 | --- 6 | 7 | # 在 Ubuntu 上面部署 Laravel 8 | 9 | 最近想將 Laravel 部署在 Ubuntu 上,記錄一下 PHP 8.3 的安裝方式。 10 | 11 | ## 安裝 PHP 8.3 12 | 13 | ```bash 14 | # 在 Dockerfile 中 需要先安裝 add-apt-reposit 15 | sudo apt-get install software-properties-common -y 16 | sudo add-apt-repository ppa:ondrej/php -y 17 | sudo apt-get update 18 | sudo apt install php8.3 php8.3-{cli,common,curl,xml,mbstring} -y 19 | # 如果你是搭配 Nginx 使用,需要安裝 php-fpm 20 | sudo apt install php8.3-fpm -y 21 | # redis 與 swoole 依照需求安裝 22 | sudo apt install php8.3-{redis,swoole} -y 23 | ``` 24 | -------------------------------------------------------------------------------- /svelte/10-animations.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 10 5 | --- 6 | 7 | # Animations 8 | 9 | 剛剛的 `crossfade` 雖然可以讓 Todo List 在勾選項目時有移動的效果,但其他項目的遞補移動卻沒有。 10 | 11 | 這時候我們可加上 `flip` 來讓其他項目的遞補移動也有動畫效果。 12 | 13 | ```svelte 14 | 19 | 20 | 21 | 22 |
  • 28 | 29 |
  • 30 | ``` 31 | 32 | > [!NOTE] 33 | > 34 | > 請注意,所有動畫都是透過 CSS 應用的,而不是 JavaScript,這意味著它們不會阻塞(或被阻塞)主執行緒。 35 | -------------------------------------------------------------------------------- /vim/03-map.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Vim 4 | nav_order: 3 5 | --- 6 | 7 | # Map 8 | 9 | 使用 `map` 可以修改按鍵的對應,例如將 `zl` 對應到 `$`,這樣就可以在 normal mode 底下使用 `zl` 來移動到行尾。 10 | 11 | ```vim 12 | nmap zl $ 13 | ``` 14 | 15 | 而 `map` 有幾種前綴,分別是: 16 | 17 | - `nmap` : 只在 normal mode 下生效。 18 | - `vmap` : 只在 visual mode 下生效。 19 | - `imap` : 只在 insert mode 下生效。 20 | - `cmap` : 只在 command mode 下生效。 21 | 22 | 除此之外還有一種 `nore` 前綴,代表非遞迴,這樣就可以避免重複對應。例如: 23 | 24 | ```vim 25 | map a b 26 | map c a 27 | ``` 28 | 29 | 這樣對 `c` 來說,效果等同於: 30 | 31 | ```vim 32 | map c a 33 | ``` 34 | 35 | ## 參考資料 36 | 37 | - [vim 的幾種模式和按鍵映射](http://haoxiang.org/2011/09/vim-modes-and-mappin/) 38 | -------------------------------------------------------------------------------- /php/02-static-analysis.md: -------------------------------------------------------------------------------- 1 | # Static Analysis 2 | 3 | 靜態分析 (Static Analysis) 是指在不執行程式的情況下,透過程式碼的分析,來找出程式碼中的錯誤。 4 | 5 | PHP 有一個靜態分析工具 [PHPStan](https://phpstan.org/),可以幫助我們找出 PHP 程式碼中的錯誤。 6 | 7 | ## 在 Laravel 專案中使用 PHPStan 8 | 9 | Laravel 因為使用了不少 PHP 的魔術方法 (Magic Method),所以在使用 PHPStan 時,會有很多的錯誤訊息,因此我們需要使用 [Larastan](https://github.com/nunomaduro/larastan) 來幫助我們處理這些錯誤訊息。 10 | 11 | 安裝 Larastan。 12 | 13 | ```bash 14 | composer require nunomaduro/larastan:^2.0 --dev 15 | ``` 16 | 17 | 然後在 Laravel 資料夾底下新增 `phpstan.neon` 檔案,內容如下: 18 | 19 | ```neon 20 | includes: 21 | - ./vendor/nunomaduro/larastan/extension.neon 22 | 23 | parameters: 24 | 25 | paths: 26 | - app/ 27 | 28 | level: 5 29 | ``` 30 | -------------------------------------------------------------------------------- /aws/03-region-and-availability-zone.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 3 5 | --- 6 | 7 | # Region and Availability Zone 8 | 9 | ## Region 10 | 11 | 如何選擇 AWS Region?有幾個面向可以考慮: 12 | 13 | - Compliance:政府資料規定不能夠離開該國家。 14 | - Proximity:離使用者最近的地區,減少延遲 (Latency)。 15 | - Available Service:某些服務只有在特定地區才有提供。 16 | - Pricing:不同地區的價格不同。 17 | 18 | ## Availability Zone 19 | 20 | 每個 region 都有多個 availability zone (簡稱 AZ),通常為 3 個,最少為 3 個,最多為 6 個。 21 | 例如 ap-southeast-2 (亞太區域 - 雪梨) 就有 3 個 AZ,分別為 ap-southeast-2a、ap-southeast-2b 與 ap-southeast-2c。 22 | 23 | 每個 AZ 都是獨立的,因此在做災害復原 (Disaster Recovery) 的時候,可以將資源部署在不同的 AZ,以達到高可用性 (High Availability) 的目的。 24 | 25 | 每個 AZ 間都使用高頻寬 (bandwidth) 且極低延遲 (ultra-low latency) 的網路互相連線。 26 | -------------------------------------------------------------------------------- /pest/05-custom-function.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Pest 4 | nav_order: 5 5 | --- 6 | 7 | # 定義自己的方法 8 | 9 | 剛剛提到的我們可以使用 `actingAs()` 在測試中模擬某個用戶登入 10 | 11 | 這個方法很常被拿來使用,但每次使用前都要先建立一個 user 並傳入 `actingAs()`,久而久之,你的測試可能很常重複下面這段程式碼 12 | 13 | ```php 14 | $user = User::factory()->create(); 15 | 16 | $this->actingAs($user); 17 | ``` 18 | 19 | 我們可以在 `tests/Pest.php` 中自己定義一個 `login()` 方法,並將上面的流程放進去 20 | 21 | ```php 22 | use App\Models\User; 23 | 24 | function login($user = null) { 25 | return test()->actingAs($user ?? User::factory()->create()); 26 | } 27 | ``` 28 | 29 | 之後我們就可以在測試中重複使用剛剛定義的登入方法,貫徹 DRY 原則 30 | 31 | ```php 32 | test('can view contents', function () { 33 | login()->get('/contents')->assertStatus(200); 34 | }); 35 | ``` 36 | -------------------------------------------------------------------------------- /tailwind-css/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 23 5 | --- 6 | 7 | # Tailwind CSS 8 | 9 | Tailwind CSS 是一個 Utility First 的 CSS 框架, 10 | 意思是框架中會盡可能的提供小型、單一樣式以及單一用途的的 Class Name。 11 | 這麼做的好處在於你可以很直觀的透過 Class Name 去調整樣式。 12 | 13 | 以下面這個卡片樣式為例子: 14 | 15 | ```html 16 |
    17 | 18 |
    19 | ``` 20 | 21 | `
    ` 中的每一個 Class Name,其代表的 CSS 屬性如下 22 | 23 | ```css 24 | .rounded-xl { 25 | border-radius: var(--radius-xl); 26 | } 27 | 28 | .bg-gray-50 { 29 | background-color: var(--color-gray-50); 30 | } 31 | 32 | .p-4 { 33 | padding: calc(var(--spacing) * 4); 34 | } 35 | ``` 36 | 37 | 可以看到每一個 Class Name 都只提供很簡單的 CSS 樣式。 38 | 因此使用者可以從名稱很直觀的知道這個 Class Name 提供了什麼樣的 CSS 效果。 39 | -------------------------------------------------------------------------------- /pest/09-groups.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Pest 4 | nav_order: 9 5 | --- 6 | 7 | # 使用 Group 幫測試建立群組 8 | 9 | 你可以使用 `group()` 將多個測試放進一個群組中 10 | 11 | ```php 12 | it('can validate an email', function () { 13 | $rule = new IsValidEmailAddress(); 14 | 15 | expect($rule->passes('email', 'allen@hello.com'))->toBeTrue(); 16 | })->group('validation'); 17 | ``` 18 | 19 | 這樣執行測試時就可以使用 `--group` 來執行指定群組的測試 20 | 21 | > group() 是可以跨檔案的,你可以把位於不同檔案的測試放進同一個群組中 22 | 23 | ```bash 24 | php artisan test --group=validation 25 | ``` 26 | 27 | 如果檔案內全部測試都屬於同一個群組,我們在檔案的上方使用下面的語法,這樣該檔案中的全部測試都會被加入 `validation` 群組中 28 | 29 | ```php 30 | uses()->group('validation'); 31 | ``` 32 | 33 | 如果不想要執行某群組的測試,可以在指令中使用 `--exclude` 34 | 35 | ```bash 36 | php artisan test --exclude=validation 37 | ``` 38 | -------------------------------------------------------------------------------- /network/06-static-route.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Network 4 | nav_order: 6 5 | --- 6 | 7 | # Static Route 8 | 9 | 靜態路由是一種手動設定的路由,通常用於小型網路或是網路設備。靜態路由的優點是簡單、容易設定,但缺點是不具備自動更新的功能,需要手動維護。 10 | 11 | 你可以使用 `ip route` 指令來設定靜態路由,例如: 12 | 13 | ```bash 14 | ip route add 172.16.11.13/32 via 192.168.0.1 15 | ``` 16 | 17 | 也可以透過 `dev` 參數來指定網路介面: 18 | 19 | ```bash 20 | ip route add 172.16.11.13/32 dev eth0 21 | ``` 22 | 23 | ## DHCP Lease 會清除靜態路由 24 | 25 | 跟 DHCP 租借而來的 IP 地址有一定的期限。**時間一到,伺服器會重新向 DHCP 重新取得 IP 位址,並重新啟動網卡,這個過程會讓原本設定的靜態路由被清除**。如果你希望靜態路由能夠在 IP 位址變更後仍然保留,可以寫增加靜態路由的一個腳本,並放入 `/usr/lib/networkd-dispatcher/routable.d` 目錄中。 26 | 27 | ```bash 28 | #!/bin/bash 29 | 30 | # 撰寫一個簡單的腳本,用來設定靜態路由,並放入 /usr/lib/networkd-dispatcher/routable.d 目錄 31 | ip route add 172.16.11.13/32 via 192.168.0.1 32 | ``` 33 | 34 | 當網卡重新啟動時,這個腳本會被執行,並重新設定靜態路由。 35 | -------------------------------------------------------------------------------- /php/04-shell-exec.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: PHP 4 | nav_order: 4 5 | --- 6 | 7 | # Shell Exec 8 | 9 | 在 PHP 中,你可以使用 `exec()` 來執行外部指令。 10 | 11 | ```php 12 | $output=null; 13 | $exitCode=null; 14 | // 在可以執行 whoami 指令的機器上,執行 whoami 指令 15 | exec('whoami', $output, $exitCode); 16 | echo "Returned with status $exitCode and output:\n"; 17 | print_r($output); 18 | 19 | // 結果 20 | // Returned with status 0 and output: 21 | // Array 22 | // ( 23 | // [0] => allen 24 | // ) 25 | ``` 26 | 27 | PHP 其實提供另外一種更方便的方式來執行外部指令 - 反引號。 28 | 29 | ```php 30 | $output = `whoami`; 31 | 32 | echo $output; // allen 33 | ``` 34 | 35 | 如果你擔心安全問題,想要關閉這個功能,可以在 `php.ini` 加入以下這行 36 | 37 | ```ini 38 | disable_functions = "shell_exec" 39 | ``` 40 | 41 | ## 參考資料 42 | 43 | - [Execution Operators](https://www.php.net/manual/en/language.operators.execution.php) 44 | -------------------------------------------------------------------------------- /svelte/15-context-api.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 15 5 | --- 6 | 7 | # Context API 8 | 9 | ## `setContext` and `getContext` 10 | 11 | Context API 為元件提供了一種相互「對話」的機制,無需將資料和函數作為 props 傳遞,也無需調度大量事件。 12 | 13 | ```svelte 14 | 15 | 26 | ``` 27 | 28 | ```svelte 29 | 30 | 37 | 38 | 41 | ``` 42 | -------------------------------------------------------------------------------- /aws/08-certificate.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 8 5 | --- 6 | 7 | # AWS Certificate Service 8 | 9 | AWS 相關的憑證管理服務。 10 | 11 | ## AWS Certificate Manager (ACM) 12 | 13 | - AWS Certificate Manager (ACM) 主要用來管理 SSL/TLS 憑證,憑證可以用在下面這些服務: 14 | - Elastic Load Balancer (ELB) 15 | - Cloudfront 16 | - API Gateway 17 | - ACM 支援自動更新憑證。 18 | - 根據安全考量,ACM 中的憑證無法匯出。 19 | - 你可以自己與 CA 申請憑證,然後匯入 ACM 中,但這樣就不支援自動更新憑證。 20 | 21 | ## AWS Private CA 22 | 23 | AWS Private CA 是一種高度可用的多功能 CA (Certificate Authority),可協助組織使用私有憑證來保護其應用程式和裝置的安全。 24 | 25 | ## AWS CloudHSM 26 | 27 | - AWS CloudHSM 可讓你在經過 FIPS (Federal Information Processing Standard) 驗證的硬體上管理和存取您的金鑰。可用來與 KMS 一起使用。 28 | - 如果 HSM 出現問題導致金鑰遺失,AWS 也無法幫用戶找回金鑰。因此 AWS 建議使用 Multi-AZ 來避免這種情況發生。 29 | 30 | > [!NOTE] 31 | > 32 | > HSM (Hardware security module) 又稱硬體安全模組,是一種用於保障和管理強認證系統所使用的數字金鑰,並同時提供相關密碼學操作的電腦硬體裝置。 33 | -------------------------------------------------------------------------------- /cloudflare/01-november-2025-outage.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Cloudflare 4 | nav_order: 1 5 | --- 6 | 7 | # Cloudflare 2025-11 全球性故障案例研究 8 | 9 | 台灣時間 2025 年 11 月 18 日,Cloudflare 發生了一次全球性的服務中斷事件,影響了數百萬網站和應用程式的可用性。這次故障持續了數個小時,導致大量用戶訪問受 Cloudflare 保護的網站時遇到 500 錯誤。 10 | 11 | ## 故障原因總結 12 | 13 | 1. 想修改權限,結果分散式資料庫的查詢語法有誤,導致從多個資料庫來源讀取資料。 14 | 2. 根據資料庫查詢產出的特徵檔案(feature file)有多個重複的值(內容相同但資料庫來源不同的重複資料)。 15 | 3. 機器人管理服務(使用 Rust 編寫)在讀取這些特徵檔案時,撞到特徵載入數量的上限(最多 200 個)。 16 | 4. 機器人管理服務某段程式碼沒寫好,並沒有處理這個例外,導致程式 Panic 並引發程式崩潰。 17 | 5. 機器人程式是 Cloudflare Proxy 的核心功能,結果程式崩潰導致整個 Proxy 服務無法運作。 18 | 6. Proxy 服務無法運作,導致所有受 Cloudflare 保護的網站都無法訪問,並顯示 500 錯誤。 19 | 20 | ## 後續影響 21 | 22 | - 機器人管理服務崩潰,每個訪問網站的用戶 0 分,判定每個用戶都是機器人。 23 | - 用戶訪問受 Cloudflare 保護的網站以及他們的 CDN 節點,都會看到 500 錯誤。 24 | - 他們內部服務也會使用自己的 Proxy,導致內部服務無法運作。 25 | 26 | ## 參考資料 27 | 28 | - [Cloudflare 2025-11-18 Global Outage Case Study](https://blog.cloudflare.com/18-november-2025-outage/) 29 | -------------------------------------------------------------------------------- /aws/21-cloudfront.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 21 5 | --- 6 | 7 | # CloudFront (AWS CDN Service) 8 | 9 | CloudFront 是 AWS 的 CDN (Content Delivery Network) 服務,可以用來加速靜態和動態的 Web 內容分發。CloudFront 會將你的內容複製到多個位於全球各地的 Edge Location,當用戶訪問你的網站時,會自動將用戶導向到離用戶最近的 Edge Location,這樣可以減少網頁載入的時間。 10 | 11 | ## SAA 筆記 12 | 13 | - Amazon CloudFront 是一項可加快向使用者分發靜態和動態 Web 內容(例如 .html、.css、.js 和映像檔)的服務 14 | - 可以設定多個 origin group,並且設定 failover,當 origin group 1 掛掉時,會自動切換到 origin group 2 15 | - 如果想在 CloudFront 限制用戶訪問你的內容,可以使用 16 | - Signed URLs:支援 Adobe's Real-Time Message Protocol (RTMP) 17 | - Signed cookies:不想更改 URL 可以用 cookie 18 | - Origin Access Identity (OAI) 19 | - Origin Access Control (OAC),官方建議使用 OAC,其支援所有地區 20 | - CloudFront geo-restriction 是用來避免部分地區的用戶訪問你的 CDN 內容 21 | - Lambda@Edge 可以讓你在各個 CDN 端點使用程式做一些小任務,例如登入 22 | - Lambda@Edge 後面可接 Kinesis 來即時處理資料 23 | - 可以透過設置 `Cache-Control max-age` 的值來設定 CloudFront 的 cache 時間 24 | -------------------------------------------------------------------------------- /database/05-languages.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Database 4 | nav_order: 5 5 | --- 6 | 7 | # 資料庫中的各種語句 8 | 9 | 簡單記錄一下資料庫中常看到的 DDL、DML、DQL、DCL 與 TCL,這些簡寫是什麼意思? 10 | 11 | ## DDL (Data Definition Language) 12 | 13 | 資料定義語言,用於定義和管理 SQL 資料庫中的所有物件的語句。 14 | 15 | - `CREATE`,建立一個物件,如資料庫與資料表。 16 | - `ALTER`,修改資料表結構。 17 | - `DROP`,刪除資料表。 18 | - `TRUNCATE`,清除資料表所有資料。 19 | 20 | ## DML (Data Manipulation Language) 21 | 22 | 資料操作語言,分別是 `UPDATE`、`INSERT` 與 `DELETE` 這些用來修改資料的語句。 23 | 24 | ## DQL (Data Query Language) 25 | 26 | 資料查詢語言,指的是 `SELECT` 這個用來查詢資料的語句,不會對資料進行修改。 27 | 28 | ## DCL (Data Control Language) 29 | 30 | 資料控制語言,是用來設置或更改資料庫使用者或角色許可權的語句。 31 | 包括 `GRANT`、`DENY` 與 `REVOKE`。 32 | 在預設狀態下,只有 sysadmin、dbcreator、db_owner 或 db_securityadmin 等人員才有權力執行。 33 | 34 | ## TCL (Transaction Control Language) 35 | 36 | 事務控制語言,有以下幾種語句。 37 | 38 | - `SAVEPOINT`,設置保存點。 39 | - `ROLLBACK`,回滾。 40 | - `SET TRANSACTION`,開始事務。 41 | - `COMMIT`,提交事務。 42 | -------------------------------------------------------------------------------- /docker/03-prune.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Docker 4 | nav_order: 3 5 | --- 6 | 7 | # 清理用不到的 Docker 資源 (容器、映像檔與資料存儲) 8 | 9 | 在使用 `docker build` 多次建立 image 時,即使 `image:tag` 相同,先前 build 出來的 image 也不會被刪除,而是呈現 untag 的狀態 10 | 11 | 這時我們可以用下方的指令查看 dangling images 12 | 13 | ```shell 14 | docker images --filter "dangling=true" 15 | ``` 16 | 17 | 移除 dangling 的 images 18 | 19 | ```shell 20 | docker image prune 21 | ``` 22 | 23 | 剛 pull 下來但沒有建立容器的 image 不算是 dangling images,而是 unused images,如果也想清除這些 images 的話,可以使用下面的指令 24 | 25 | ```shell 26 | docker image prune -a 27 | ``` 28 | 29 | 移除所有沒用到的 Docker 物件。會連同停用的容器、無用的網路、無用的映像檔案與無用的建置快取全部刪除 30 | 31 | ```shell 32 | docker system prune -a 33 | ``` 34 | 35 | 當 Docker 資料存儲不再被容器使用時,可以使用下方的指令清理這些不再使用的 Docker 資料存儲 36 | 37 | ```shell 38 | docker volume prune 39 | ``` 40 | 41 | ## 參考資料 42 | 43 | - [如何快速刪除所有已經無用的 Docker 資源 (容器,容器映像,網路)](https://blog.miniasp.com/post/2022/11/18/docker-image-prune-notes) 44 | -------------------------------------------------------------------------------- /git/02-stash.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Git 4 | nav_order: 2 5 | --- 6 | 7 | # 使用 Stash 來暫存目前的變更 8 | 9 | 將目前所有修改加入暫存。 10 | 11 | ```bash 12 | git stash 13 | ``` 14 | 15 | 暫存可以使用註解,方便查找。 16 | 17 | ```bash 18 | git stash save "save message" 19 | ``` 20 | 21 | 查看所有暫存。 22 | 23 | ```bash 24 | git stash list 25 | ``` 26 | 27 | 顯示最新的暫存。 28 | 29 | ```bash 30 | git stash show 31 | ``` 32 | 33 | 顯示第二新的暫存,根據 `{}` 中的數字以此類推。 34 | 35 | ```bash 36 | git stash show stash@{1} 37 | ``` 38 | 39 | 顯示最新暫存的改動。 40 | 41 | ```bash 42 | git stash show -p 43 | ``` 44 | 45 | 顯示第二新的暫存的改動,根據 `{}` 中的數字以此類推。 46 | 47 | ```bash 48 | git stash show -p stash@{1} 49 | ``` 50 | 51 | 套用暫存,並將此暫存從暫存列表中刪除。 52 | 53 | ```bash 54 | git stash pop 55 | ``` 56 | 57 | 套用暫存,但是不將此暫存從暫存列表中移除。 58 | 59 | ```bash 60 | git stash apply 61 | ``` 62 | 63 | 丟棄暫存。 64 | 65 | ```bash 66 | git stash drop 67 | ``` 68 | 69 | 刪除全部暫存。 70 | 71 | ```bash 72 | git stash clear 73 | ``` 74 | -------------------------------------------------------------------------------- /svelte/20-global-state.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 20 5 | --- 6 | 7 | # Global state 8 | 9 | Svelte 5 的 `$state` 除了可以在元件內部使用之外,還可以用來創建全域狀態 (global state),讓你可以在多個元件之間共享狀態。 10 | 11 | 首先建立一個 `shared.svelte.js` 檔案,並在其中使用 `$state` 來定義全域狀態: 12 | 13 | ```javascript 14 | // shared.svelte.js 15 | export const counter = $state({ 16 | count: 0, 17 | }); 18 | ``` 19 | 20 | 在其他元件中,你可以匯入這個全域狀態並使用它: 21 | 22 | ```svelte 23 | 30 | 31 | 34 | ``` 35 | 36 | ## 參考資料 37 | 38 | - [Universal Reactivity - Basic Svelte](https://svelte.dev/tutorial/svelte/universal-reactivity) 39 | - [Runes and Global state: do's and don'ts](https://mainmatter.com/blog/2025/03/11/global-state-in-svelte-5/) 40 | -------------------------------------------------------------------------------- /aws/14-auto-scaling-group.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 14 5 | --- 6 | 7 | # Auto Scaling Group (ASG) 8 | 9 | - ASG 的 Policy 種類: 10 | - **Target tracking scaling policy**:允許你指定目標值,ASG 將盡力保持 EC2 實例數量以滿足這個目標值。例如平均 CPU 使用率維持在 50%,或是平均網路流量維持在 100MB。 11 | - **Simple scaling policy**:最基本的自動擴展策略。它根據 CloudWatch 指標的閾值進行擴展和縮減。例如 CPU 使用率超過 50% 時,擴展 2 台機器,CPU 使用率低於 20% 時,縮減 1 台機器。 12 | - **Step scaling policy**:允許你在多個指標範圍定義的區域進行擴展和縮減,以應對不同負載情境。例如 CPU 50% 時,擴展 2 台機器,CPU 80% 時,擴展 4 台機器。 13 | - **Scheduled scaling policy**:如果你早就知道什麼時候會有較大的流量,可以使用此策略,在大流量的時間點前擴展機器。 14 | - **Predictive scaling policy**:如果你想讓 AWS 使用機器學習,根據過去幫你預測未來流量,可以使用此策略。 15 | - ASG 在做 scale in 時,會優先關掉**啟動設定檔最舊**的機器,如果是在 Multi-AZ 的架構下,會優先選擇擁有最多機器的 AZ。 16 | - ASG 在一次 scale in/out 活動之後會有一段冷卻期 (cool down period),冷卻期內即使達到 scale in/out 條件,ASG 也不會有任何動作。冷卻期的預設時間是 300 秒。 17 | - 可以使用 CloudWatch Alarm 來觸發 ASG 的 scale in/out。 18 | - ASG 定義好 launch template 後就無法在修改,只能新增一個新的。 19 | -------------------------------------------------------------------------------- /rust/02-variable.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Rust 4 | nav_order: 2 5 | --- 6 | 7 | # 變數 8 | 9 | ## 變數與常量 10 | 11 | Rust 的變數默認為不可變 (immutable)。 12 | 13 | ```rust 14 | let x = 10; 15 | x = 5; // cannot assign twice to immutable variable 16 | ``` 17 | 18 | 想使變數可變可以加上 `mut` 關鍵字。 19 | 20 | ```rust 21 | let mut x = 10; 22 | x = 5; 23 | ``` 24 | 25 | 可以使用 `const` 聲明常量,常量不允許改變。 26 | 27 | 在宣告的作用域中,常量在整個程式的生命週期都有效,因此常用來做全局範圍的固定值。 28 | 29 | ```rust 30 | const MAX_POINT: u32 = 100_000; 31 | ``` 32 | 33 | ## 隱藏 (Shadowing) 34 | 35 | 可以使用 `let` 重複宣告同一個變數,此時第一個變數會被**隱藏**。 36 | 37 | 與 `mut` 不同的地方是,隱藏其實是建立一個新的變數,只是變數名稱與別人相同而已,因此類型上也可以是全新的。 38 | 39 | 隱藏的好處在於對於意思類似但類型不同的變數,我們可以不用特地再去想一個新的變數名稱。 40 | 41 | ```rust 42 | let spaces = " "; 43 | let spaces = spaces.len() 44 | ``` 45 | 46 | 如果改用可變變數就會有問題,因為第二次賦值時,變數類型並不一樣。 47 | 48 | ```rust 49 | let mut spaces = " "; 50 | spaces = spaces.len(); // expected type `&str` found type `usize` 51 | ``` 52 | -------------------------------------------------------------------------------- /aws/12-api-gateway.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 12 5 | --- 6 | 7 | # API Gateway 8 | 9 | - 可以將回傳結果做 cache,減少後面 server 或是 Lambda 的負擔 10 | - API Gateway 可以很輕鬆的做到金絲雀部署 (canary deployment),金絲雀部署是指先讓一小部分的用戶測試新功能,如果沒問題再逐步擴大至全部用戶 11 | - 藍綠部署是指同時有新版本與舊版本,並且可以很方面的快速切換,但同一時間只會有一個環境在線上 12 | - API Gateway 可以調整流量限制 (throttling) 13 | - API gateway 只收資料傳輸量的費用,即 pay as you go 14 | - 可以根據 path 將請求送到不同的 backend 15 | - 可以根據 query string 將請求送到不同的 backend 16 | 17 | ## Burst Limit VS Rate Limit 18 | 19 | API Gate 可以調整流量限制 (Throttling),可以在左側選單中選擇 Protect 底下的 Throttling,其中又分為 Burst Limit 與 Rate Limit。 20 | 21 | - Burst Limit 代表你的 API 在同一時間最多可以處理幾個請求。 22 | - Rate Limit 代表你的 API 在一秒鐘內最多可以處理幾個請求。 23 | 24 | > [!NOTE] 25 | > 26 | > 所謂的 API Throttling,其實是一種用來限制用戶 API 請求數量的方式,用以保護後端不被大量請求癱瘓 27 | > 28 | > API Throttling 有多種策略,最常見的策略是限制使用者在一定時間內可以發出的 API 請求數量。 29 | > 除此之外還有令牌桶策略,設定一個有上限數量的令牌桶,令牌重新生成的速率固定, 30 | > 用戶每發一次請求都會消耗一個令牌,令牌沒了就要等令牌重新生成才能發請求。 31 | > 令牌桶策略可以允許偶發性的大量請求出現。 32 | -------------------------------------------------------------------------------- /pest/02-ide-plugin.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Pest 4 | nav_order: 2 5 | --- 6 | 7 | # IDE Plugin 8 | 9 | Pest 官方有提供多種 IDE 的 plugin,詳細可以上官方網站查看 : [Pest - IDE plugins](https://pestphp.com/docs/ide-plugins) 10 | 11 | ## PhpStorm 的功能 12 | 13 | - 安裝好 plugin 之後,如果你測試檔案是用 Pest 寫的,那麼 icon 就會變成 Pest 的 icon 14 | - 每個 Pest 測試檔案的最上方都會有一個按鈕可以讓你直接執行該檔案的測試 15 | - 此外點選 Menu -> Navigate -> File Structure 就可以查看該測試檔案所包含的所有測試 16 | 17 | - Mac 快捷鍵為 `Cmd + F12` 18 | - Windows 快捷鍵為 `Ctrl + F12` 19 | 20 | - 可以使用 `Shift x 2` 直接搜尋測試名稱並跳轉 21 | - 支援 Pest 的 `expect()` API,如果你在 `Pest.php` 中有客製的 `expect` 方法,這個 plugin 會在 autocompletion 中顯示 22 | - 在 Laravel 的 `tests` 資料夾上,可以點選右鍵選擇 More Run/Debug -> Run 'tests(Pest) with Coverage' 執行測試並顯示覆蓋度 23 | - 測試執行完畢之後,會在檔案列表中顯示每個檔案的測試覆蓋度 24 | - 在 Menu -> Run -> Hide coverage 中可以關閉檔案列表測試覆蓋度的顯示 25 | 26 | ## 參考資料 27 | 28 | [![Discovering the Pest Plugin](https://img.youtube.com/vi/umVUEq4yGIQ/sddefault.jpg)](https://www.youtube.com/watch?v=umVUEq4yGIQ) 29 | -------------------------------------------------------------------------------- /k8s/03-roloader.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Kubernetes (K8s) 4 | nav_order: 3 5 | --- 6 | 7 | # Reloader 8 | 9 | 為開源專案,當更新 `ConfigMap` 與 `Secret` 時,會重新建立與之相依的 `Pod`,讓 `Pod` 使用最新的設定。 10 | 11 | ## 概念 12 | 13 | Reloader 會在叢集中執行一個 controller,這個 controller 會不斷的檢查 `ConfigMap` 與 `Secret` 是否有更新, 14 | 如果有的話,就會滾動更新 (rolling update) 與之相依的 Pod。 15 | 16 | ## 部署 Reloader 到 K3s 中 17 | 18 | 可以使用官方的配置清單部署。 19 | 20 | ```shell 21 | kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml 22 | ``` 23 | 24 | ## 修改服務的配置清單,啟動 Reloader 的檢查機制 25 | 26 | 如果你有一個 `Deployment`,只要在他的配置清單加上下方的 `annotations`,當這個 `Deployment` 使用的 `ConfigMap` 與 `Secret` 有更新時, 27 | 就會觸發這個 `Deployment` 的滾動更新。 28 | 29 | ```yaml 30 | kind: Deployment 31 | metadata: 32 | annotations: 33 | reloader.stakater.com/auto: "true" 34 | spec: 35 | template: 36 | metadata: 37 | ``` 38 | 39 | ## 參考資料 40 | 41 | - [GitHub - stakater/Reloader](https://github.com/stakater/Reloader) 42 | -------------------------------------------------------------------------------- /network/08-data-plane-and-control-plane.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Network 4 | nav_order: 8 5 | --- 6 | 7 | # Data Plane 與 Control Plane 8 | 9 | TL;DR。Data Plane (資料平面) 講的是資料傳輸的部分,讓封包從一個點傳送到另外一個點。 10 | Control Plane (控制平面) 講的是資料該如何傳輸的部分,它決定了封包在傳輸過程應該如何被轉發,以及如何根據網路變化做出反應。 11 | 12 | 當 Control Plane 制定好路由表,Data Plane 就是考慮該如何根據路由表將封包傳送到目的地。 13 | 14 | ## Control Plane 15 | 16 | 舉個例子,Border Gateway Protocol (BGP)、Intermediate System-to-Intermediate System (IS-IS) 與 Open Shortest Path First (OSPF) 都是很常見的 Control Plane 協定。 17 | 18 | ## Data Plane 19 | 20 | 俺就只負責送資料,看你要用實體線路送,還是用 Wi-Fi。我會依照 Control Plane 制定的規則來送資料。 21 | 22 | ## Data Plane 與 Control Plane 應該分開 23 | 24 | 在設計上,Data Plane 與 Control Plane 應該分開,並分別實作 HA 與保持彈性。 25 | 26 | 當 Control Plane 發生問題時,Data Plane 依然能夠正常運作,反之亦然。 27 | 28 | 舉例來說,當有個 Load Balancer (Control Plane) 出問題,設計上應該確保這不會影響到資料的傳輸, 29 | 因為傳輸可能會轉給另外一個 Load Balancer 來處理。 30 | 31 | ## 參考資料 32 | 33 | - [Control plane vs. data plane](https://www.ibm.com/think/topics/control-plane-vs-data-plane) 34 | -------------------------------------------------------------------------------- /aws/01-aws-cli.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 1 5 | --- 6 | 7 | # AWS CLI 8 | 9 | AWS CLI 是一個用來操作 AWS 的指令列工具,可以用來建立還有管理 EC2、S3、IAM 等服務。 10 | 11 | ## 安裝 12 | 13 | 在 Mac 上可以透過 Homebrew 安裝: 14 | 15 | ```bash 16 | brew install awscli 17 | ``` 18 | 19 | ## 設定權限 20 | 21 | 要使用 AWS CLI 操作 AWS 服務,必須要有一組 Access Key 跟 Secret Key,可以在 AWS Console 的 IAM 服務裡面建立。然後在本機上執行下面的指令設定 Key: 22 | 23 | ```bash 24 | aws configure 25 | ``` 26 | 27 | 這個指令會建立 `~/.aws/credentials` 跟 `~/.aws/config` 兩個檔案,分別用來存放 Key 跟其他設定。 28 | 29 | ## S3 30 | 31 | 列出所有 S3 bucket: 32 | 33 | ```bash 34 | aws s3 ls 35 | ``` 36 | 37 | 從雲端上下載檔案可以使用 `cp` 指令,例如下載檔案到本機上: 38 | 39 | ```bash 40 | aws s3 cp s3://bucket-name/file-name . 41 | ``` 42 | 43 | 上傳檔案到雲端: 44 | 45 | ```bash 46 | aws s3 cp s3://bucket-name 47 | ``` 48 | 49 | 可以使用 sync 指令同步本機跟雲端的檔案,例如下面的指令會把本機上的檔案同步到雲端: 50 | 51 | ```bash 52 | aws s3 sync s3://bucket-name 53 | ``` 54 | 55 | 也可以同步雲端上面的兩個 bucket: 56 | 57 | ```bash 58 | aws s3 sync s3://bucket-name1 s3://bucket-name2 59 | ``` 60 | -------------------------------------------------------------------------------- /aws/07-route53.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 7 5 | --- 6 | 7 | # Route53 8 | 9 | 為 AWS 販售並管理域名的服務。 10 | 11 | ## SAA 筆記 12 | 13 | - 這是個全球服務。 14 | - Route 53 Alias Record 可以將流量導向至 AWS 資源,背後使用 A Record (讓 FQDN 指向 IP)。 15 | - Route 53 可以藉由 Health Check 來設定 Failover Routing Policy Configuration: 16 | - 要設定 NACL (Network Access Control List) 允許 Route 53 對目標發送 Health Check 的請求。 17 | - Route 53 的 Evaluate Target Health 要設定為 yes。 18 | - AWS Route53 Health Checking 提供兩種 Failover 設定 19 | - Active-Active Failover:確保所有資源都是可行的,如果發現某資源不健康,就會停止將流量轉過去該資源 20 | - Active-Passive Failover:有一個 Primary 與 Secondary 資源,Secondary 資源會是 Stand By 的狀態,只有當 Primary 無法,才會將流量轉送至 Secondary 的資源。 21 | - Route 53 有幾種 Routing: 22 | - Latency Routing:根據最低 Latency 提供服務,注意最低延遲不一定來自於同一區。 23 | - Geoproximity Routing:根據"**用戶與服務的地理位置**提供服務,且提供調整 bias,將較多或較少的流量引導到你想要的地區。 24 | - Geolocation Routing:根據"**用戶的地理位置**提供服務,不提供調整 bias。 25 | - Weighted Routing:主要用在單一域名但需要指向多個資源的情況,可以設定流量轉發的權重。可以做到跨 Region LB 或是測試新功能。 26 | - CloudWatch Events 無法直接監控 Route 53 端點的狀態。 27 | -------------------------------------------------------------------------------- /pest/10-exception.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Pest 4 | nav_order: 10 5 | --- 6 | 7 | # 斷定是否會拋出例外 (Exception) 8 | 9 | 如果要測試一個流程在遭遇問題時是否會拋出例外 (Exception),斷定中也有 `expectException()` 的方法可以使用 10 | 11 | ```php 12 | it('can validate an email', function () { 13 | // 如果預計這個測試會拋出例外,我們可以使用這個方法來進行斷定 14 | // 注意這個方法必須放在測試中的最上方 15 | $this->expectException(InvalidArgumentException::class); 16 | 17 | $rule = new IsValidEmailAddress(); 18 | 19 | $rule->passes('email', 123); 20 | }); 21 | ``` 22 | 23 | Pest 為這種情況提供一個更直覺的方法 `throws()` 24 | 25 | ```php 26 | it('can validate an email', function () { 27 | $rule = new IsValidEmailAddress(); 28 | 29 | $rule->passes('email', 123); 30 | }) 31 | ->throws(InvalidArgumentException::class); 32 | ``` 33 | 34 | 除了斷定丟出哪一種例外,也可以對例外的錯誤訊息進行斷定,就算例外的類型對上了,只要訊息不對,斷定還是會失敗 35 | 36 | ```php 37 | it('can validate an email', function () { 38 | $rule = new IsValidEmailAddress(); 39 | 40 | $rule->passes('email', 123); 41 | }) 42 | ->throws(InvalidArgumentException::class, 'The value must be a string'); 43 | ``` 44 | -------------------------------------------------------------------------------- /php/05-install-php.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: PHP 4 | nav_order: 5 5 | --- 6 | 7 | # 安裝 PHP 8 | 9 | 記錄如何在各個系統上安裝 PHP 開發環境。 10 | 11 | ## MacOS 12 | 13 | Mac 上最推薦使用 Homebrew 安裝 PHP,並使用 Laravel Valet 來設定 Laravel 的開發環境。 14 | 15 | ```shell 16 | # 使用 homebrew 安裝 php 17 | brew install php 18 | 19 | # 使用 composer 安裝 laravel valet 20 | composer global require laravel/valet 21 | 22 | # 想使用 valet 指令需要先確保 ~/.composer/vendor/bin 有加入環境變數中 23 | # valet 會使用 homebrew 來安裝 nginx 與 dnsmasq,因此需要 sudo 權限 24 | sudo valet install 25 | 26 | # 如果不想要每次執行 valet 指令都使用 sudo,可以將其加入 sudoers.d 中 27 | # valet 會在 /private/etc/sudoers.d 加入 valet 與 brew 兩個使用者 28 | sudo valet trust 29 | ``` 30 | 31 | 建議可以使用 [PHP Monitor](https://phpmon.app/) 這個工具來查看 Valet 的狀態、 32 | 調整 PHP 的設定與**管理 PHP Extension**。 33 | 34 | ```shell 35 | # 安裝 php monitor 36 | brew tap nicoverbruggen/homebrew-cask 37 | brew install phpmon --cask 38 | 39 | # 如果想透過 php monitor 來安裝 php extension,需要先引入第三方的 php extension 庫 40 | brew tap shivammathur/extensions 41 | ``` 42 | 43 | 啟動 PHP Monitor 之後,就可以很清楚地看到各種 PHP 相關的設定,也能很方便的進行調整。 44 | -------------------------------------------------------------------------------- /k8s/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 7 5 | --- 6 | 7 | # Kubernetes (K8s) 8 | 9 | 一直想學習如何使用 k8s,因此計畫自己在雲端上面開一些機器然後搭建一個 k3s 叢集, 10 | 並將自己的部落格 (Laravel App) 轉移到 k3s 叢集上。 11 | 12 | > k3s 為輕量版的 k8s,也是 CNCF 的專案之一,在使用上與 k8s 幾乎相同。 13 | 14 | ## 計畫 15 | 16 | 搭建好叢集之後預計做一些項目來練習如何使用 k8s。 17 | 18 | - 將自己的部落格搬移到 k8s 上。 19 | - 在 k8s 上面部署 Argo CD,可以透過 Argo CD 更新與部署部落格。 20 | 21 | ## 架構 22 | 23 | 與前輩討論後,便規劃了下面的網路架構。 24 | 25 | ![k8s architecture](https://allen-files.s3.ap-northeast-1.amazonaws.com/images/k8s/k8s-architecture.jpg) 26 | 27 | - 在一個 VPC 底下,有兩個 subnet,一個是可以與外部直接連線的 public subnet,一個是只能透過 NAT 與外部連線的 private subnet。 28 | - Public subnet 底下有一個用 nginx 做的 proxy。 29 | - 想使用 SSH 遠端連線到 private subnet 底下的機器時,需要透過 proxy 當作 SSH 的跳板。 30 | - 因為 k3s 叢集放在 private subnet,所以外部無法直接訪問,如果想訪問叢集上的服務,會透過 proxy 做請求上的轉發。 31 | - 想在本地端使用 `kubectl` 操作 k3s 叢集時,也會透過 proxy 做請求上的轉發。 32 | 33 | ```nginx 34 | stream { 35 | server { 36 | listen 6443; 37 | proxy_pass 10.0.1.10:6443; 38 | } 39 | } 40 | ``` 41 | 42 | > Kubectl 本身就是使用 TLS 加密,因此不需要在 nginx 上額外設定憑證,只需要單純轉發請求就好。 43 | -------------------------------------------------------------------------------- /rust/32-control-how-tests-are-run.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Rust 4 | nav_order: 32 5 | --- 6 | 7 | # 控制程式如何執行 8 | 9 | 就跟 `cargo run` 一樣,`cargo test` 也會產生用於測試的執行檔,並執行它。 10 | 11 | ## 平行或接續執行測試 12 | 13 | 預設情況下,測試會並行執行,這樣可以加快測試速度。如果你的測試需要使用到共享資源,例如檔案或網路連線,並行執行可能會導致測試失敗。你可以使用 `--test-threads` 參數來控制測試執行緒數量。 14 | 15 | ```bash 16 | cargo test -- --test-threads=1 17 | ``` 18 | 19 | ## 顯示輸出 20 | 21 | 在測試中,如果測試是成功的,是無法看到 `println!` 輸出的,只有失敗的測試會顯示。 22 | 23 | 如果你想要在成功的測試看到輸出,可以使用 `--show-output` 參數。 24 | 25 | ```bash 26 | cargo test -- --show-output 27 | ``` 28 | 29 | ## 透過名稱來執行部分測試 30 | 31 | 如果你想要執行特定名稱的測試,可以在參數 `cargo test` 後面加上測試的名稱。 32 | 33 | ```bash 34 | cargo test add 35 | ``` 36 | 37 | 這樣測試只會執行函式名稱包含 `add` 的測試。 38 | 39 | ## 忽略測試 40 | 41 | 對於想忽略不執行的測試,可以在測試函式上加上 `#[ignore]`。 42 | 43 | 這樣當執行 `cargo test` 時,`expensive_test` 這個測試就不會被執行。 44 | 45 | ```rust 46 | #[test] 47 | fn it_works() { 48 | assert_eq!(2 + 2, 4); 49 | } 50 | 51 | #[test] 52 | #[ignore] 53 | fn expensive_test() { 54 | // 會執行一小時的程式碼 55 | } 56 | ``` 57 | 58 | 如果想執行被忽略的測試,可以加上參數 `--ignored`。 59 | 60 | ```bash 61 | cargo test -- --ignored 62 | ``` 63 | -------------------------------------------------------------------------------- /ansible/05-handlers.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Ansible 4 | nav_order: 5 5 | --- 6 | 7 | # Handlers 8 | 9 | 在 Ansible 中,你可以根據狀態是否變化,來觸發一些額外的操作。 10 | 11 | ## 範例 12 | 13 | ```yaml 14 | --- 15 | - name: Example of no-handler rule 16 | hosts: localhost 17 | tasks: 18 | - name: Register result of a task 19 | ansible.builtin.lineinfile: 20 | dest: "/tmp/example.txt" 21 | line: "Hi from Ansible!" 22 | check_mode: true # 根據檔案是否有 Hi from Ansible! 字串回傳 changed 屬性(沒有的話回傳 true) 23 | notify: # 如果 changed 屬性為 true 則依序執行下面兩個操作 24 | - Second command to run 25 | - Third command to run 26 | 27 | handlers: 28 | - name: Second command to run 29 | ansible.builtin.debug: 30 | msg: The placeholder file was modified! 31 | 32 | - name: Third command to run 33 | ansible.builtin.debug: 34 | msg: The placeholder file was modified! 35 | ``` 36 | 37 | ## 參考資料 38 | 39 | - [Handlers: running operations on change](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html#handlers) 40 | - [Ansible Lint - no-handler](https://ansible.readthedocs.io/projects/lint/rules/no-handler/) 41 | -------------------------------------------------------------------------------- /python/02-serial-number.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Python 4 | nav_order: 2 5 | --- 6 | 7 | # 從憑證取得 Serial Number 8 | 9 | 你可以使用 Python 從公有憑證中取得 Serial Number。 10 | 11 | 簡單的範例程式如下: 12 | 13 | ```python 14 | import re 15 | from cryptography import x509 16 | 17 | 18 | def is_pem_format(cert: str): 19 | return re.search( 20 | r"^(-----BEGIN CERTIFICATE-----)[\S\s]*(-----END CERTIFICATE-----)$", cert 21 | ) 22 | 23 | 24 | def get_serial_number_from_certificate(cert: str): 25 | """ 26 | calculate the certificate serial number 27 | ref: https://github.com/Azure/azure-sdk-for-python/issues/16965 28 | """ 29 | if is_pem_format(cert) is False: 30 | raise Exception("Sorry, certificate is not correct pem format.") 31 | 32 | cert = x509.load_pem_x509_certificates(bytes(cert, "utf-8")) 33 | serial = cert[0].serial_number 34 | serial_number = f"{serial:x}".lower() 35 | 36 | return serial_number 37 | 38 | 39 | with open("cert.pem", "r") as cert: 40 | serial_number = get_serial_number_from_certificate(cert.read()) 41 | print(serial_number) 42 | ``` 43 | 44 | > 為什麼特地寫這一段,因為 Azure Key Vault 的 Certificate API 居然沒有回傳 Serial Number! 45 | -------------------------------------------------------------------------------- /rust/37-box.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Rust 4 | nav_order: 37 5 | --- 6 | 7 | # 使用 `Box` 指向堆積上的資料 8 | 9 | Rust 中有一個智慧指標功能叫做 Box。 10 | 11 | **Box 允許你將資料儲存到堆積 (Heap) 上。同時會有一個堆疊 (Stack) 儲存指向堆積資料的指標 (Pointer)**。 12 | 13 | ```rust 14 | fn main() { 15 | let b = Box::new(5); 16 | println!("b = {}", b); 17 | } // b 在這裡被釋放。堆積上的值會被釋放,同時指向堆積的指標也會被釋放。 18 | ``` 19 | 20 | Box 在遞迴資料結構中非常有用,因為它允許你的資料有一個已知的大小 (因為資料是一個固定的指標)。 21 | 22 | 一般的遞迴資料結構會有不確定的大小,因為它的大小取決於遞迴的深度。 23 | 24 | ```rust 25 | enum List { 26 | Cons(i32, List), 27 | Nil, 28 | } 29 | 30 | use List::{Cons, Nil}; 31 | 32 | fn main() { 33 | // 這樣的寫法會造成編譯錯誤 34 | // 每個 Cons 的大小是不確定的,因為每個 Cons 都包含另一個 List,而這個 List 又包含另一個 Cons,以此類推 35 | // 因此編譯器無法判別出它需要多少空間才能儲存一個 List 的數值 36 | let list = Cons(1, Cons(2, Cons(3, Nil))); 37 | } 38 | ``` 39 | 40 | 我們可以使用 `Box` 來解決這個問題,因為 `Box` 的指標有一個已知的大小 41 | 42 | ```rust 43 | enum List { 44 | Cons(i32, Box), 45 | Nil, 46 | } 47 | 48 | use List::{Cons, Nil}; 49 | 50 | fn main() { 51 | // Cons 變體需要的大小為 i32 加上儲存 Box 指標的空間 52 | // 這樣的寫法就不會造成編譯錯誤,因為 Cons 變體的大小是已知的 53 | let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))); 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /docker/05-proxy.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Docker 4 | nav_order: 5 5 | --- 6 | 7 | # 使用自己的 Proxy 8 | 9 | 部分公司較為嚴謹,內部伺服器會要求使用公司的 proxy 來對外連線,這時候就需要修改伺服器系統預設的 proxy。 10 | 11 | 我們可以在 `.bashrc` 或是 `/etc/environment` 中設定環境變數來修改 proxy,例如: 12 | 13 | ```bash 14 | export HTTP_PROXY=http://proxy.example.com:8888 15 | export HTTPS_PROXY=http://proxy.example.com:8888 16 | ``` 17 | 18 | 但這麼做你會發現 `docker pull` 還是會失敗,**因為 Docker 的 Daemon 並不會去讀取系統的環境變數**。 19 | 20 | 我們需要在 `/etc/systemd/system/docker.service.d/` 中建立一個 `http-proxy.conf` 檔案,內容如下: 21 | 22 | ```conf 23 | [Service] 24 | Environment="HTTP_PROXY=http://proxy.example.com:8888" 25 | Environment="HTTPS_PROXY=http://proxy.example.com:8888" 26 | ``` 27 | 28 | 接著重新啟動 Docker Daemon: 29 | 30 | ```bash 31 | sudo systemctl daemon-reload 32 | sudo systemctl restart docker 33 | ``` 34 | 35 | 別忘記啟動的 container 也要使用 `--env` 參數來設定環境變數,否則 container 內無法對外連線: 36 | 37 | ```bash 38 | docker run \ 39 | --env HTTP_PROXY=http://proxy.example.com:8888 \ 40 | --env HTTPS_PROXY=http://proxy.example.com:8888 \ 41 | -it ubuntu:20.04 bash 42 | ``` 43 | 44 | ## 參考資料 45 | 46 | - [How to use proxy in Dockerfile](https://stackoverflow.com/questions/23111631/how-to-use-proxy-in-dockerfile) 47 | -------------------------------------------------------------------------------- /azure/05-service-principal.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Azure 4 | nav_order: 5 5 | --- 6 | 7 | # Service Principal 8 | 9 | ## 使用 Azure CLI 建立一個 Service Principal 給 Terraform 部署資源 10 | 11 | > 必須先安裝 Azure CLI 12 | 13 | ```bash 14 | az ad sp create-for-rbac --name terraform --role Owner --scopes /subscriptions/ 15 | ``` 16 | 17 | 之後將產生的 app id 與 secret key 放到環境變數中,可以在 `.bashrc` 中設定 18 | 19 | ```bash 20 | export ARM_SUBSCRIPTION_ID="" 21 | export ARM_TENANT_ID="" 22 | export ARM_CLIENT_ID="" 23 | export ARM_CLIENT_SECRET="" 24 | ``` 25 | 26 | 要刪除 service principal,可以使用下方的指令 27 | 28 | ```bash 29 | az ad sp delete --id 30 | ``` 31 | 32 | ## 參考資料 33 | 34 | - [Configure Terraform in Azure Cloud Shell with Bash](https://learn.microsoft.com/en-us/azure/developer/terraform/get-started-cloud-shell-bash?tabs=bash) 35 | - [Azure | Creating an Azure Service Principal using Azure Portal](https://www.youtube.com/watch?v=Kf1Tai_BkWU) 36 | - [Application and service principal objects in Azure Active Directory](https://learn.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals) 37 | -------------------------------------------------------------------------------- /git/06-update-from-original-repo.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Git 4 | nav_order: 6 5 | --- 6 | 7 | # 跟上原始專案的更新 8 | 9 | 如果你的專案是從某一個專案 fork 出來的,當原始專案有更新時,你可以使用 `git pull` 來跟上原始專案的更新。 10 | 11 | 首先列出專案的遠端節點,通常只有一個 `origin`,也就是你 fork 出來的專案。 12 | 13 | ```bash 14 | git remote -v 15 | 16 | # origin git@github.com:yilanboy/starter-kit.git (fetch) 17 | # origin git@github.com:yilanboy/starter-kit.git (push) 18 | ``` 19 | 20 | 然後加入原始專案的遠端節點,遠端節點的名稱可以自行命名,我這裡使用 `upstream`。 21 | 22 | ```bash 23 | git remote add upstream https://github.com/original-repo/starter-kit.git 24 | ``` 25 | 26 | 再次列出專案的遠端節點,可以看到多了一個 `upstream`。 27 | 28 | ```bash 29 | git remote -v 30 | 31 | # upstream https://github.com/original-repo/starter-kit.git (fetch) 32 | # upstream https://github.com/original-repo/starter-kit.git (push) 33 | # origin git@github.com:yilanboy/starter-kit.git (fetch) 34 | # origin git@github.com:yilanboy/starter-kit.git (push) 35 | ``` 36 | 37 | 接下來就可以使用 `gut fetch` 來下載原始專案的更新了。 38 | 39 | ```bash 40 | git fetch upstream 41 | 42 | # 合併原始專案的更新到當前分支 43 | git merge upstream/main 44 | 45 | # 推送到自己的遠端專案 46 | git push origin main 47 | ``` 48 | 49 | ## 參考資料 50 | 51 | - [為你自己學 Git - 怎麼跟上當初 fork 專案的進度?](https://gitbook.tw/chapters/github/syncing-a-fork) 52 | -------------------------------------------------------------------------------- /docker/08-logging-drivers.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Docker 4 | nav_order: 8 5 | --- 6 | 7 | # Logging Drivers 8 | 9 | Docker 本身可以使用多種不同的 Logging Drivers 來記錄容器輸出的日誌。 10 | 11 | Docker 預設的 Logging Driver 是 `json-file`。也就是簡單的將日誌以 JSON 格式儲存在容器內部。 12 | 13 | 你可以用下面的指令查看目前的 Logging Driver: 14 | 15 | ```bash 16 | docker info --format '{{.LoggingDriver}}' 17 | ``` 18 | 19 | ## Local Logging Driver 20 | 21 | 你可以使用 `local` Logging Driver 來避免容器日誌量過大的問題,因為容器預設不會執行 Log Rotation,所以日誌會隨著時間越來越肥大。 22 | 23 | `local` Logging Driver 會自動執行 Log Rotation,所以會比 `json-file` 快更適合當作預設的 Logging Driver。 24 | 25 | > [!NOTE] 26 | > 27 | > Q:為什麼 Docker 不使用 `local` 當作預設的 Logging Driver? 28 | > 29 | > A:主要是為了與舊版本兼容。 30 | 31 | 你可以編輯 `~/.docker/daemon.json` 來預設使用 `local` Logging Driver。 32 | 33 | ```json 34 | { 35 | "log-driver": "local", 36 | "log-opts": { 37 | "max-size": "10m" 38 | } 39 | } 40 | ``` 41 | 42 | 也可以在啟動容器時透過參數指定 Logging Driver。 43 | 44 | ```bash 45 | docker run \ 46 | --log-driver local --log-opt max-size=10m \ 47 | alpine echo hello world 48 | ``` 49 | 50 | ## 參考資料 51 | 52 | - [Configure logging drivers](https://docs.docker.com/engine/logging/configure/) 53 | - [Local file logging driver](https://docs.docker.com/engine/logging/drivers/local/) 54 | -------------------------------------------------------------------------------- /svelte/19-webstorm-settings.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 19 5 | --- 6 | 7 | # WebStorm IDE 設定 8 | 9 | 目前寫 SvelteKit 是用 JetBrains 的 WebStorm 來進行開發。這裡記錄一些對於 WebStorm 的設定。 10 | 11 | ## 調整重複程式碼的偵測範圍 12 | 13 | 在寫 SvelteKit 中的 `+page.server.ts` 時,發現會莫名其妙的出現 _重複程式碼行數過多_ 的提醒。 14 | 看了一下才發現原來 WebStorm 也將 `.svelte-kit` 資料夾底下的檔案納入檢查的範圍。 15 | 但這個資料夾是 SvelteKit 自動產生的,照理說不應該納入檢查的範圍才對。 16 | 17 | 這個檢查的範圍可以進行調整。 18 | 19 | 首先在設定中找到 _Editor -> Inspections -> General -> Duplicate code fragment_。 20 | 21 | 點開 _Scope_ 下拉選單,並選擇 _Edit Scopes Order..._ 來新增自己想要的檢查範圍 22 | 23 | ![change-duplicate-code-fragment-01](./images/change-duplicate-code-fragment-01.png) 24 | 25 | 點擊鉛筆圖示來新增檢查範圍。 26 | 27 | ![change-duplicate-code-fragment-02](./images/change-duplicate-code-fragment-02.png) 28 | 29 | 新增一個叫做 `SvelteKit` 的範圍,並輸入 `file:src/*`。指定只檢查 `src` 資料夾底下的檔案。 30 | 31 | ![change-duplicate-code-fragment-03](./images/change-duplicate-code-fragment-03.png) 32 | 33 | 在 _Scope_ 選擇剛剛建立的範圍 `SvelteKit`。並取消 `Everywhere else` 這個範圍。 34 | 35 | ![change-duplicate-code-fragment-04](./images/change-duplicate-code-fragment-04.png) 36 | 37 | ## 參考資料 38 | 39 | - [WebStorm Document - Locate duplicates](https://www.jetbrains.com/help/webstorm/analyzing-duplicates.html#configure-inspection) 40 | -------------------------------------------------------------------------------- /github/02-outputs.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: GitHub 4 | nav_order: 2 5 | --- 6 | 7 | # Defining Outputs for Jobs 8 | 9 | 如果你想設定一個變數讓後續的 Job 使用,可以使用 GitHub Action 提供的 `GITHUB_OUTPUT` 環境變數。 10 | 11 | ## 範例 12 | 13 | ```yaml 14 | jobs: 15 | get-the-version-number-from-tag-name: 16 | name: Get the version number from tag name 17 | runs-on: ubuntu-latest 18 | # 3. 根據 step id 抓取 output 19 | outputs: 20 | version: ${{ steps.get-the-version-number.outputs.version }} 21 | steps: 22 | - name: Get the version number from tag name 23 | # 1. 需要在 step 上設定 id 24 | id: get-the-version-number 25 | # 2. 將變數設定放入 GITHUB_OUTPUT 26 | run: | 27 | echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT 28 | 29 | print-the-version-number: 30 | needs: get-the-version-number-from-tag-name 31 | name: Print the version number 32 | runs-on: ubuntu-latest 33 | env: 34 | APP_VERSION: ${{ needs.get-the-version-number-from-tag-name.outputs.version }} 35 | steps: 36 | - name: Print the version number 37 | run: | 38 | echo ${{ env.APP_VERSION }} 39 | ``` 40 | 41 | ## 參考資料 42 | 43 | - [Defining Outputs for Jobs](https://docs.github.com/en/actions/using-jobs/defining-outputs-for-jobs) 44 | -------------------------------------------------------------------------------- /pest/04-refreash-database-trait.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Pest 4 | nav_order: 4 5 | --- 6 | 7 | # 使用 RefreshDatabase Trait 重置資料庫 8 | 9 | 通常在測試時,我們很常使用 `RefreshDatabase` 這個 Trait 來重置整個資料庫,方便進行測試 10 | 11 | 在 Pest 中,因為已經沒有 `class` 宣告,我們無法使用 trait 的方式引入 `RefreshDatabase`,所以我們必須換個方式,使用 uses() 12 | 13 | ```php 14 | use Illuminate\Foundation\Testing\RefreshDatabase; 15 | 16 | uses(RefreshDatabase::class); 17 | 18 | test('can view contents', function () { 19 | // ... 20 | }); 21 | ``` 22 | 23 | 如果你的每個測試都需要 `uses(RefreshDatabase::class)`,你可以考慮在 `tests/TestCase.php` 中引入 `RefreshDatabase` 24 | 25 | ```php 26 | namespace Tests; 27 | 28 | use Illuminate\Foundation\Testing\TestCase as BaseTestCase; 29 | use Illuminate\Foundation\Testing\RefreshDatabase; 30 | 31 | abstract class TestCase extends BaseTestCase 32 | { 33 | use CreatesApplication; 34 | 35 | use RefreshDatabase; 36 | } 37 | ``` 38 | 39 | 為了有更好的測試速度,你可以使用 `LazilyRefreshDatabase`,當測試動到資料庫時,才會重置資料庫 40 | 41 | ```php 42 | namespace Tests; 43 | 44 | use Illuminate\Foundation\Testing\TestCase as BaseTestCase; 45 | use Illuminate\Foundation\Testing\LazilyRefreshDatabase; 46 | 47 | abstract class TestCase extends BaseTestCase 48 | { 49 | use CreatesApplication; 50 | 51 | use LazilyRefreshDatabase; 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /svelte/08-motion.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 8 5 | --- 6 | 7 | # Motion (動態效果) 8 | 9 | ## Tweens 10 | 11 | Svelte 提供了 `tweened` 這個函式,可以簡單的建立一個由 A 轉變至 B 的平滑動畫。 12 | 13 | 以下方的 progress bar 為例,使用點擊按鈕來改變 progress bar 的進度。可以發現進度條的變化有一個簡易的動畫效果。 14 | 15 | ```svelte 16 | 21 | 22 | 23 | 24 | 27 | 28 | 31 | ``` 32 | 33 | 還可以使用 `svelte/easing` 來增加其他動畫效果。 34 | 35 | ```svelte 36 | 45 | ``` 46 | 47 | ## Spring 48 | 49 | `spring` 功能與 `tweened` 類似,提供了一種 Q 彈的效果動畫,`spring` 更適合時常變更值的場景。 50 | 51 | ```svelte 52 | 62 | ``` 63 | -------------------------------------------------------------------------------- /linux/07-sockets.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Linux 4 | nav_order: 7 5 | --- 6 | 7 | # 什麼是 Sockets 8 | 9 | Sockets 是作業系統為了不同進程之間的溝通而提供的一層抽象層,不論是在同一台機器上還是透過網路跨越多台機器。 10 | 11 | Socket = IP Address + Port Number,可以用來標識網路上的一個通訊端點。 12 | 13 | > 所以 192.168.1.5:22 就是一個 Socket。 14 | 15 | Socket 運作在 OSI 模型的傳輸層(Layer 4),會將資料打包成 TCP(Transmission Control Protocol) 或 UDP(User Datagram Protocol)封包,並透過網路層(Layer 3)傳送到目的地。 16 | 所以 TCP 與 UDP 也是 Socket 的主要通訊協定。 17 | 18 | 除了網路,Socket 也可以用於同一台機器上的進程間通訊(Inter-Process Communication, IPC),例如 Unix Domain Sockets(簡稱 UDS)。UDS 的速度通常比透過網路的 Socket 快,例如 PostgreSQL 與 Redis 的客戶端指令工具都是使用 UDS。 19 | 20 | UDS 不使用 IP Address 與 Port Number,而是使用檔案系統中的路徑來標識通訊端點,例如 `/var/run/postgresql/.s.PGSQL.5432` 或者是 `/tmp/app.sock`,所以速度會比透過網路的 Socket 快很多。 21 | 22 | ## 什麼是 Anonymous Pipes? 23 | 24 | Anonymous Pipes(匿名管道)是一種用於在同一台機器上的不同進程之間進行通信的機制。它們通常用於父子進程之間的數據傳輸。匿名管道是單向的,意味著數據只能從一個端點流向另一個端點。它們不需要命名,因此只能在創建它們的進程及其子進程之間使用。 25 | 26 | ## 什麼是 Ephemeral Ports? 27 | 28 | Ephemeral Ports(臨時端口)是操作系統在需要時動態分配給應用程序的短暫端口號。這些端口號通常用於客戶端應用程序在與服務器建立連接時使用。Ephemeral Ports 的範圍通常在 49152 到 65535 之間,但具體範圍可能因操作系統而異。當應用程序關閉連接後,這些端口號會被釋放並可供其他應用程序使用。 29 | 30 | ## 什麼是 File Descriptor? 31 | 32 | File Descriptor(文件描述符)是操作系統用來表示打開的文件、Socket 或其他輸入/輸出資源的整數標識符。在 Unix 和類 Unix 系統中,文件描述符是非負整數,通常從 0 開始分配。標準輸入、標準輸出和標準錯誤分別對應文件描述符 0、1 和 2。文件描述符允許程序通過統一的接口來讀寫不同類型的資源。 33 | -------------------------------------------------------------------------------- /linux/05-last.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Linux 4 | nav_order: 5 5 | --- 6 | 7 | # last 指令 8 | 9 | last 指令可以用來檢查系統用戶的登入記錄。 10 | 11 | ```bash 12 | last 13 | ``` 14 | 15 | 指令結果如下: 16 | 17 | ```text 18 | ubuntu pts/2 61.220.176.180 Fri Aug 9 06:56 still logged in 19 | ubuntu pts/2 61.220.176.180 Fri Aug 9 06:08 - 06:09 (00:00) 20 | ubuntu pts/2 61.220.176.180 Fri Aug 9 05:42 - 05:43 (00:01) 21 | ubuntu pts/2 61.220.176.180 Fri Aug 9 05:40 - 05:41 (00:00) 22 | ubuntu pts/0 3.114.176.187 Fri Aug 9 05:38 still logged in 23 | reboot system boot 6.8.0-1010-azure Fri Aug 9 04:04 still running 24 | reboot system boot 6.8.0-1001-azure Fri Aug 9 03:53 - 04:04 (00:11) 25 | 26 | wtmp begins Fri Aug 9 03:53:14 2024 27 | ``` 28 | 29 | 你可以指定查看某一用戶的登入記錄: 30 | 31 | ```bash 32 | last ubuntu 33 | ``` 34 | 35 | 或是指定只想看前幾筆的紀錄: 36 | 37 | ```bash 38 | last -n 5 39 | ``` 40 | 41 | last 也可以用來檢查開機的時間: 42 | 43 | ```bash 44 | last reboot 45 | ``` 46 | 47 | `last` 預設是從 `/var/log/wtmp` 這個記錄檔案取得使用者登入的資料。 48 | 49 | 因為系統都會有 logrotate 服務定期清空記錄檔案並將舊紀錄移到其他檔案存放。這會導致 `last` 看不到比較舊的資料,此時可以用 `-f` 參數指定要查詢的記錄檔案路徑: 50 | 51 | ```bash 52 | last -f /var/log/wtmp.1 53 | ``` 54 | 55 | ## 參考資料 56 | 57 | - [Linux 使用 last 指令檢查使用者登入記錄教學與範例](https://officeguide.cc/linux-last-command-tutorial-examples/) 58 | -------------------------------------------------------------------------------- /docker/06-custom-command.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Docker 4 | nav_order: 6 5 | --- 6 | 7 | # 使用 Docker Container 來製作自己的指令 8 | 9 | 我不太想為了 `pg_dump` 安裝 `PostgreSQL` 資料庫 ,所以就打算使用 Docker Container 來製作自己的 `pg_dump` 指令。首先新增一個檔案 `pg_dump.sh` 10 | 11 | ```bash 12 | #!/bin/bash 13 | 14 | # -it:指示 Docker 容器在互動模式下執行並分配一個偽終端 15 | # --rm:指示 Docker 容器在退出時自動刪除 16 | # "$@":表示命令列參數。"$@" 會展開傳遞給 shell script 檔案的所有參數 17 | docker run -it --rm postgres:16.3 pg_dump "$@" 18 | ``` 19 | 20 | 幫 `pg_dump.sh` 加上執行權限。 21 | 22 | ```bash 23 | chmod a+x pg_dump.sh 24 | ``` 25 | 26 | 試著執行 `pg_dump.sh`。 27 | 28 | ```bash 29 | ./pg_dump.sh --version 30 | 31 | # 指令輸出結果如下 32 | # pg_dump (PostgreSQL) 16.3 (Debian 16.3-1.pgdg120+1) 33 | ``` 34 | 35 | 看能不能用 `pg_dump.sh` 來備份資料庫中的資料,找一個 PostgreSQL 資料庫試試看。 36 | 37 | ```bash 38 | ./pg_dump.sh --host='my-postgres-database.net' -d my_db --username='db_owner' -f db.sql 39 | ``` 40 | 41 | 輸入密碼之後,會發現 `db.sql` 並沒有出現,這是因為檔案是下載到容器中,而不是本地環境上。可以透過 Docker Volume 與 Work Dir 來解決這個問題。 42 | 43 | 修改一下 `pg_dump.sh` 的內容。 44 | 45 | ```bash 46 | #!/bin/bash 47 | 48 | # -v ${PWD}:/app:此參數將當前工作目錄掛載到容器內部的 /app 目錄。這意味著容器內部的 pg_dump 命令將能夠訪問你的當前工作目錄中的檔案。 49 | # -w /app:此參數將容器內部的工作目錄設定為 /app。這意味著 pg_dump 命令將在 /app 目錄中執行。 50 | docker run -it --rm -v ${PWD}:/app -w /app postgres:16.3 pg_dump "$@" 51 | ``` 52 | 53 | 再次使用 `pg_dump.sh` 來備份資料庫中的資料,就可以看到 `db.sql` 出現囉。 54 | -------------------------------------------------------------------------------- /ansible/07-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Ansible 4 | nav_order: 7 5 | --- 6 | 7 | # Template Module 8 | 9 | Ansible 的 Template 套件支援使用 Jinja Template,可以動態生成配置檔案。 10 | 11 | ## 基本用法 12 | 13 | Template 模組將 Jinja2 模板檔案轉換為目標主機上的檔案。 14 | 15 | ### 簡單範例 16 | 17 | 新增一個 `templates` 資料夾,並在其底下建立模板檔案 `nginx.conf.j2`: 18 | 19 | ```jinja2 20 | server { 21 | listen {{ nginx_port | default(80) }}; 22 | server_name {{ server_name }}; 23 | 24 | location / { 25 | root {{ web_root }}; 26 | index index.html; 27 | } 28 | } 29 | ``` 30 | 31 | 在 Playbook 中使用 template 模組: 32 | 33 | ```yaml 34 | - name: Deploy website nginx config 35 | ansible.builtin.template: 36 | src: ./templates/nginx.conf.j2 37 | dest: /etc/nginx/sites-available/{{ server_name }} 38 | owner: root 39 | group: root 40 | mode: "u=rw,g=r,o=r" 41 | vars: 42 | nginx_port: 8080 43 | server_name: example.com 44 | web_root: /var/www/html 45 | notify: restart nginx 46 | ``` 47 | 48 | ## 常用參數 49 | 50 | - `src`: 模板檔案路徑(相對於 templates/ 目錄) 51 | - `dest`: 目標檔案路徑 52 | - `owner`: 檔案擁有者 53 | - `group`: 檔案群組 54 | - `mode`: 檔案權限 55 | - `backup`: 是否備份原檔案(true/false) 56 | 57 | ## Jinja2 語法重點 58 | 59 | - `{{ variable }}`: 輸出變數值 60 | - `{% if condition %}...{% endif %}`: 條件判斷 61 | - `{% for item in list %}...{% endfor %}`: 迴圈 62 | - `{{ variable | default('default_value') }}`: 設定預設值 63 | -------------------------------------------------------------------------------- /vim/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | has_children: true 4 | nav_order: 21 5 | --- 6 | 7 | # Vim 8 | 9 | Vim 是一個很強大的編輯器,搭配多種快捷鍵,可以讓你的快速的編寫任何文件或是撰寫程式碼 10 | 11 | ## 模式 (Mode) 12 | 13 | Vim 有三種模式 14 | 15 | - Normal Mode (Keep Mode) 16 | - Insert Mode 17 | - Visual Mode 18 | 19 | ### Normal Mode 20 | 21 | 在 normal mode 底下無法編輯檔案,但可以輸入各種 vim 的快捷鍵 22 | 23 | ### Insert Mode 24 | 25 | 在 normal mode 底下輸入 `i` 或是 `a`,即可進入編輯模式,開始修改檔案的內容 26 | 27 | ### Visual Mode 28 | 29 | 在 normal mode 底下輸入 `v`,即可進入 visual mode,可以選取你想要的範圍已進行複製或是剪下 30 | 31 | ## 指令模式 32 | 33 | 在 normal mode 輸入 `:` 進入指令模式,可以輸入指令或修改 vim 的設定 34 | 35 | 例如,我想搜尋檔案的話,可以在輸入 `:/keyword`,就可以搜尋當前檔案的內容 36 | 37 | 如果我想要修改 vim 的設定,例如在編輯器中顯示行的數字,可以輸入 `:set number` 38 | 39 | 設定預設不會保留,如果想要儲存 vim 的設定可以建立一個檔案 `~/.vimrc`,然後將你要的檔案設定寫上 40 | 41 | ```vim 42 | syntax on 43 | colorscheme onedark 44 | 45 | set clipboard=unnamedplus 46 | set clipboard+=unnamed 47 | set number 48 | set rnu 49 | set smartindent 50 | set tabstop=4 51 | set shiftwidth=4 52 | set expandtab 53 | set backspace=indent,eol,start 54 | set scrolloff=8 55 | 56 | nmap zh ^ 57 | nmap zl $ 58 | nmap ,p "0p 59 | 60 | vmap < >gv 62 | ``` 63 | 64 | ## 參考資料 65 | 66 | - [Why doesn't the backspace key work in insert mode?](https://vi.stackexchange.com/questions/2162/why-doesnt-the-backspace-key-work-in-insert-mode) 67 | - [onedark.vim](https://github.com/joshdick/onedark.vim) 68 | -------------------------------------------------------------------------------- /google-cloud-platform/02-projects.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Google Cloud Platform 4 | nav_order: 2 5 | --- 6 | 7 | # Project 8 | 9 | 在 GCP 中,如果要建立資源,就需要先建立一個 project (專案),你可以將你的資源建立在專案中 10 | 11 | ## 建立專案 12 | 13 | 專案的名稱可以隨意自訂,不過 project id 必須是全球唯一性 (globally unique),建立之後還會獲得一組 project number 14 | 15 | > project id 在建立後不能修改 16 | 17 | 可以使用 gcloud CLI 來建立 project 18 | 19 | ```shell 20 | gcloud projects create my-project 21 | ``` 22 | 23 | 建立完成之後可以嘗試使用 `gcloud projects list` 指令查看目前建立了哪些 project 24 | 25 | ```shell 26 | $ gcloud projects list 27 | 28 | PROJECT_ID NAME PROJECT_NUMBER 29 | container-platform-123 container-platform 123456789012 30 | ``` 31 | 32 | ## 切換專案 33 | 34 | 你可以透過 gcloud CLI 來切換專案。 35 | 36 | ```shell 37 | gcloud config set project $MY_PROJECT_ID 38 | ``` 39 | 40 | ## 刪除專案 41 | 42 | 你可以使用 gcloud CLI 刪除專案 43 | 44 | ```shell 45 | gcloud projects delete my-project 46 | ``` 47 | 48 | 但要注意刪除專案為軟性刪除 (soft deleting),在**30 天之內**你都可以恢復 (restore) 已刪除的專案,可以上 GCP 主控台操作,也可以使用 gcloud CLI 的 restore 指令 49 | 50 | ```shell 51 | gcloud projects restore my-project 52 | ``` 53 | 54 | 專案在刪除後需要等待 30 天之後才會完全刪除,並沒有辦法立即刪除 55 | 56 | 此外 project id,**即使是在系統刪除專案之後,也無法重新使用**,假設你想保留 project id,你應該避免將專案刪除,而是只刪除 project 底下的資源 57 | 58 | ## 參考資料 59 | 60 | - [Creating and managing projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects) 61 | -------------------------------------------------------------------------------- /network/01-ca-certificate.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Network 4 | nav_order: 1 5 | --- 6 | 7 | # CA 憑證 8 | 9 | 紀錄使用 certbot 向 Let's Encrypt 申請網域 `example.com` 憑證的流程 10 | 11 | ## 證明網域所有權 12 | 13 | 1. 憑證管理軟體 (certbot) 會向 Let's Encrypt CA 發起申請 14 | 2. 憑證管理軟體會產生一組公私鑰,並將公鑰交給 CA 15 | 3. CA 會提供兩種挑戰,擇一即可,用來讓 Server 證明其確實擁有網域所有權 16 | - 在 `example.com` 下設定 DNS 紀錄 (dns-01) 17 | - 在 `http://example.com` 的特定路徑底下提供 HTTP 文件 (http-01) 18 | 4. 以 http-01 挑戰為例,CA 產生一組隨機數 (nonce) 交給憑證管理軟體,請它將這組隨機數使用私鑰簽名後寫入文件,並將文件放在網站上的特定路徑 19 | 5. 憑證管理軟體完成後會通知 CA 進行檢查 20 | 6. CA 會從網站上的特定路徑下載文件並確認內容 21 | 7. 驗證通過,剛剛的公私鑰會被用作「授權金鑰對」,並開始頒發憑證 22 | 23 | ## 頒發憑證 24 | 25 | 1. 憑證管理軟體發出憑證管理請求並用授權金鑰對簽名 26 | 2. 憑證管理軟體建立一個憑證簽署請求 (Certificate Signing Request, CSR),要求 CA 頒發憑證 27 | 3. CSR 通常會包含由另外一組私鑰加密的資料與其對應的公鑰,此外 CSR 會由授權金鑰進行簽名 28 | 4. 當 CA 收到請求後會檢查兩組簽名 29 | 5. 如果驗證成功,CA 會用 CSR 中的公鑰替 `example.com` 的憑證簽名,再將文件回傳給憑證管理軟體 30 | 31 | ## 註銷憑證 32 | 33 | 1. 憑證管理軟體使用授權金鑰幫助消請求簽名並發送給 CA 34 | 2. CA 確認過簽名後,便將註銷消息發布到 OCSP (Online Certificate Status Protocol) 伺服器,以便讓瀏覽器等有關程式知道該憑證已被註銷 35 | 36 | ## 筆記 37 | 38 | - CA 不會產生與保管私鑰,公私鑰皆由 Server 上的憑證管理軟體產生,避免惡意 CA 將私鑰另做它途 39 | 40 | ## 參考資料 41 | 42 | - [certbot - frequently asked questions](https://certbot.eff.org/faq) 43 | - [Let's encrypt 運作原理](https://letsencrypt.org/zh-tw/how-it-works/) 44 | - [What harm can a malicious CA do?](https://security.stackexchange.com/questions/61730/what-harm-can-a-malicious-ca-do) 45 | -------------------------------------------------------------------------------- /azure/06-data-explorer.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Azure 4 | nav_order: 6 5 | --- 6 | 7 | # Azure Data Explorer 8 | 9 | 記錄一下使用 Azure Data Explorer (以下簡稱 ADX)的過程。 10 | 11 | 前陣子公司在研究如何將地端的 Log 系統上雲,做了一些研究之後,發現 ADX 或許是我們可以考慮的解決方案之一。理由如下: 12 | 13 | - ADX 可接收的資料量很大。端看你要使用 streaming ingestion 或是 batch ingestion。 14 | - 公司內部的認證與 Azure AD 深度整合,因此在訪問 ADX 的權限控管上會比較好設定。 15 | - ADX 有提供 REST API 與 SDK,因此可以自己寫工具來存取資料。 16 | - ADX 內部的資料可以設定 retention policy,時間一到可以自動刪除資料,節省成本。 17 | - ADX 提供 Kusto Query Language (KQL) 讓用戶對資料進行操作,可以用來查詢資料,也可以結合 Power BI 來做資料視覺化。 18 | 19 | 雖然 ADX 看起來貌似不錯,但由於 ADX 會啟動一組 cluster 處理所有的 ingestion、data markup 與 user query。**所以即使你不使用,也需要負擔 cluster 運行的成本**。但另外一方面來說,即使 user query 的次數很頻繁,也不會因此增加費用。 20 | 21 | 總結來說,ADX 很適合用在存放大量的資料,且 query 次數相當頻繁的場景。 22 | 23 | ## Log 系統架構圖 24 | 25 | ![Log 系統架構圖](https://allen-files.s3.ap-northeast-1.amazonaws.com/images/azure/log-system-architecture.jpg) 26 | 27 | 簡單說明架構的設計: 28 | 29 | - Log 的來源大多為地端的 server。並由 fluent bit 送往 Azure。 30 | - 跟據合規性的要求,需要將 log 備份一段時間。因此 log 會先送至 blob storage 進行備份。 31 | - Blob storage 可以設定資料物件的 policy。根據保存的時間自動轉 tier,例如從 cool 轉成 archive,也可以根據時間自動刪除資料,以節省成本。 32 | - 當 log 被上傳至 blob storage,會觸發 event grid 通知 ADX 進行 ingestion。將資料倒入 ADX 中。 33 | - ADX 上也會設定 retention policy,根據時間自動刪除資料。我這裡設計是保存一個月,超過一個月的資料會自動刪除,以節省成本。 34 | 35 | > [!NOTE] 36 | > 37 | > Fluent bit 本身支援將資料送往 blob storage 或是 ADX,我之前嘗試過在 fluent bit 將資料複製一份同時送往 blog storage 與 ADX,但非常不穩定,時常發生掉資料的情況。 38 | -------------------------------------------------------------------------------- /ansible/03-variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Ansible 4 | nav_order: 3 5 | --- 6 | 7 | # Variables 8 | 9 | 在 playbook 中可以使用 `vars` 來定義變數,例如: 10 | 11 | ```yaml 12 | # playbook.yml 13 | - name: update apt packages 14 | hosts: web_servers 15 | become: true 16 | vars: 17 | package_name: nginx 18 | tasks: 19 | - name: install nginx 20 | ansible.builtin.apt: 21 | name: "{{ package_name }}" 22 | state: present 23 | ``` 24 | 25 | 你也可以在 inventory 中設定要給 host 使用的變數,例如: 26 | 27 | ```ini 28 | web_server http_port=80 https_port=443 29 | ``` 30 | 31 | 然後在 playbook 中使用 `package_name` 來取得變數,例如: 32 | 33 | ```yaml 34 | # playbook.yml 35 | - name: Set Firewall Configurations 36 | hosts: web_server 37 | tasks: 38 | - name: Allow HTTP 39 | community.general.ufw: 40 | rule: allow 41 | port: "{{ http_port }}" 42 | proto: tcp 43 | 44 | - name: Allow HTTPS 45 | community.general.ufw: 46 | rule: allow 47 | port: "{{ https_port }}" 48 | proto: tcp 49 | ``` 50 | 51 | 更好的方式,你也可以創建一個與 host 名稱相同的檔案,例如 `web_server.yaml`,然後在檔案中定義變數,例如: 52 | 53 | ```yaml 54 | # web_server.yaml 55 | http_port: 80 56 | https_port: 443 57 | ``` 58 | 59 | 變數是可以與其他字串結合的,例如: 60 | 61 | ```yaml 62 | # playbook.yml 63 | - name: do not permit traffic in default zone on port 80/tcp 64 | ansible.posix.firewalld: 65 | port: "{{ http_port }}/tcp" 66 | permanent: true 67 | state: disabled 68 | ``` 69 | -------------------------------------------------------------------------------- /php/08-phpstorm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: PHP 4 | nav_order: 8 5 | --- 6 | 7 | # PHPStorm 8 | 9 | PHPStorm 為 Jetbrains 推出的 PHP IDE,是寫 PHP 的好幫手,這裡記錄一些我習慣在 PHPStorm 中調整的設定。 10 | 11 | ## 程式碼樣式 12 | 13 | ### 使用 Laravel Pint 的程式碼風格 14 | 15 | 在 Settings -> Editor -> Code Style -> PHP 中。 16 | 17 | 點選右上角的 Set from... 然後選擇 **Laravel**。 18 | 19 | ### 對齊陣列的值 20 | 21 | 在 Settings -> Editor -> Code Style -> PHP -> Wrappings and Braces 底下。 22 | 23 | 勾選 Array Initializer 底下的 **Align key-value pairs**。 24 | 25 | ## 快捷鍵(Shortcuts) 26 | 27 | | Shortcut | Description | 28 | | --------------- | ---------------------- | 29 | | `Ctrl` + `G` | 選取相同的字段 | 30 | | `Ctrl` + `Ctrl` | Run anythings | 31 | | `Shift` + `F4` | 開啟當前頁面的浮動視窗 | 32 | | `Cmd` + `[` | 跳回之前的位置 | 33 | | `F3` | 將該行加入書籤 | 34 | 35 | ## 系統設定 36 | 37 | ### 衝突的按鍵 38 | 39 | PHPStorm 中的快捷鍵 `Cmd` + `Shift` + `A` 與 MacOS 的快捷鍵會產生衝突,建議在系統中將其關閉。 40 | 41 | 在 設定 -> 鍵盤 -> 鍵盤快速鍵 -> 服務 -> 文字 底下。 42 | 43 | 取消勾選「在終端機裡搜尋 man 頁面索引」。 44 | 45 | ## 參考資料 46 | 47 | - [Formatting code: getting aligned array setups](https://www.reddit.com/r/phpstorm/comments/17apa05/formatting_code_getting_aligned_array_setups/) 48 | - [Cmd+Shift+A hotkey opens Terminal with "apropos" search instead of the Find Action dialog](https://intellij-support.jetbrains.com/hc/en-us/articles/360005137400-Cmd-Shift-A-hotkey-opens-Terminal-with-apropos-search-instead-of-the-Find-Action-dialog) 49 | -------------------------------------------------------------------------------- /github/03-markdown-syntax.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: GitHub 4 | nav_order: 3 5 | --- 6 | 7 | # GitHub Markdown Syntax 8 | 9 | 記錄一些在 Github 上撰寫文件時會用到的特殊 Markdown 語法。 10 | 11 | ## Alerts 12 | 13 | Github 上提供了幾種不同的警告訊息樣式,可以用來強調文件中的重要資訊。 14 | 15 | ```markdown 16 | > [!NOTE] 17 | > Useful information that users should know, even when skimming content. 18 | 19 | > [!TIP] 20 | > Helpful advice for doing things better or more easily. 21 | 22 | > [!IMPORTANT] 23 | > Key information users need to know to achieve their goal. 24 | 25 | > [!WARNING] 26 | > Urgent info that needs immediate user attention to avoid problems. 27 | 28 | > [!CAUTION] 29 | > Advises about risks or negative outcomes of certain actions. 30 | ``` 31 | 32 | 這看起來會長這樣: 33 | 34 | 筆記: 35 | 36 | > [!NOTE] 37 | > Useful information that users should know, even when skimming content. 38 | 39 | 提示: 40 | 41 | > [!TIP] 42 | > Helpful advice for doing things better or more easily. 43 | 44 | 重要: 45 | 46 | > [!IMPORTANT] 47 | > Key information users need to know to achieve their goal. 48 | 49 | 警告: 50 | 51 | > [!WARNING] 52 | > Urgent info that needs immediate user attention to avoid problems. 53 | 54 | 注意: 55 | 56 | > [!CAUTION] 57 | > Advises about risks or negative outcomes of certain actions. 58 | 59 | ## 參考資料 60 | 61 | - [Basic writing and formatting syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) 62 | -------------------------------------------------------------------------------- /aws/16-storage.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: AWS 4 | nav_order: 16 5 | --- 6 | 7 | # Storage Service 8 | 9 | ## Elastic Block Storage (EBS) 10 | 11 | - EBS 預設加密。這個是地區 (regional) 級的功能。 12 | - Amazon EBS 的類型有三種: 13 | - General Purpose (SSD)。 14 | - Provisioned IOPS (SSD)。 15 | - Magnetic (現在稱 Cold HDD)。 16 | - Elastic Block Storage (EBS) io1/io2 支援同時被多個 EC2 掛載,最多 16 台。 17 | - EBS 沒有 lifecycle policy。 18 | - 使用 Amazon Data Lifecycle Manager (DLM) 可以幫 EBS 做到以下功能的自動化: 19 | - 建立 snapshot。 20 | - 設定 snapshot 保留時間。 21 | - 刪除 snapshot。 22 | - EBS snapshot 會送至 S3 上保存。 23 | - Data Lifecycle Manager (DLM) 可以與 CloudWatch 事件進行整合,例如 DLM 的備份數量達到上限,就會觸發 CloudWatch 事件。 24 | - 用 DLM 來備份 EBS 是最快速也最經濟實惠的選擇,透過 AWS CLI 定期執行 `craete-snapshot` 也可以,但需要時間。 25 | - EBS 支援 file lock,但不支援 object lock。object lock 是 S3 的功能。 26 | - EBS 建立後,會自動在**同區域**建立 replica。 27 | - EBS 與 EC2 必須要在同一個區域才能連接。 28 | - 如果想換區域,可以使用 snapshot 來做到。 29 | - EBS 使用 KMS 來加密,無論是 AWS Managed Key 或是匯入的 Custom Key 都可以。 30 | - 未加密的 EBS,其 snapshot 也是未加密的,反之亦然。因此想加密 EBS,可以先建立一個加密的 snapshot,然後再建立 EBS。 31 | - IOPS SSD,在 io1 可以提供 4GB 到 16TB 的存儲空間,根據你的硬碟大小,可以提供的 IOPS 也會提高。 32 | - 1GB 的硬碟大小可以提供 50 IOPS。 33 | 34 | ## Elastic File System (EFS) 35 | 36 | - 支援 POSIX (Portable Operating System Interface) 標準。 37 | - EFS 可以同時被**上千台 EC2** 掛載。 38 | - EFS 的生命週期管理無法刪除檔案,根據時間可以將資料移往。 39 | - 不常存取 (Infrequent Access, Standard-IA)。 40 | - 單區域不常存取 (One-Zone IA)。 41 | 42 | ## Amazon FSx 檔案系統 43 | 44 | - Amazon FSx For Lustre 是熱門開源的 parallel file system,效能非常好。 45 | -------------------------------------------------------------------------------- /docker/02-build.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Docker 4 | nav_order: 2 5 | --- 6 | 7 | # 建立映像檔 8 | 9 | 寫好 `Dockerfile`,就可以使用 docker 指令開始建立 image 10 | 11 | ```bash 12 | # 確定與 Dockerfile 在同一個目錄底下 13 | docker build -t image:tag . 14 | 15 | # 可以使用 -f 指定 Dockerfile 16 | docker build -t image:tag ./Dockerfile 17 | ``` 18 | 19 | ## 使用 Docker Buildx 建立不同架構的映像檔 20 | 21 | Docker Buildx 是一個 Docker 官方的工具,可以用來建構跨平台的 Docker 映像檔 22 | 23 | 使用 Docker Buildx,您可以輕鬆地建構多種不同系統架構的映像檔,例如 x86、ARM、IBM PowerPC 等等 24 | 25 | 可以查看目前系統支援 build 哪幾種架構 26 | 27 | ```bash 28 | docker buildx ls 29 | ``` 30 | 31 | 顯示結果如下,`*` 表示預設使用的 builder 32 | 33 | ```text 34 | NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS 35 | default * docker default default running 20.10.22 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6 36 | desktop-linux docker desktop-linux desktop-linux running 20.10.22 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6 37 | ``` 38 | 39 | 我們可以建立以 docker container 執行的 builder,並設定新建立的 builder 為預設 40 | 41 | ```bash 42 | docker buildx create --name mybuilder --platform linux/amd64,linux/arm64 43 | docker buildx use mybuilder 44 | ``` 45 | 46 | 之後我們就可以使用 Buildx 建立不同架構的映像檔案,並推送至 Docker Hub 47 | 48 | ```bash 49 | # 確定與 Dockerfile 在同一個目錄底下 50 | docker buildx build --platform linux/amd64,linux/arm64 --push -t image:tag . 51 | ``` 52 | -------------------------------------------------------------------------------- /svelte/11-actions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 11 5 | --- 6 | 7 | # Actions 8 | 9 | Actions 本質上是元素級生命週期 (element-level lifecycle) 的函式,會在元素被建立時呼叫。常常用在 10 | 11 | - 第三方庫的整合 12 | - 圖片的惰性載入 13 | - 工具提示 (tooltips) 14 | - 新增自訂事件處理程序 15 | 16 | ## `use:` 語法 17 | 18 | ```svelte 19 | 31 | 32 | 33 | 34 |
    35 | ``` 36 | 37 | ## 加入變數 38 | 39 | Actions 也可以傳入變數。下方是一個整合 tippy.js 的例子: 40 | 41 | ```svelte 42 | 62 | 63 | 64 | 65 | 68 | ``` 69 | -------------------------------------------------------------------------------- /pest/06-faker.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Pest 4 | nav_order: 6 5 | --- 6 | 7 | # 使用 Faker 產生假資料 8 | 9 | Faker 可以用來生產假資料,除了常被用做 database 的 seeding 之外,測試中也同樣很常被使用 10 | 11 | Pest 有提供一個 faker plugin,讓我們可以在 Pest 中使用 Faker,首先使用下面的方式安裝 12 | 13 | ```bash 14 | composer require pestphp/pest-plugin-faker --dev 15 | ``` 16 | 17 | Faker 在 Pest 中的使用範例如下,假設測試能否通過 Post 請求新增一個聯絡人 18 | 19 | ```php 20 | use function Pest\Faker\faker; 21 | 22 | it('can store a contact', function () { 23 | login()->post('/contacts', [ 24 | 'first_name' => faker()->firstName, 25 | 'last_name' => faker()->lastName, 26 | 'email' => faker()->email, 27 | 'phone' => faker()->e163PhoneNumber, 28 | 'address' => 'No. 22, Fake Rd', 29 | 'city' => 'Fake City', 30 | 'region' => 'Fake Region', 31 | 'country' => faker()->randomElement(['us', 'tw']), 32 | 'postal_code' => faker()->postcode, 33 | ]) 34 | ->assertRedirect('/contacts') 35 | ->assertSessionHas('success', 'Contact created'); 36 | }); 37 | ``` 38 | 39 | 如果不想額外裝套件,可以使用 `WithFaker` 這個 trait 40 | 41 | ```php 42 | use Illuminate\Foundation\Testing\WithFaker; 43 | 44 | uses(WithFaker::class); 45 | 46 | it('can store a contact', function () { 47 | login()->post('/contacts', [ 48 | 'first_name' => $this->faker->firstName, 49 | 'last_name' => $this->faker->lastName, 50 | // ... 51 | ]) 52 | ->assertRedirect('/contacts') 53 | ->assertSessionHas('success', 'Contact created'); 54 | }); 55 | ``` 56 | -------------------------------------------------------------------------------- /linux/03-ram-disk.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Linux 4 | nav_order: 3 5 | --- 6 | 7 | # 在 Linux 中建立記憶體硬碟 8 | 9 | 記憶體硬碟 (RAM Disk) 相較於傳統機械硬碟或固態硬碟,其讀寫速度更快,但是資料無法永久保存,只要一重新開機,資料就會消失。 10 | 11 | 在 Linux 中,你有兩種方式可以新增一個記憶體硬碟: 12 | 13 | 1. 使用 `mount` 指令 14 | 2. 修改 `/etc/fstab` 檔案 15 | 16 | ## 使用 `mount` 指令 17 | 18 | 首先使用 `mkdir` 建立要掛載的資料夾: 19 | 20 | ```bash 21 | sudo mkdir /mnt/ramdisk 22 | ``` 23 | 24 | 接著使用 `mount` 指令掛載記憶體硬碟: 25 | 26 | ```bash 27 | sudo mount -t tmpfs -o size=512M tmpfs /mnt/ramdisk 28 | ``` 29 | 30 | 各項參數說明: 31 | 32 | - `-t tmpfs`:指定檔案系統為 tmpfs 33 | - `-o size=512M`:指定記憶體硬碟大小為 512MB 34 | - `/mnt/ramdisk`:指定掛載的目錄 35 | 36 | ## 修改 `/etc/fstab` 檔案 37 | 38 | 如果想再重開機之後自動設定 RAM Disk,可以修改 `/etc/fstab` 檔案。 39 | 40 | 首先使用 `root` 權限以 `vim` 開啟 `/etc/fstab` 檔案: 41 | 42 | ```bash 43 | sudo vim /etc/fstab 44 | ``` 45 | 46 | 在檔案最後加入以下內容: 47 | 48 | ```text 49 | LABEL=cloudimg-rootfs / ext4 discard,commit=30,errors=remount-ro 0 1 50 | LABEL=BOOT /boot ext4 defaults 0 2 51 | LABEL=UEFI /boot/efi vfat umask=0077 0 1 52 | tmpfs /ramdisk tmpfs rw,nodev,nosuid,size=10M 0 0 53 | ``` 54 | 55 | 編輯完成之後,按下 `Esc` 鍵,輸入 `:wq` 並按下 `Enter` 儲存並離開。 56 | 57 | 最後使用 `mount -a` 指令重新掛載 `/etc/fstab` 中的檔案系統: 58 | 59 | ```bash 60 | sudo systemctl daemon-reload 61 | sudo mount -a 62 | ``` 63 | 64 | ## 參考資料 65 | 66 | - [Linux 中如何建立 RAM Disk,兩個快速簡單的方式,tmpfs、fstab | 適用各式 Linux 系統 | 挨踢實驗室](https://www.youtube.com/watch?v=xnSlYGeqlNA) 67 | -------------------------------------------------------------------------------- /database/07-foreign-key.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Database 4 | nav_order: 7 5 | --- 6 | 7 | # MySQL、SQLite 與 PostgreSQL 在加上 Foreign Key 上的差異。 8 | 9 | 前幾天在寫 Laravel ORM 時,發現有一句關係查詢語句在 SQLite 中非常慢。 10 | 11 | ```sql 12 | SELECT *, 13 | (SELECT Count(*) 14 | FROM "comments" AS "laravel_reserved_1" 15 | WHERE "comments"."id" = "laravel_reserved_1"."parent_id") AS 16 | "children_count" 17 | FROM "comments" 18 | WHERE "post_id" = 100 19 | AND "parent_id" IS NULL 20 | ORDER BY "children_count" DESC 21 | ``` 22 | 23 | 使用 `EXPLAIN` 發現查詢做了全表掃描,這時我才發現 `parent_id` 竟然沒有被加上索引 (Index)。 24 | 在 `parent_id` 加上索引之後,查詢速度就變快非常多,基本上不到一秒就能返回結果。 25 | 26 | 找資料才發現,**只有 MySQL 預設會幫 Foreign Key 加上索引,但是 SQLite 與 PostgreSQL 並不會這麼做**。 27 | 28 | 所以如果你在 Laravel Database Migration 中使用這個 `foreignId` 方法來建立 Foreign Key。 29 | 30 | ```php 31 | $table->foreignId('parent_id') 32 | ->nullable() 33 | ->constrained('comments') 34 | ->onDelete('cascade'); 35 | ``` 36 | 37 | 那麼就只有 MySQL 會加上索引,可以參考[MySQL 文件](https://dev.mysql.com/doc/refman/9.1/en/constraint-foreign-key.html)的說明。 38 | 39 | > MySQL requires that foreign key columns be indexed; if you create a table with a foreign key constraint but no index on a given column, an index is created. 40 | 41 | 相反的,PostgreSQL 與 SQLite 並不會這麼做,可以參考[PostgreSQL 文件](https://www.postgresql.org/docs/current/ddl-constraints.html)的說明。 42 | 43 | > Because this is not always needed, and there are many choices available on how to index, the declaration of a foreign key constraint does not automatically create an index on the referencing columns. 44 | -------------------------------------------------------------------------------- /laravel/06-laravel-pennant.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Laravel 4 | nav_order: 6 5 | --- 6 | 7 | # Laravel Pennant 8 | 9 | Laravel Pennant 是一個用來管理功能旗標 (Feature Flag) 的輕量套件。 10 | 11 | 你可以用來管理新功能是否開放給使用者使用,當新功能尚未準備好時,可以先將功能關閉,或是只開放給部分使用者使用。 12 | 13 | 14 | ## 如何使用 15 | 16 | 假設你有一個新的頁面只想開放給管理員使用,你可以在 `AppServiceProvider.php` 的 `boot` 方法中加入以下的程式碼: 17 | 18 | ```php 19 | use Laravel\Pennant\Feature; 20 | 21 | public function boot(): void 22 | { 23 | Feature::define('new-checkout', function (User $user) { 24 | // 回傳一個 boolean 值 25 | return $user->isAdmin(); 26 | }); 27 | } 28 | ``` 29 | 30 | 然後在你的控制器中,你可以使用 `Feature::active('new-checkout')` 來檢查使用者是否有權限訪問該頁面。 31 | 32 | ```php 33 | public function index() 34 | { 35 | if (Feature::active('new-checkout')) { 36 | return view('new-checkout'); 37 | } 38 | 39 | return view('checkout'); 40 | } 41 | ``` 42 | 43 | 在預設情況下,Laravel Pennant 會將功能旗標的值儲存在資料庫中,但也可以儲存在記憶體中。 44 | 45 | 除了單純的 Boolean 值之外,你也能儲存其他型別的值,例如字串。 46 | 47 | ```php 48 | use Laravel\Pennant\Feature; 49 | 50 | public function boot(): void 51 | { 52 | Feature::define('new-button-color', function (User $user) { 53 | return Arr::random(['red', 'green', 'blue']); 54 | }); 55 | } 56 | ``` 57 | 58 | 59 | 之後就可以在你的控制器中使用 `Feature::value('new-button-color')` 來取得功能旗標的值。 60 | 61 | ```php 62 | public function index() 63 | { 64 | $buttonColor = Feature::value('new-button-color'); 65 | 66 | return view('index', ['buttonColor' => $buttonColor]); 67 | } 68 | ``` 69 | 70 | ## 參考資料 71 | 72 | - [Laravel Pennant](https://laravel.com/docs/master/pennant) -------------------------------------------------------------------------------- /svelte/21-dynamic-attributes-component.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 21 5 | --- 6 | 7 | # Dynamic Attributes in Components 8 | 9 | 在 Laravel 中,我們可以使用 `$attributes` 來接收任何寫在 Component 上的屬性。 10 | 11 | ```blade 12 | {{-- button.blade.php --}} 13 | 14 | ``` 15 | 16 | 任何寫在 Component 上的屬性,都會被 `$attributes` 接收。 17 | 18 | ```blade 19 | 25 | Click me 26 | 27 | ``` 28 | 29 | 在 Svelte 中也有類似的功能,也就是 `HTMLInputAttributes`。 30 | 31 | ```svelte 32 | 45 | 46 |
    47 | 50 |
    51 | 52 | 58 |
    59 |
    60 | ``` 61 | -------------------------------------------------------------------------------- /svelte/02-props.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 2 5 | --- 6 | 7 | # Props 8 | 9 | ## Declaring Props 10 | 11 | 如果你需要將變數從父元件傳遞到子元件,你可以在子元件使用 `$props` 關鍵字來宣告子元件的 Props: 12 | 13 | ```svelte 14 | 17 | ``` 18 | 19 | 然後你就可以在父元件中使用 `name="world"` 將 `world` 傳入子元件中: 20 | 21 | ```svelte 22 | 25 | 26 | 27 | ``` 28 | 29 | ## Default Values 30 | 31 | 你可以在宣告 Props 的時候指定預設值: 32 | 33 | ```svelte 34 | 37 | ``` 38 | 39 | ## Spread Props 40 | 41 | 假設我們有一個元件叫做 `PackageInfo`,它有四個 Props:`name`、`speed`、`version`、`website`。 42 | 43 | ```svelte 44 | 49 | 50 |

    51 | The {name} package is {speed} fast. Download version {version} from 52 | npm and learn more here 53 |

    54 | ``` 55 | 56 | 你可以使用下面的方式將這四個 Props 傳入子元件: 57 | 58 | ```svelte 59 | 69 | 70 | 75 | ``` 76 | 77 | 也可以使用 `...` 來將物件的所有屬性傳入子元件: 78 | 79 | ```svelte 80 | 81 | ``` 82 | -------------------------------------------------------------------------------- /rust/16-package-and-crates.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Rust 4 | nav_order: 16 5 | --- 6 | 7 | # Packages 與 Crates 8 | 9 | Crate 是 Rust 編譯器能執行成功的最小程式碼量。 10 | 11 | 舉個例子,新增一個 `main.rs` 檔案,內容為一個印出 `Hello World!` 簡單程式碼。 12 | 13 | ```rust 14 | fn main() { 15 | println!("Hello World!"); 16 | } 17 | ``` 18 | 19 | 使用 `rustc` 編譯這個檔案。 20 | 21 | ```bash 22 | rustc main.rs 23 | 24 | # 編譯成功之後會生成一個可執行檔案 25 | ./main 26 | ``` 27 | 28 | 對 Rust 編譯器來說,這個 `main.rs` 檔案,就可以被看成是一個 Crate。 29 | 30 | ## Binary Crate 與 Library Crate 31 | 32 | Crate 有兩種形式,一種為 Binary Crate,另外一種為 Library Crate。 33 | 34 | Binary Crate 可以編譯並產生一個可執行程式,例如我們常用的命令行工具,前面筆記所有寫的程式碼都屬於 Binary Crate。 35 | 36 | Library Crate 不會有 `main` 函式,他們也不會被編譯成可執行程式,他們會定義許多功能,並用在其他專案上,例如之前用來產生一組隨機數的 `rand` 就是一種 Library Crate,通常 Rustaceans 提到 Crate 的時候,更多是指 Library Crate。 37 | 38 | ## Crate Root 39 | 40 | Crate Root 是一個源文件 (source file),Rust 編譯器會從從該源文件開始去建構你的 Crate Root Module。 41 | 42 | ## Package 43 | 44 | Package 是一個包含許多 Crate 並提供一組特定功能或方法的程式碼。 45 | 46 | Package 會包含 `Cargo.toml` 去描述這個 Package 需要依賴哪些 Crate。 47 | 48 | Cargo 實際上是一個軟體包,包含了你用來構建程式碼所需命令行工具的 Binary Crate,當中也包含這些命令行工具所需要的 Library Crate。 49 | 50 | Package 可以包含**許多 Binary Crate,但最多只能有一個 Library Crate**。 51 | 52 | Package 至少要包含一個 Crate,不論是 Binary Crate 或是 Library Crate 都可以。 53 | 54 | ## main.rs 與 lib.rs 55 | 56 | 使用 `cargo new` 新建一個初始 Package 時,Cargo 會自動認定 `src/main.rs` 為該 Package Binary Crate 的 Crate Root。 57 | 58 | > [!IMPORTANT] 59 | > 60 | > 這個 Crate 的名稱會與專案名稱相同。 61 | 62 | 如果是 `src/lib.rs` 就會認定為 Library Crate 的 Crate Root。 63 | 64 | Package 可以有多個 Binary Crate,但需要將其放置於 `src/bin` 目錄底下,每一個檔案都會被視為一個 Binary Crate。 65 | -------------------------------------------------------------------------------- /svelte/17-module-context.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | parent: Svelte 4 | nav_order: 17 5 | --- 6 | 7 | # Module Context 8 | 9 | ## Sharing Data Between Components 10 | 11 | 在很少的情況下,你需要在不同的元件之間共享數據。 12 | 13 | 假設你有一個音樂播放元件,當你的畫面上有多個播放元件時,你會希望同一時間只有一個元件在播放音樂。 14 | 這就代表當我們在一個元件中點擊播放時,我們需要通知其他元件停止播放。 15 | 16 | 我們可以使用 ` 25 | 26 | 27 | 28 |