🔍 搜尋結果:COM

🔍 搜尋結果:COM

Javascript Proxy 的 7 個實際用例🧙

JavaScript 的`Proxy`物件是一個有用的工具,它開啟了一個充滿可能性的世界,讓您在應用程式中建立一些真正有用的行為。當與 TypeScript 結合使用時,Proxy 可以增強您以您可能認為不可能的方式管理和操作物件和函數的能力。在本文中,我們將透過實際範例探索代理的令人難以置信的實用性。 什麼是代理? ------ [Javascript 中的代理程式](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)是另一個物件(目標)的包裝器,它允許您攔截並重新定義該物件的基本操作,例如屬性查找、賦值、枚舉和函數呼叫。這意味著您可以在取得或設定屬性時新增自訂邏輯。這對於處理驗證、通知甚至自動資料綁定非常有用。 建立一個簡單的代理 --------- 讓我們開始看看如何建立代理。我們將從一個非常基本的範例開始,以防您以前從未見過代理。 ``` type MessageObject = { message: string; }; let target: MessageObject = { message: "Hello, world!" }; let handler: ProxyHandler<MessageObject> = { get: (obj, prop) => { return `Property ${String(prop)} is: ${obj[prop]}`; } }; let proxy: MessageObject = new Proxy(target, handler); console.log(proxy.message); // Output: Property message is: Hello, world! ``` 在此範例中,每當存取代理程式上的屬性時,都會呼叫處理程序的 get 方法,從而允許我們修改簡單存取屬性的行為。我相信您可以想像這帶來的所有不同的可能性。 現在讓我們來看看 7 個更有用的例子! ### 1. 自動填充屬性 代理程式可以在存取時動態填充物件屬性,這對於複雜物件的按需處理或初始化非常有用。 ``` type LazyProfile = { firstName: string; lastName: string; fullName?: string; }; let lazyProfileHandler = { get: (target: LazyProfile, property: keyof LazyProfile) => { if (property === "fullName" && !target[property]) { target[property] = `${target.firstName} ${target.lastName}`; } return target[property]; } }; let profile: LazyProfile = new Proxy({ firstName: "John", lastName: "Doe" }, lazyProfileHandler); console.log(profile.fullName); // Output: John Doe ``` ### 2. 運算計數 使用代理來計算對物件執行某些操作的次數。這對於除錯、監視或分析應用程式效能特別有用。 ``` type Counter = { [key: string]: any; _getCount: number; }; let countHandler = { get: (target: Counter, property: keyof Counter) => { if (property === "_getCount") { return target[property]; } target._getCount++; return target[property]; } }; let counter: Counter = new Proxy({ a: 1, b: 2, _getCount: 0 }, countHandler); counter.a; counter.b; console.log(counter._getCount); // Output: 2 ``` ### 3. 不可變物件 透過攔截並防止物件建立後對其進行任何更改,使用代理程式建立真正不可變的物件。 ``` function createImmutable<T extends object>(obj: T): T { return new Proxy(obj, { set: () => { throw new Error("This object is immutable"); } }); } const immutableObject = createImmutable({ name: "Jane", age: 25 }); // immutableObject.age = 26; // Throws error ``` ### 4. 方法鍊和流暢的接口 透過使用代理建立流暢的介面來增強方法鏈,其中每個方法呼叫都會傳回一個代理程式以啟用進一步的呼叫。 ``` type FluentPerson = { setName(name: string): FluentPerson; setAge(age: number): FluentPerson; save(): void; }; function FluentPerson(): FluentPerson { let person: any = {}; return new Proxy({}, { get: (target, property) => { if (property === "save") { return () => { console.log(person); }; } return (value: any) => { person[property] = value; return target; }; } }) as FluentPerson; } const person = FluentPerson(); person.setName("Alice").setAge(30).save(); // Output: { setName: 'Alice', setAge: 30 } ``` ### 5. 智慧緩存 這是我最喜歡的用例之一。實施智慧型快取機制,按需獲取或計算資料,然後儲存以供快速後續存取。 ``` function smartCache<T extends object>(obj: T, fetcher: (key: keyof T) => any): T { const cache: Partial<T> = {}; return new Proxy(obj, { get: (target, property: keyof T) => { if (!cache[property]) { cache[property] = fetcher(property); } return cache[property]; } }); } const userData = smartCache({ userId: 1 }, (prop) => { console.log(`Fetching data for ${String(prop)}`); return { name: "Bob" }; // Simulated fetch }); console.log(userData.userId); // Output: Fetching data for userId, then returns { name: "Bob" } ``` ### 6. 動態屬性驗證 代理可以動態地強制執行屬性分配規則。以下是如何確保在更改屬性之前滿足某些條件: ``` let user = { age: 25 }; let validator = { set: (obj, prop, value) => { if (prop === 'age' && (typeof value !== 'number' || value < 18)) { throw new Error("User must be at least 18 years old."); } obj[prop] = value; return true; // Indicate success } }; let userProxy = new Proxy(user, validator); userProxy.age = 30; // Works fine console.log(userProxy.age); // Output: 30 // userProxy.age = 'thirty'; // Throws error // userProxy.age = 17; // Throws error ``` ### 7. 觀察變化 代理程式的常見用例是建立可監視物件,以便在發生變更時通知您。 ``` function onChange(obj, onChange) { const handler = { set: (target, property, value, receiver) => { onChange(`Property ${String(property)} changed to ${value}`); return Reflect.set(target, property, value, receiver); } }; return new Proxy(obj, handler); } const person = { name: "John", age: 30 }; const watchedPerson = onChange(person, console.log); watchedPerson.age = 31; // Console: Property age changed to 31 ``` 使用代理的缺點 ------- 雖然代理非常有用,但它們有一些注意事項: 1. **效能**:代理程式會帶來效能開銷,尤其是在高頻操作中,因為代理程式上的每個操作都必須經過處理程序。 2. **複雜性**:能力越大,複雜度越高。代理的不正確使用可能會導致難以除錯的問題和可維護性問題。 3. **相容性**:代理程式無法為不支援 ES6 功能的舊版瀏覽器進行多填充,這限制了它們在需要廣泛相容性的環境中的使用。 結束 -- JavaScript 中的代理,尤其是與 TypeScript 一起使用時,提供了一種與物件互動的靈活方式。它們支援驗證、觀察和綁定等功能。無論您是建立複雜的使用者介面、開發遊戲還是處理伺服器端邏輯,理解和利用代理程式都可以為您提供更深層的控制和程式碼的複雜性。感謝您的閱讀,希望您學到新東西! 🎓 還有無恥的插頭🔌。如果您在敏捷開發團隊中工作並使用線上會議工具(例如規劃撲克或回顧),請查看我的免費工具[Kollabe](https://kollabe.com/) ! --- 原文出處:https://dev.to/mattlewandowski93/7-use-cases-for-javascript-proxies-3b29

進階 CI/CD 管道配置策略

\_歡迎參加 DevSecOps in 5 的第 3 週:您獲得安全開發超級大國的門票! 嘿,安全冠軍和編碼戰士! 您是否渴望提升 DevSecOps 水平並成為堅如磐石的軟體架構師?好吧,您來對地方了!這個為期 5 週的部落格系列是您掌握安全開發和部署的快速通道。 --- 在當今快節奏的開發環境中,持續整合和持續交付(CI/CD)管道已成為高效軟體交付的基石。它們會自動執行重複性任務,例如建置、測試和部署程式碼,使團隊能夠更快、更可靠地交付功能和錯誤修復。但除了基本功能之外,還有一個進階配置的世界,可以釋放更高的效率和控制力。本部落格深入探討了先進的 CI/CD 管道策略,為您提供了根據您的特定需求建立強大且可擴展的管道的知識。 部署策略:超越藍/綠 ---------- 雖然藍/綠部署是最大限度地減少更新期間停機時間的熱門選擇,但它們並不是唯一的選擇。讓我們探討一些進階部署策略: #### 藍/綠部署(深入): 在藍/綠部署中,您維護兩個相同的生產環境(藍色和綠色)。新程式碼首先部署到綠色環境中,並經過嚴格的測試。一旦穩定,流量就會逐漸從藍色環境轉向綠色環境,有效取代舊版本。這種方法可以最大限度地減少停機時間,並在出現問題時允許快速回滾。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/51im761vqe814tob58tw.png) #### 金絲雀版本(擴充): 金絲雀發布涉及首先向一小部分用戶(金絲雀)部署應用程式的新版本。這允許在全面推出之前進行實際測試和監控。您可以使用先進的技術,例如透過基於百分比的流量轉移進行分階段部署。首先將新版本部署到一小部分用戶(例如 1%),隨著效能和穩定性的確認逐漸增加流量,最後推廣到整個用戶群。 A/B 測試可以與金絲雀版本集成,以比較不同的應用程式版本並在全面推出之前收集用戶回饋。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7v6gstbyayfspqah7ldy.png) #### 紅帽部署堆疊 (OpenShift): OpenShift 是一個容器編排平台,提供內建部署功能。它可以與 CI/CD 管道集成,以利用藍/綠部署和金絲雀發布等高級部署策略。 OpenShift 管理容器化應用程式的擴充和運作狀況,從而簡化部署工作流程。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/81v097cqxon85xcl084j.png) CI/CD 管道中的基礎設施配置: ----------------- 自動化基礎設施配置和部署是一種強大的實踐。以下是如何實現它: #### 基礎設施即程式碼 (IaC) 工具: Terraform、Ansible 或 CloudFormation 等流行的 IaC 工具可讓您將基礎架構定義為程式碼。這些配置可以與 CI/CD 管道集成,從而在部署期間實現基礎設施資源(例如虛擬機器、儲存)的自動配置和管理。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q9limw1f3ew3xudrjkum.png) #### 多雲基礎設施管理: 跨不同雲端供應商(多雲)管理基礎架構可能很複雜。 IaC 工具可以透過定義與雲端無關的配置來提供協助,這些配置可以透過最小的變更來適應不同的雲端供應商。與多雲 IaC 工具整合的 CI/CD 管道可以跨各種雲端環境自動化基礎設施配置和部署。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ysyfl6vi2juabenjgmr4.png) 管道中 IaC 的安全注意事項: ---------------- 使用 IaC 時,安全性至關重要。安全實踐包括: 使用 HashiCorp Vault 等機密管理工具在 IaC 配置中安全地儲存敏感資訊(API 金鑰、密碼)。 實施存取控制以限制誰可以修改 IaC 配置和配置資源。 定期掃描 IaC 設定是否有漏洞,以防止安全漏洞。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rgx2mbbzj9zotcnz3dfl.png) #### 功能標誌和分支切換: 功能標誌是允許您在執行時啟用或停用應用程式中的特定功能的機制。它們可以與 CI/CD 管道和 Git 分支策略整合。例如,您可以將新功能的程式碼部署到特定分支,並使用功能標誌透過 CI/CD 管道控制其對不同環境或使用者群組的可見性。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dohg04gfnfg7f1cftmtq.png) #### 持續交付與持續部署(深入探討): 雖然持續交付 (CD) 和持續部署 (CD) 經常互換使用,但它們之間存在細微的差異。 CD 專注於自動化整個建置、測試和打包管道直至部署就緒狀態。通常需要人工幹預來批准和觸發部署。另一方面,持續部署使整個流程自動化,包括部署到生產環境。這需要在管道內進行強大的測試和驗證,以確保只有穩定的程式碼才能投入生產。對於需要手動批准的部署或較高風險的環境,請選擇 CD;對於頻繁、低風險的部署,請考慮 CD。 #### 無伺服器應用程式的 CI/CD: 無伺服器函數是在雲端中按需執行的事件驅動的程式碼片段。將 CI/CD 管道與無伺服器功能整合可以在程式碼變更時自動部署這些功能。考慮使用 AWS 無伺服器應用程式模型 (SAM) 或 Google Cloud Functions 等無伺服器框架來簡化無伺服器部署的 CI/CD 工作流程。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a597bj2j3j22nf4j21an.png) 監控和效能優化: -------- 以下是如何確保 CI/CD 管道的最佳性能和運作狀況: #### 監控 CI/CD 管道: 持續監控您的 CI/CD 管道以辨識瓶頸和潛在問題。監控指標,例如: #### 建置時間: 追蹤建置完成所需的平均時間。辨識並解決執行緩慢的建置,以提高整體管道效率。 #### 部署持續時間: 監控將新程式碼部署到生產環境所需的時間。研究並優化耗時過長的部署。 #### 錯誤率: 追蹤管道階段內發生錯誤的頻率(建置失敗、測試失敗)。分析錯誤以確定根本原因並實施解決方案來預防錯誤。 #### CI/CD 的指標和儀表板: 利用儀表板視覺化 CI/CD 管道中的關鍵指標。這樣可以快速辨識趨勢和潛在問題。用於 CI/CD 監控的流行工具包括 Prometheus、Grafana 和 Datadog。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4tja96vhhc36vp4umzq.png) #### 效能優化技術: 實施策略來優化 CI/CD 管道: #### 快取: 快取常用的依賴項、建置工件和測試結果,以減少冗餘下載並縮短建置時間。 #### 並行化: 將管道階段分解為可以並發執行的較小任務,以加快建置和部署速度。 #### 容器化建置: 利用 Docker 等容器化技術建立隔離的建置環境,確保跨不同環境的一致性和更快的建置。 ### 機器學習 (ML) 計畫的 CI/CD: 將 ML 模型和資料管道與 CI/CD 工作流程整合需要具體考慮。這些包括: 在管道內自動化訓練資料版本控制和管理。 整合 ML 模型的單元和整合測試,以確保其準確性和功能。 自動化模型部署和回滾過程。 ### CI/CD 安全最佳實踐: 在整個 CI/CD 管道中實施安全性: 實作程式碼簽章以驗證透過管道部署的程式碼的完整性。 整合漏洞掃描工具來辨識程式碼相依性中的安全缺陷。 實施嚴格的存取控制,以限制誰可以觸發部署並存取管道內的敏感資源。 ### CI/CD 的未來: CI/CD 的新興趨勢包括: AI/ML 整合用於管道內的自動化決策,例如最佳化資源分配或預測潛在問題。 自癒管道可以自動偵測故障並從故障中恢復。 與 GitOps 整合以進行聲明式基礎架構管理,利用 Git 作為程式碼和基礎架構配置的真實來源。 不同考慮因素的 CI/CD 管道配置 ------------------ 除了核心功能之外,CI/CD 管道還可以根據各種開發方法和專案要求進行客製化: ### 微服務架構的 CI/CD: 微服務架構涉及將應用程式分解為小型的獨立服務。微服務的 CI/CD 管道需要支援這些服務的獨立部署和測試。這可能涉及使用容器化和服務發現等技術來有效管理部署和依賴項。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mxbp17lc7tlbteoqiz9q.png) #### 用於敏捷開發的 CI/CD: 敏捷開發方法強調頻繁的程式碼變更和迭代。 CI/CD 管道可以配置為透過在每次程式碼提交時啟用快速建置、自動化測試和快速部署來支援這一點。 #### 遺留應用程式的 CI/CD: 將 CI/CD 實踐與遺留應用程式整合可能具有挑戰性。它可能涉及分階段的方法,在過渡到完整的 CI/CD 整合之前,逐步為開發生命週期的特定部分(例如單元測試)引入自動化。 進階安全注意事項: --------- #### 軟體組成分析(SCA): SCA 工具與 CI/CD 管道集成,以掃描程式碼依賴項以查找已知漏洞。這使您可以在部署之前辨識並解決潛在的安全風險。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r9fj3qqc1lj594borrhw.png) #### 秘密管理和保險庫整合: 利用 HashiCorp Vault 或基於雲端的機密管理器等工具,安全地管理 CI/CD 管道中使用的機密(API 金鑰、密碼)。這些工具為敏感資訊提供安全儲存和存取控制機制。 #### 合規性和監理要求: 可以配置 CI/CD 管道以滿足您的行業或安全標準的特定合規性和監管要求。這可能涉及實施審核日誌記錄、實施存取控制以及與合規性掃描工具整合。 CI/CD 管道優化以實現可擴展性 ----------------- 隨著您的專案和部署的成長,您的 CI/CD 管線處理增加的工作負載的能力也應該隨之成長: #### 使用容器編排器進行水平擴展: Kubernetes 等容器編排平台可透過跨叢集執行管道代理程式的多個實例來水平擴展 CI/CD 管道。這允許並行執行任務並在繁重的工作負載下提高效能。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/td28dh0cskt6fn6f00t6.png) #### 提高效能的快取策略: 在整個管道中實施快取以減少冗餘操作: 快取建置工件(編譯後的程式碼),以避免在原始程式碼未更改的情況下在每個後續建置中重建它們。 快取依賴項下載以避免為每個建置重新下載它們。 #### 管道健康狀況監控和警報: 建立全面的監控和警報系統來辨識 CI/CD 管道中的問題。這可能涉及: 監控 CI/CD 基礎設施的資源利用率以辨識潛在的瓶頸。 針對管道故障、建置緩慢或錯誤設定警報,以確保及時幹預和故障排除。 CI/CD 的新興趨勢 ----------- 透過探索 CI/CD 的這些新興趨勢來保持領先地位: #### GitLab 和 GitHub 操作的 CI/CD: GitLab 和 GitHub 都提供內建的 CI/CD 功能。利用這些功能直接在 Git 儲存庫中進行自動化部署和程式碼測試。 #### 測試環境的基礎設施即程式碼: 利用 IaC 在 CI/CD 管道中配置和管理臨時測試環境。這樣可以根據需要有效率地建立和銷毀測試環境,從而減少基礎設施開銷。 #### 資料管道的 CI/CD: 將資料管道與 CI/CD 工作流程集成,以自動執行資料測試、版本控制和部署以及應用程式程式碼。這可確保資料管道與應用程式變更保持同步並保持資料品質。 ### 用於災難復原的 CI/CD: CI/CD 管道可用於自動化災難復原工作流程。透過在管道內編寫基礎架構配置、應用程式部署和資料復原過程的腳本,您可以在發生中斷或事件時加快復原時間。 ### A/B 測試與 CI/CD 整合: 將 A/B 測試工具與 CI/CD 管道集成,以促進受控部署和功能實驗。這使您可以將不同版本的功能部署到一部分用戶並收集其效能資料,然後再將其推廣到整個用戶群。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t22zepxcrskevzi2l470.png) ### CI/CD 成本優化策略: 優化與 CI/CD 管道相關的成本: 利用 CI/CD 基礎架構的隨選資源(雲端實例、容器實例),只需按使用量付費。 優化管道配置以最大限度地減少建置和部署期間的資源消耗。 考慮在雲端中使用現貨實例或搶佔式虛擬機器來實現經濟高效的 CI/CD 基礎架構。 結論 -- CI/CD 管道是強大的工具,可顯著提高軟體交付過程的速度、可靠性和效率。透過利用本部落格中探討的進階策略和注意事項,您可以釋放 CI/CD 的全部潛力並簡化您的開發工作流程。請記住根據您的特定專案需求和開發環境自訂 CI/CD 管道配置。隨著 CI/CD 的不斷發展,請隨時了解新興趨勢和最佳實踐,以確保您的管道在不斷變化的軟體開發世界中保持穩健和高效。 --- 我很高興今天有機會與您一起深入研究高級 CI/CD 管道配置策略。這是一個令人著迷的領域,具有改善安全狀況的巨大潛力。 感謝您和我一起探索進階 CI/CD 管道配置策略。您持續的興趣和參與推動了這趟旅程! 如果您發現有關進階 CI/CD 管道配置策略的討論有幫助,請考慮與您的網路分享!知識就是力量,尤其是在安全方面。 讓我們繼續談話吧!在下面的評論中分享您對進階 CI/CD 管道配置策略的想法、問題或經驗。 渴望了解有關 DevSecOps 最佳實踐的更多資訊?請繼續關注下一篇文章! 透過共同努力並採用安全的開發實踐,我們可以建立一個更具彈性和值得信賴的軟體生態系統。 請記住,安全開發之旅是一個持續學習的過程。這是為了持續改進! --- 原文出處:https://dev.to/gauri1504/advanced-cicd-pipeline-configuration-strategies-4mjh

Angular 18 的新增功能

介紹 -- 2024 年 5 月 22 日星期三,Angular 核心團隊發布了 Angular 新版本:版本 18。 該版本不僅穩定了最新的API,還引入了許多旨在簡化框架的使用並改善開發人員體驗的新功能。 這些新功能是什麼?請仔細閱讀,找出答案。 新的控制流程語法現已穩定 ------------ 當最新版本的 Angular 發佈時,引入了一種管理視圖流的新方法。提醒一下,這個新的控制流程直接整合到 Angular 模板編譯器中,使以下結構指令成為可選: - 動圖 - ngFor - ngSwitch / ngSwitchCase ``` <!-- old way --> <div *ngIf="user">{{ user.name }}</div> <!-- new way --> @if(user) { <div>{{ user.name }}</div> } ``` 這個新的 API 現已穩定,我們建議使用這個新語法。 如果您想將應用程式遷移到這個新的控制流,可以使用原理圖。 ``` ng g @angular/core:control-flow ``` 此外,新的 @for 語法取代了 ngFor 指令,迫使我們使用 track 選項來優化清單的渲染,並避免在變更期間完全重新建立清單。 開發模式中新增了兩個新警告: - 如果追蹤鍵重複,則會發出警告。如果所選鍵值在您的集合中不唯一,則會引發此警告。 - 如果追蹤鍵是整個專案並且選擇此鍵會導致整個清單的破壞和重新建立,則會發出警告。如果認為該操作成本太高(但門檻較低),則會出現此警告。 Defer 語法現已穩定 ------------ @defer 語法也在最新版本的 Angular 中引入,讓您定義一個在滿足條件時延遲載入的區塊。當然,此區塊中使用的任何第三方指令、管道或庫也將被延遲載入。 這是它的使用範例 ``` @defer(when user.name === 'Angular') { <app-angular-details /> }@placeholder { <div>displayed until user.name is not equal to Angular</div> }@loading(after: 100ms; minimum 1s) { <app-loader /> }@error { <app-error /> } ``` 提醒一句, - 只要不滿足@defer區塊條件,就會顯示@Placeholder區塊 - 當瀏覽器下載@defer區塊的內容時,將顯示@loading區塊;在我們的例子中,如果下載時間超過 100 毫秒,就會顯示區塊加載,並且顯示的最短持續時間為 1 秒。 - 如果下載@defer區塊時發生錯誤,將顯示@error區塊 Zone js 會發生什麼 ------------- Angular 18 引進了一種觸發偵測變更的新方法。此前,毫不奇怪,檢測更改完全由 Zone Js 處理。現在,偵測變化由框架本身直接觸發。 為了實現這一點,框架中加入了一個新的變更檢測調度程序 ( *ChangeDetectionScheduler* ),並且該調度程序將在內部使用來引發變更檢測。這個新的調度程序不再基於 Zone Js,並且預設與 Angular 版本 18 一起使用。 這個新的調度程序將引發檢測更改,如果 - 觸發範本或主機偵聽器事件 - 附加或刪除視圖 - 非同步管道接收新值 - 呼叫 markForCheck 函數 - 訊號的值發生變化等。 小文化時刻:此偵測變更是由於內部呼叫*ApplicationRef.tick*函數所致。 正如我上面提到的,由於Angular 18 版本一直基於這個新的調度程序,因此當您遷移應用程式時,不會出現任何問題,因為Angular 可能會收到Zone Js 和/或這個新調度程序的檢測更改通知。 但是,要回到 Angular 18 之前的行為,您可以使用provideZoneChangeDetection 函數,並將*ignoreChangesOutsideZone* setter 選項設為true。 ``` bootstrapApplication(AppComponent, { providers: [ provideZoneChangeDetection({ ignoreChangesOutsideZone: true }) ] }); ``` 另外,如果您希望僅依賴新的排程器而不依賴 Zone Js,則可以使用*ProvideExperimentalZonelessChangeDetection*函數。 ``` bootstrapApplication(AppComponent, { providers: [ provideExperimentalZonelessChangeDetection() ] }); ``` 透過實現*provideExperimentalZonelessChangeDetection*函數,Angular不再依賴Zone Js,這使得 - 如果專案的其他依賴項均不依賴它,則刪除 Zone js 依賴項 - 從 angular.json 檔案中的 polifills 中刪除區域 js 棄用 HttpClientModule ------------------- 自從 Angular 14 版本和獨立元件的到來以來,模組在 Angular 中已成為可選的,現在是時候看到第一個模組已棄用:我將其命名為 HttpClientModule 此模組負責為整個應用程式註冊 HttpClient 單例,以及註冊攔截器。 該模組可以輕鬆地替換為*ProvideHttpClient*函數,並提供支援 XSRF 和 JSONP 的選項。 這個函數有一個用於測試的孿生姊妹: *provideHttpClientTesting* ``` bootstrapApplication(AppComponent, { providers: [ provideHttpClient() ] }); ``` 像往常一樣,Angular 團隊提供了原理圖來幫助您遷移應用程式。 當發出*ng update @Angular/core @Angular /cli*命令時,如果在應用程式中使用,將發出遷移 HttpClientModule 的請求 內容後備 ---- ng-content 是 Angular 中的一個重要功能,尤其是在設計通用元件時。 此標籤可讓您投影自己的內容。然而,這項功能有一個重大缺陷。您無法為其指定預設內容。 從版本 18 開始,情況就不再如此。您可以在其中包含內容如果開發者沒有提供任何內容,將顯示的標籤。 我們以按鈕元件為例 ``` <button> <ng-content select=".icon"> <i aria-hidden="true" class="material-icons">send</i> </ng-content> <ng-content></ng-content> </button> ``` 使用按鈕元件時,如果沒有提供圖示類別的元素,則會顯示圖示傳送 表單事件:一種對表單事件進行分組的方法 ------------------- 這是社群很久以前提出的請求:有一個 api 將表單中可能發生的事件組合在一起;當我說事件時,我指的是以下事件 - 原始的 - 感動 - 狀態改變 - 重置 - 提交 Angular 18 版本公開了 AbstractControl 類別中的一個新事件屬性(允許 FormControl、FormGroup 和 FormArray 繼承該屬性),該屬性傳回一個 observable ``` @Component() export class AppComponent { login = new FormControl<string | null>(null); constructor() { this.login.events.subscribe(event => { if (event instanceof TouchedChangeEvent) { console.log(event.touched); } else if (event instanceof PristineChangeEvent) { console.log(event.pristine); } else if (event instanceof StatusChangeEvent) { console.log(event.status); } else if (event instanceof ValueChangeEvent) { console.log(event.value); } else if (event instanceof FormResetEvent) { console.log('Reset'); } else if (event instanceof FormSubmitEvent) { console.log('Submit'); } }) } } ``` 路由:重定向作為函數 ---------- 在最新版本的 Angular 之前,當您想要重新導向到另一個路徑時,可以使用*redirectTo*屬性。該屬性僅將一個字串作為其值 ``` const routes: Routes = [ { path: '', redirectTo: 'home', pathMath: 'full' }, { path: 'home', component: HomeComponent } ]; ``` 現在可以傳遞具有此屬性的函數。該函數將*ActivatedRouteSnapshot*作為參數,讓您可以從url中檢索queryParams或params。 另一個有趣的點是,這個函數是在註入上下文中呼叫的,使得注入服務成為可能。 ``` const routes: Routes = [ { path: '', redirectTo: (data: ActivatedRouteSnapshot) => { const queryParams = data.queryParams if(querParams.get('mode') === 'legacy') { const urlTree = router.parseUrl('/home-legacy'); urlTree.queryParams = queryParams; return urlTree; } return '/home'; }, pathMath: 'full' }, { path: 'home', component: HomeComponent }, { path: 'home-legacy', component: HomeLegacyComponent } ]; ``` 伺服器端渲染:兩個很棒的新功能 --------------- Angular 18 引進了兩個重要且期待已久的新伺服器端渲染功能 - 事件回放 - 國際化 ### 重播事件 當我們建立伺服器端渲染應用程式時,該應用程式會以 html 格式傳送回瀏覽器,顯示一個靜態頁面,然後由於水化現象而變得動態。在此水合階段期間,無法傳送對互動的回應,因此使用者互動會遺失,直到水合完成為止。 Angular 能夠記錄此水合作用階段的用戶交互,並在應用程式完全加載並交互後重播它們。 若要解鎖此功能,仍處於開發者預覽版,您可以使用 ServerSideFeature *withReplayEvents*函數。 ``` providers: [ provideClientHydration(withReplayEvents()) ] ``` ### 國際化 隨著 Angular 16 的發布,Angular 改變了頁面水合的方式。破壞性水合作用已被漸進性水合作用所取代。然而,當時缺乏一個重要的功能:國際化支持。 Angular 跳過了標記為 i18n 的元素。 有了這個新版本,這種情況就不再是這樣了。請注意,此功能仍處於開發預覽階段,可以使用*withI18nSupport*函數啟動。 ``` providers: [ provideClientHydration(withI18nSupport()) ] ``` 國際化 --- Angular 建議使用 INTL 原生 javascript API 來處理與 Angular 應用程式國際化相關的所有事務。 根據此建議, **@angular/common**套件公開的函數助手已被棄用。因此,不再建議使用 getLocaleDateFormat 等函數。 新的建構器包和棄用 --------- 到目前為止,自從 Angular 中出現 vite 以來,用於建立 Angular 應用程式的建構器位於以下套件中: **@angular-devkit/build-angular** 該套件包含 Vite、Webpack 和 Esbuild。對於將來僅使用 Vite 和 Esbuild 的應用程式來說,這個套件太重了。 考慮到這一潛在的未來,一個僅包含 Vite 和 Esbuild 的新包被建立,名稱為**@angular/build** 遷移到 Angular 18 時,如果應用程式不依賴 webpack(例如,沒有基於 Karma 的單元測試),則可以執行可選原理圖。此原理圖將修改 angular.json 檔案以使用新套件,並透過新增套件和刪除舊套件來更新 package.json。 重要的是,舊包可以繼續使用,因為它為新包提供了別名。 透過在專案的 node\_modules 中加入必要的依賴項,Angular 開箱即用地支援 Less Sass Css 和 PostCss。 然而,隨著新的**@angular/build**套件的到來,Less 和 PostCss 成為可選的,並且必須在 package.json 中明確作為開發依賴項。 當您遷移到 Angular 18 時,如果您希望使用新包,這些依賴項將自動新增。 不再需要降級非同步/等待 ------------ Zone js 不支援 Javascript 功能*async/await* 。 為了不限制開發人員使用此功能,Angular 的 CLI 將使用*async/await 的*程式碼轉換為「常規」Promise。 這種轉換稱為降級,就像它將 Es2017 程式碼轉換為 Es2015 程式碼一樣。 隨著應用程式不再基於 Zone Js,即使目前仍處於實驗階段,如果不再在 polyfill 中聲明 ZoneJs,Angular 將不再降級。 因此,應用程式的建置將更快、更輕。 新別名:by dev ---------- 從現在開始,當執行*ng dev*命令時,應用程式將以開發模式啟動。 實際上,ng dev 指令是*ngserve*指令的別名。 建立此別名是為了與 Vite 生態系統保持一致,特別是 npm run dev 指令。 未來 -- Angular 團隊再次交付了一個充滿新功能的版本,無疑將大大增強開發人員的體驗,並向我們展示 Angular 的未來一片光明。 未來我們可以期待什麼? 毫無疑問,性能和開發人員體驗持續改進。 我們還將看到基於訊號的表單、基於訊號的元件的引入,以及很快使用 @let 區塊聲明模板變數的能力。 --- 原文出處:https://dev.to/this-is-angular/whatnew-in-angular-18-60j

新的 CSS 媒體查詢語法 💥

告別`Min-Width`和`Max-Width` 👋🏻 ---------------------------- **新的**CSS 媒體查詢語法徹底改變了我們定義回應斷點的方式。 **它使我們的程式碼更清晰、更容易理解。** 🚀 新語法的好處: - **清晰度**:新語法簡單直覺✨ - **效率**:降低複雜度可以加快開發速度🏎️ - **相容性**:現代瀏覽器的高度支援。你可以[在這裡](https://caniuse.com/?search=media%20queries)查看🌐 --- 程式碼範例🖥️ ------- 傳統上,你可以這樣寫: ![CSS 媒體查詢](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6ve06caf2ldo23pbspy.png) 使用新的、更簡單的文法,它變成: ![CSS 媒體查詢](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68jazsua4xi7cywfcp02.png) 老辦法: ![CSS 媒體查詢](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3mgra2idikmwt7411vd2.png) 新方法: ![CSS 媒體查詢](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uqszibsl7sdzu3rwz1jc.png) 您也可以在兩個寬度之間進行測試... ![CSS 媒體查詢](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ue83l9wilriie5qziqt1.png) --- 結論🌟 --- 採用新的 CSS 媒體查詢語法將簡化您的程式碼。您可以專注於輕鬆建立響應式設計。 請評論您的想法。您的想法對於為前端開發領域做出貢獻很有價值。歡迎大家!我想聽聽他們的聲音💬 保持良好的工作! 👍 --- 原文出處:https://dev.to/perisicnikola37/new-css-media-queries-syntax-45og

探索 JavaScript 中的解構

什麼是解構? ------ **解構**是 JavaScript 中一個非常酷的特殊語法功能,它允許我們從*陣列*、*物件*或其他可迭代結構中提取值並將它們指派給變數。 這是一種存取資料結構的屬性或元素的簡寫方式,而無需使用點表示法或陣列索引。 它對我們(用 JavaScript 寫程式的人)有什麼好處? ------------------------------ 解構有幾個好處,可以讓我們的程式碼更加簡潔、可讀和可維護! - ***提高可讀性***:解構透過減少複雜變數賦值和點符號的需要來簡化程式碼。 - ***更少的樣板程式碼***:您可以直接從資料結構中提取值,而無需建立中間變數。 - ***更簡潔的程式碼***:解構可以減少實現相同結果所需的程式碼行數。 - ***靈活性***:您可以解構任何類型的資料結構(物件、陣列、迭代),使其成為 JavaScript 工具包中的多功能工具。 有效的解構🚀使我們能夠編寫更具***表現力***、***可維護性***和***高效性的***程式碼,並且更容易理解和除錯。 基本範例 ---- ``` const person = { name: 'John', age: 30 }; const { name, age } = person; console.log(name); // "John" console.log(age); // 30 ``` 在這裡,我們解構了一個具有兩個屬性的物件`person` : `name`和`age` 。 解構 JavaScript 物件時,我們提取的值必須與物件中的鍵完全相同。您不能將`userName`取代該行中的`name` `const { name, age } = person;` 。這只是意味著 - `const { userName, age } = person;`行不通的。 但是,是的!我們可以在解構物件時套用別名。 EG- ``` const person = { name: 'John', age: 30 }; const { name:userName, age:userAge } = person; console.log(userName); // "John" console.log(userAge); // 30 ``` 您很可能在導入模組時第一次看到物件的解構。例如,當導入 exec 函數時 - ``` import { exec } from "node:child_process"; // ES Module syntax ``` ``` const { exec } = require("child_process"); // commonJS syntax ``` **同樣,我們也可以解構陣列**- ``` const numbers = [4, 5, 6]; const [x, y, z] = numbers; console.log(x); // 4 console.log(y); // 5 console.log(z); // 6 ``` 在這裡,當解構陣列時,您不需要使用別名將任何元素指派給自訂變數名稱。因為陣列元素只是值,所以它們不與某些鍵綁定。 預設值 --- 如果物件中不存在屬性,則解構允許您為變數指派預設值。 ``` const person = { name: 'John' }; const { name = 'Anonymous', age } = person; // age will be undefined console.log(name); // "John" console.log(age); // undefined ``` 這裡,字串值`'John'`沒有被變數`name`中的值`'Anonymous'`替換,因為它已經存在於物件中。 然而 - ``` const person = { name: 'John' }; const { name, age = 30 } = person; // age defaults to 30 if not present console.log(name); // "John" console.log(age); // 30 ``` 傳播文法 ---- **擴展**語法或**運算子**`(...)`可以與解構一起使用,以將陣列的剩餘元素或物件的屬性捕獲到新變數中。 - 使用陣列的擴充語法 - ``` const numbers = [1, 2, 3, 4, 5]; const [first, second, ...rest] = numbers; console.log(first); // 1 console.log(second); // 2 console.log(rest); // [3, 4, 5] (remaining elements) ``` - 物件的擴展語法 - ``` const person = { name: 'John', age: 30, city: 'New York' }; const { name, ...info } = person; console.log(name); // "John" console.log(info); // { age: 30, city: "New York"} (remaining properties) ``` 嵌套解構 ---- 解構可以嵌套以從深度嵌套的物件或陣列中提取值。 ``` const data = { user: { name: 'Alicia', origin: 'Romania', eyes: 'blue', address: { city: 'London', } } }; const { user: { name, address: { city } } } = data; console.log(name); // "Alicia" console.log(city); // "London" ``` 函數參數列表中的解構 ---------- 假設我們有一個名為`credentials`的JavaScript物件 - ``` const credentials = { name: 'Debajyati', age: 20, address: { city: 'Kolkata', state: 'West Bengal', country: 'India' }, phone: '', email: '', hobbies: ['reading', 'listening to music', 'coding', 'watching Anime'], skills: { programming: true, blogging: true, singing: false } } ``` 名為`showCredentials`的函數只接受 1 個參數值,該參數值是一個物件,而 Standard 會根據某些物件屬性輸出一個字串。 好吧,我們可以這樣寫函數定義 - ``` function showCredential(obj) { const hasSkill = (skill) => obj.skills[skill]; console.log( `${obj.name} is ${obj.age} years old.\n Lives in ${obj.address.city}, ${obj.address.country}.\n`, `He has the following hobbies: ${obj.hobbies.join(", ")}`, ); if (hasSkill("programming")) { console.log(`He is a programmer.`); } if (hasSkill("singing")) { console.log(`He is a singer.`); } if (hasSkill("blogging")) { console.log(`He is also a tech blogger.`); } } ``` 用 - 來呼叫它 ``` showCredential(credentials); ``` 得到這個輸出 - ``` Debajyati is 20 years old. Lives in Kolkata, India. He has the following hobbies: reading, listening to music, coding, watch ing Anime He is a programmer. He is also a tech blogger. ``` 相反,我們可以在定義函數時解構參數清單中的物件參數。像這樣 - ``` function showCredential({ name, age, address: { city, country}, hobbies, skills }) { const hasSkill = (skill) => skills[skill]; console.log( `${name} is ${age} years old.\n Lives in ${city}, ${country}.\n`, `He has the following hobbies: ${hobbies.join(", ")}`, ); if (hasSkill("programming")) { console.log(`He is a programmer.`); } if (hasSkill("singing")) { console.log(`He is a singer.`); } if (hasSkill("blogging")) { console.log(`He is also a tech blogger.`); } } ``` 給出相同的輸出。 &gt; | :資訊來源: 注意| |----------------------------------------| 函數仍然只接受一個參數。解構不會增加函數參數清單中的參數數量。 此外,呼叫該函數也沒有改變。依然是—— ``` showCredential(credentials); ``` ### 那麼,為什麼要解構函數參數列表中的物件呢? 雖然函數參數清單中的解構一開始可能看起來很麻煩或乏味,但它有非常重要的好處。 #### 需要考慮的要點 - ***更安全的程式碼:*** 解構可以清楚地表明函數需要哪些屬性,有助於防止錯誤。如果傳遞的物件中缺少屬性,解構將導致函數執行期間出現錯誤,有助於及早發現潛在問題。 - ***減少冗長:*** 透過直接將屬性提取到參數清單中的變數中,可以避免使用點表示法重複存取物件屬性。這導致函數定義更清晰、更簡潔。 - ***注重功能:*** 透過在參數清單中進行解構,您可以將資料存取邏輯與函數的核心功能分開。這改進了程式碼組織並使函數的目的更加清晰。 解構字串 ---- 就像我們如何解構陣列一樣,我們也可以將字串解包為陣列元素。巧妙地運用我們的智慧。 ``` const fruit = 'grape'; const [first, second, ...rest] = fruit; const animal = rest.join(''); console.log(animal); // ape ``` > | :警告:記住! |------------------------| 當您使用展開運算子`(...)`捕獲字串中的剩餘字元時,您不會得到字串。您將會得到這些字元的陣列。 解構的一些方便的應用範例 ------------ - ***沒有第三個變數的交換解構***: JavaScript 傳統上需要一個臨時變數來交換兩個變數的值。解構提供了一種更簡潔、更易讀的方式來實現這一目標。 ``` - Before Destructuring: ``` ``` let a = 10; let b = 20; let temp = a; a = b; b = temp; console.log(a, b); // Output: 20 10 ``` ``` - After Destructuring: ``` ``` let a = 10; let b = 20; [a, b] = [b, a]; console.log(a, b); // Output: 20 10 ``` ``` So nifty & elegant✨! Isn't it? ``` - ***解構函數傳回值***:函數可以以陣列或物件的形式傳回多個值。解構允許您將這些返回值解包到單獨的變數中,從而提高程式碼清晰度。 假設您有一個從 API 取得資料並傳回回應物件的函數: ``` function getUserUpdates(id) { // Simulating some API call with a GET request return { data: { player: response.group.names[id], brain: "rotting", powerLevel: Number(response.group.power[id]), useAsDecoy: true, }, statusCode: Number(response.status), }; } ``` 在建立 API 或處理伺服器回應的上下文中,它提供了增強程式碼品質和可維護性的獨特優勢。 存取各個屬性將變得輕而易舉,因為您可以在函數呼叫本身期間直接將所需的屬性從函數的返回值提取到單獨的變數中。 ``` const { data: {player, useAsDecoy, powerLevel}, statusCode, } = getUserUpdates(1); ``` 每當函數傳回物件並且您對特定屬性值感興趣時,請始終立即套用解構。 如果您仍然認為返回值的解構不是一個好主意,那麼這另外兩個優點可能會說服您 - (A)***簡化的心智模型:***解構簡化了將使用您的函數的開發人員理解資料流所需的思考過程。開發人員可以專注於解構模式中使用的變數名稱所傳達的含義,而不是記住複雜的屬性存取鏈。這減少了認知負擔並促進更好的程式碼理解。 (B)***簡化複雜回傳物件的樣板程式碼:*** 當函數傳回具有大量或嵌套屬性的物件時,解構會顯著減少單獨存取它們所需的樣板程式碼。這使得程式碼庫更加簡潔、更簡潔,從而提高了整體程式碼品質。 - ***帶條件的解構***:解構可以與條件語句結合起來,根據物件的結構來處理不同的場景。如果您有一個接收具有可選屬性的物件的函數: ``` function greetUser(user) { const { name = "Anonymous" } = user || {}; // Destructuring with default value console.log(`Hello, ${name}!`); } greetUser({ name: "Bob" }); // Output: "Hello, Bob!" greetUser({}); // Output: "Hello, Anonymous!" (no name property) greetUser(undefined); // Output: "Hello, Anonymous!" (function receives no argument) ``` 結論 -- 在整篇文章中,我們了解到**「解構」**是 JavaScript 中一個強大且多功能的功能,可以顯著提高程式碼的可讀性、可維護性和效率。透過有效地使用解構技術,您可以編寫更乾淨、更簡潔且不易出錯的程式碼。因此,擁抱解構並將您的 JavaScript 技能提升到一個新的水平! 如果您發現這篇文章有幫助,如果這個部落格為您的時間和精力增加了一些價值,請透過給這篇文章點讚來表達一些愛,並與您的朋友分享。 請隨時透過[Twitter](https://twitter.com/ddebajyati) 、 [LinkedIn](https://www.linkedin.com/in/debajyati-dey)或[GitHub](https://github.com/Debajyati)與我聯繫:) 快樂編碼🧑🏽‍💻👩🏽‍💻!祝你有個美好的一天! 🚀 --- 原文出處:https://dev.to/ddebajyati/exploring-destructuring-in-javascript-5a24

了解 JWT 身份驗證:帶有範例的綜合指南

在 Web 開發領域,安全性至關重要。保護 Web 應用程式最受歡迎的方法之一是 JSON Web 令牌 (JWT) 身份驗證。在本綜合指南中,我們將透過實際範例探討 JWT 身份驗證是什麼、它的工作原理以及如何在 Web 應用程式中實現它。 ### 什麼是 JWT 身份驗證? JWT 身份驗證是一種以 JSON 物件的形式在各方之間安全地傳輸資訊的方法。它通常用於驗證用戶身份並在客戶端和伺服器之間安全地傳輸資料。 ### JWT 身份驗證如何運作? JWT 身份驗證的工作原理是建立一個包含有關使用者或會話的編碼資訊的令牌。然後,該令牌隨每個請求從客戶端發送到伺服器,從而允許伺服器驗證請求的真實性並相應地授予存取權限。 以下是 JWT 身份驗證過程的簡化概述: 1. **使用者驗證**:當使用者登入 Web 應用程式時,伺服器會驗證他們的憑證(例如使用者名稱和密碼)。 2. **令牌產生**:身份驗證成功後,伺服器產生包含相關資訊(例如使用者 ID、過期時間)的 JWT,並使用金鑰對其進行簽署。 3. **令牌傳輸**:JWT 被發送回客戶端並儲存(通常在本機儲存或 cookie 中)以供將來使用。 4. **請求授權**:對於每個後續請求,用戶端都會在請求標頭中包含 JWT。 5. **令牌驗證**:伺服器驗證 JWT 的簽名並解碼其內容以驗證使用者身份並確定他們的存取權限。 6. **回應處理**:根據 JWT 的有效性和使用者的權限,伺服器處理請求並發送適當的回應。 ### JWT 的關鍵元件 - **標頭**:包含有關令牌的元資料,例如令牌的類型和使用的雜湊演算法。 - **Payload** :包含正在傳輸的實際資料,例如使用者資訊或權限。 - **簽章**:透過組合標頭、有效負載和金鑰來確保令牌的完整性。 ### JWT 身份驗證的好處 - **無狀態**:JWT 是獨立的,不需要伺服器端儲存會話資料,這使得它們非常適合無狀態架構。 - **可擴展性**:由於 JWT 不依賴伺服器端存儲,因此它們可以輕鬆擴展以適應大量用戶。 - **安全性**:JWT 經過數位簽名,提供了在各方之間傳輸資料的安全方式。 ### 實作 JWT 身份驗證:使用 Node.js 和 Express 的範例 讓我們來看一個在 Node.js 和 Express 應用程式中實作 JWT 身份驗證的簡單範例。 ``` // Required Libraries const express = require('express'); const jwt = require('jsonwebtoken'); // Create Express App const app = express(); // Secret Key for JWT Signing const secretKey = 'your-secret-key'; // Mock User Database const users = [ { id: 1, username: 'user1', password: 'password1' }, { id: 2, username: 'user2', password: 'password2' }, ]; // Route to Authenticate User and Generate JWT app.post('/login', (req, res) => { const { username, password } = req.body; const user = users.find(u => u.username === username && u.password === password); if (user) { // Generate JWT with user ID const token = jwt.sign({ userId: user.id }, secretKey); res.json({ token }); } else { res.status(401).json({ message: 'Invalid credentials' }); } }); // Middleware to Authenticate Requests const authenticateToken = (req, res, next) => { const token = req.headers['authorization']; if (!token) return res.status(401).json({ message: 'Unauthorized' }); jwt.verify(token, secretKey, (err, user) => { if (err) return res.status(403).json({ message: 'Invalid token' }); req.user = user; next(); }); }; // Protected Route app.get('/protected', authenticateToken, (req, res) => { res.json({ message: 'Protected route accessed successfully' }); }); // Start Server app.listen(3000, () => { console.log('Server running on port 3000'); }); ``` ### 結論 JWT 身份驗證是一種強大且廣泛使用的保護 Web 應用程式的方法。透過了解 JWT 的工作原理並遵循最佳實施實踐,您可以增強 Web 應用程式的安全性和可靠性。無論您是建立簡單的部落格還是複雜的企業應用程式,JWT 身份驗證都可以提供靈活且可擴展的解決方案來保護用戶資料並確保無縫的用戶體驗。 --- 原文出處:https://dev.to/vyan/understanding-jwt-authentication-a-comprehensive-guide-with-examples-1l3

Docker 在本地 Laravel 開發中的魅力

想要快速入門並跳過下面的詳細教學嗎?為您的作業系統安裝[Docker](https://docs.docker.com/docker-for-mac/install/) ,複製[此儲存庫](https://github.com/aschmelyun/docker-compose-laravel),將 Laravel 應用程式檔案新增至**src**目錄,然後從您剛剛複製的根專案目錄執行: `docker-compose build && docker-compose up -d` 。 簡介 -- 在開始之前,我們應該知道,本文並不是關於 Docker 的完整教程,也不是對該工具集複雜性的解釋。它更像是使用 Docker 和 docker-compose 快速設定本地開發環境的簡化演練,而不是直接在電腦上安裝 LAMP 堆疊。雖然有一些注意事項,但我發現下面的方法在開發 Laravel 應用程式時最適合我。 對於那些不知道 Docker 是什麼的人,讓我們先簡單了解一下。根據 opensource.com 報告: > [Docker](https://github.com/docker/docker)是一種工具,旨在讓使用容器更輕鬆地建立、部署和執行應用程式。容器允許開發人員將應用程式及其所需的所有部分(例如庫和其他依賴項)打包在一起,並將其全部作為一個套件發布。 您可以將 Docker 視為一個淡化的虛擬機器。 為什麼這有幫助或有用?如果您有多個執行不同版本的 Linux、PHP 或任何其他 Web 軟體的生產伺服器,那麼這些變數可以複製到您的容器中,並且可以保證應用程式將按照其預期在生產電腦上準確執行。 更符合本文的基調,如果您的本地計算機上有多個跨越不同版本的Laravel 專案,您可以為每個應用程式指定特定的Docker 配置,而無需實現PHP 版本切換器之類的東西並修改實際計算機的配置。您甚至可以同時存取這兩個專案,每個容器都彼此隔離執行。 聽起來令人興奮嗎?**讓我們深入了解一下吧!** 安裝 Docker --------- 在本文中,螢幕截圖和參考資料將與 MacOS 用戶相關。但是,Windows 上的安裝和使用說明應該非常相似(即使不是幾乎完全相同)。 首先,取得安裝程式: <https://docs.docker.com/docker-for-mac/install/> 。 執行典型的應用程式安裝過程,完成後打開應用程式。第一次開啟 Docker 時,系統會要求您透過系統密碼對 Docker 進行授權,之後您會看到頂部狀態列中出現小鯨魚圖示。 專案結構 ---- 以下是我在 Laravel + Docker 專案中使用的結構。儘管本文的其餘部分將假設您的專案是使用相同的佈局設定的,但您不必明確遵循這一點。 ``` my-project.com/ ├── nginx/ │ └── default.conf ├── src/ │ └── (Laravel app files) ├── docker-compose.yml └── Dockerfile ``` 在接下來的幾個部分中,我將介紹每個檔案的用途,但現在只需使用上面的佈局將它們建立為空白佔位符。此外,在**src/**目錄下新增(或建立)整個 Laravel 應用程式的檔案。 建立我們的堆疊 ------- 使用 Docker 時的一個重要經驗法則是每個容器都應該提供單一服務。由於我們正在建立一個典型的 LEMP 堆疊,這意味著我們需要一個用於 Web 伺服器 ( **Nginx** )、 **PHP**和**MySQL 的**堆疊。雖然理論上我們可以為每個服務建立單獨的容器,然後嘗試將它們連結在一起,但 Docker 有一個漂亮的內建工具,稱為**[docker-compose](https://docs.docker.com/compose/)** 。 我們所做的就是定義將要使用的服務,並在執行時 Docker 將每個服務提供為一個容器並將它們全部包裝在虛擬網路中。這意味著每個服務都可以從每個容器存取。 首先,打開**docker-compose.yml**檔案並將以下內容新增至其頂部: ![docker-compose.yml 截圖開始](https://cdn-images-1.medium.com/max/800/1*xNYoBOhF9G-TQFz3wVsYfg.png) 對我們剛剛加入的內容的一些快速解釋: - **版本:3** ,最新最推薦的docker-compose引擎版本 - **網路:**我們只使用一個網路**laravel** ,除了名稱之外我們沒有加入任何選項 - **服務:**我們將在其中指定構成堆疊的映像 新增 Nginx -------- 在我們在上面**docker-compose.yml**檔案底部指定的服務標題的正下方,您將加入以下內容: ![nginx 服務的 docker-compose.yml 截圖](https://cdn-images-1.medium.com/max/800/1*ioySVPvb1iSlIv7ev501VQ.png) 上面我們所做的就是告訴 Docker 我們想要一個名為**nginx**的容器,它是從 nginx:stable-alpine 映像建置的(您可以[在此處](https://github.com/nginxinc/docker-nginx/blob/14c1b938737cf4399a6bb039bc506957dce562ae/stable/alpine/Dockerfile)查看其完整原始程式碼)。我們使用 alpine linux 作為基礎作業系統,因為它輕巧且響應靈敏。 接下來,我們將容器命名為**nginx**並將其`:80`連接埠在本機電腦上公開為`:8080` 。我們最終將使用此連接埠號碼來存取我們的網站,您可以將其調整為您喜歡的任何非保留連接埠號碼。 對於 Web 伺服器的捲,我們新增以下兩項: - 我們的本地**/src**資料夾綁定到容器的**/var/www**路徑。與符號連結不同,我們在 /src 中修改的任何內容都將立即可供 /var/www 下的伺服器使用。 - 我們建立的**/nginx/default.conf**檔案連結到**/etc/nginx/conf.d/default.conf**容器文件,並且使我們能夠修改本地電腦上的 nginx Web 伺服器。 您可以在此標題下指定任意數量的目錄或文件,以將它們從本機電腦符號連結到 nginx 容器。 透過在**depends\_on**專案下加入php和mysql(我們接下來將建立的服務),我們告訴Docker在初始化時php和mysql容器需要在nginx之前執行。此外,如果我們嘗試只啟動 nginx 容器,它也會啟動這兩個依賴容器。 最後,我們明確指定容器位於我們在 docker-compose.yml 檔案開頭所建立的**laravel**網路下。 新增MySQL ------- 我們要加入**docker-compose.yml**檔案中的下一個服務是 MySQL。這個相對簡單。 ![docker-compose.yml 截圖新增mysql服務](https://cdn-images-1.medium.com/max/800/1*0rXBlDAOOWxUQnDPy7lvMQ.png) 最初,我們指定映像和容器名稱,以及設定一些我認為有助於維護 MySQL 在容器中的穩定性的其他設定。 預設的 MySQL 端口`:3306`是我們向本地計算機公開的端口,然後使用**環境**物件,我們可以設定初始化期間使用的一些變數來修改建立的資料庫。由於我們正在為 Laravel 應用程式配置 Docker,因此我使用典型 Laravel .env 檔案中的預設資料庫名稱/使用者名稱/密碼。 就像 nginx 一樣,我們將此服務附加到**laravel**網路。 ✨ 簡單! 新增 PHP ------ 與 Nginx 和 MySQL 不同,新增**PHP**容器將採取不同的、*稍微*複雜的路徑。透過前兩個服務,我們能夠直接引用映像來建置我們的容器,但是由於 Laravel 需要依賴項,我們實際上將基於本機 Dockerfile 建置我們自己的映像。 在我們開始這部分之前,將以下內容作為下一個(也是最後一個)服務加入到我們的**docker-compose.yml**檔案中。 ![新增php服務的docker-compose.yml截圖](https://cdn-images-1.medium.com/max/800/1*N8S_9gJheDvwcXIpuphk2Q.png) 您已經可以發現差異,我們正在用**建置**標題替換之前使用的**圖像**標題。在它下面,我們將上下文指定為當前專案目錄,並將 dockerfile 指定為 Dockerfile(我們之前已經建立了)。 與我們的 nginx 容器一樣,我們為根目錄指定相同的捲,然後為容器公開連接埠`:9000`並將網路設定為**laravel** 。 現在我們已經加入了該服務,是時候將以下內容加入到我們的**Dockerfile**中了: ![用於建立 PHP 映像的 Dockerfile 螢幕截圖](https://cdn-images-1.medium.com/max/800/1*eCT3BxPVZ2w7redLrfHpKA.png) 是的,就是這樣。 我們在這裡所做的就是: - 指定我們希望從`7.2-fpm-alpine` PHP 映像建置 php 容器。 - 安裝 Laravel 的 ORM 與其資料庫方法一起使用的`pdo`和`pdo_mysql` PHP 擴充。 `docker-php-ext-install`指令是 Docker 內建的(並且[沒有詳細記錄](https://docs.docker.com/samples/library/php/#how-to-install-more-php-extensions))。您可以傳遞任何 PHP 擴展,它將在我們新建立的容器中處理安裝和配置。 配置nginx ------- 還記得我們建立的**/nginx/default.conf**檔案嗎?打開它並加入以下內容: ![預設 nginx 設定的螢幕截圖](https://cdn-images-1.medium.com/max/800/1*GhwmexAjEEbdags1CQOowg.png) 老實說,這裡沒有太多可討論的,因為它主要是與大多數基本 Laravel 應用程式一起使用的樣板 nginx 配置。請注意,根路徑設定為我們將 Laravel 應用程式連結到的**/var/www** nginx 目錄的公共資料夾。 啟動 Docker --------- 我們已經將所有單獨的部分都準備好了,現在終於可以組裝我們的 Docker 網路了!開啟終端機視窗並導航到該專案的根目錄。由於我們的一個容器( **php** )使用 Dockerfile 作為其映像,並且這是我們第一次啟動這些容器,因此我們需要做的第一件事是執行**建置**命令來產生映像資料: `docker-compose build` 這需要一些時間才能完成,並且可能看起來有一段時間沒有發生任何事情。大約 1-2 分鐘後,您應該會在終端機中看到**「已成功建置」**和**「已成功標記」**訊息。然後,您可以使用以下命令繼續實際啟動容器: `docker-compose up -d` Docker 將建立我們的 laravel 網絡,然後建立我們在 docker-compose.yml 檔案的 services 部分中指定的三個容器。如果您對**-d**標誌感到好奇,它代表**分離**並在處理完所有命令後保持容器執行。否則,一旦完成初始化,Docker 就會停止它們。對於網頁伺服器來說毫無意義! 配置 Laravel ---------- 在我們第一次存取我們的應用程式之前,我們需要對 Laravel .env 檔案進行一些小的調整。特別是關於資料庫連接和應用程式域。在**src**目錄中開啟專案的`.env`檔案並修改以下行: - `DB_HOST=mysql` - 這個名稱來自我們在 docker-compose.yml 檔案中建立的 MySQL 服務,並在 Docker 網路中用於引用其他容器中的服務。 - `APP_URL=http://localhost:8080` - 新增您在 nginx 容器中公開的連接埠號,以使其指向可解析的位址。 存取您的應用程式 -------- 假設上述步驟中的所有內容都已成功啟動,我們現在可以使用公開的連接埠存取我們的容器並查看我們應用程式的登陸頁面! 在瀏覽器中,導覽至<http://localhost:8080> ,其中**8080**是您在 docker-compose.yml 檔案中的 nginx 服務下指定的**第一個**連接埠。 ![顯示 Laravel 登陸畫面的瀏覽器螢幕截圖](https://cdn-images-1.medium.com/max/800/1*p3yulsFx0g_Szh_2hqfkPg.png) 💥 繁榮!我們的 Laravel 應用程式在 Docker 網路中執行! 當然,如果您可能還想使用[TablePlus](https://tableplus.io/)之類的工具存取 MySQL 資料庫,那麼連接到該資料庫也同樣簡單。您要做的就是使用`127.0.0.1`作為主機,以及您在 docker-compose.yml 檔案中的 MySQL 服務下公開的連接埠(在本範例中,我們將其保留為預設值**3306** ) 。 我們在環境變數中指定的使用者名稱和密碼分別為`MYSQL_USER`和`MYSQL_PASSWORD` 、 **homestead**和**Secret** 。 ![TablePlus 設定的螢幕截圖](https://cdn-images-1.medium.com/max/2000/1*oupY3mehpHd2bItaf_tNzw.png) **注意:**如果您打算為不同的專案同時執行多個網絡,則必須指定不同的連接埠以在本機電腦上公開(例如,一個為 8080,另一個為 8081)。否則,在容器初始化期間,您將收到`port is already allocated`錯誤。 執行命令 ---- Laravel 經常使用命令列來進行遷移、佇列和測試等操作。使用 docker-compose 的`exec`指令在我們的 Docker 網路上執行這些指令非常簡單。 **Docker 不是透過 ssh 進入系統並直接在作業系統上執行命令的虛擬機,而是偏好將命令傳遞到容器,**然後將這些命令的輸出回顯到終端。例如,讓我們透過在專案根目錄的終端機中執行以下命令來執行 Laravel 附帶的預設遷移: `docker-compose exec php php /var/www/artisan migrate` 讓我們稍微分解一下: - **docker-compose exec**告訴 Docker 我們要在容器網路上執行指令。 - **php**我們要執行指令的容器名稱。由於我們要執行 PHP 命令,因此它需要位於執行 PHP 的容器上。 - **php /var/www/artisan 遷移**我們正在執行的指令的實際名稱。我們使用 artisan 的絕對路徑,該路徑通過 ./src 的本地捲進行符號連結,並執行標準的 Laravel 遷移。 ![執行 docker-compose migrate 指令後的終端螢幕截圖](https://cdn-images-1.medium.com/max/800/1*HUKD-2efKCz8jM1G0Eg_eQ.png) 執行我們的命令後,您應該會看到遷移輸出,並且您的資料庫現在將填充兩個表! 可以從本機終端將任意數量的命令執行到我們選擇的 Docker 容器。只需注意要在其上執行命令的容器中安裝和可用的服務即可。 **提示:**如果您堅持要直接透過 ssh 進入容器來執行命令,有一個非常簡單的解決方法。跑步 `docker-compose exec {container_name} /bin/sh`將開啟與 {container\_name} 參數中指定的容器的持久連線。 隊伍的盡頭 ----- 好吧,我們就有了!我們已經安裝了 Docker,設定並配置了 docker-compose 檔案來建立包含在單一網路中的三個容器的 LEMP 堆疊,在該網路上公開了允許我們存取應用程式和資料庫的端口,甚至執行了 cli 命令透過docker-compose的exec方法。 展望未來,如果您想關閉容器和網絡,只需導航到專案的根資料夾並執行即可 `docker-compose down` 。這將關閉並銷毀容器以及儲存在其中的**任何關聯的非磁碟區資料**。 當我處理跨越不同 Laravel 版本的多個專案時,Docker 為我開啟了一個充滿開發可能性的世界。我可以使用`7.1`輕鬆地在具有 PHP 容器的 Docker 網路上執行一個專案,如果我想了解當前專案在 PHP `7.3`中的執行情況,只需更改 Dockerfile 中的**單個字符**,重新建置容器即可,並恢復docker -compose 網路。 我不會否認,與直接在機器硬體上執行堆疊相比,您不會獲得更好的本地開發效能。但對我來說,**性能**與**多功能性、易用性、並行環境和客製化的**權衡遠遠超過了這些。 如果您有任何問題、意見或想進一步討論 PHP 和 Laravel,請隨時在[Twitter](https://twitter.com/aschmelyun)上與我聯絡!如果您正在尋找**專門針對 Laravel 應用程式的超級簡單錯誤和日誌監控服務**,我已經建立了[Larahawk](https://larahawk.com) 。它目前處於內測階段,很快就會推出,每個應用程式每月只需 5 美元。 --- 原文出處:https://dev.to/aschmelyun/the-beauty-of-docker-for-local-laravel-development-13c0

您可以在開源中貢獻這 25 個專案

受資助計畫的聲譽非常好,因為它們獲得了大量資金並得到了風險投資的支持。 有很多開源專案,你絕對應該為這些專案做出貢獻,特別是因為它們的可信度要高得多。 也許你有機會獲得直接的工作機會,畢竟你真的不知道誰在開源中關注你! 我只保留了活躍的專案(最後一次提交不到 2 個月),所以它會很有用。讓我們保持簡短和直接。 --- 1. [Taipy](https://github.com/Avaiga/taipy) - 資料和人工智慧演算法融入生產級網路應用程式。 -------------------------------------------------------------------- ![打字](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wd10iiofzmt4or4db6ej.png) Taipy 是用於輕鬆、端到端應用程式開發的完美 Python 程式庫,具有假設分析、智慧型管道執行、內建調度和部署工具。 它用於為基於 Python 的資料和人工智慧應用程式建立 GUI 介面並改進資料流管理。 關鍵是性能,而 Taipy 是完美的選擇,尤其是與 Streamlit 相比。您可以閱讀 Marktechpost 發表的[Taipy 與 Streamlit](https://www.marktechpost.com/2024/03/15/taipy-vs-streamlit-navigating-the-best-path-to-build-python-data-ai-web-applications-with-multi-user-capability-large-data-support-and-ui-design-flexibility/)的詳細比較。 - 💰 獲得總資金 500 萬美元。 - 🚀 使用的主要語言是Python。 Taipy 在 GitHub 上有近 10k 顆星,並且正在發布`v3.1`版本。 https://github.com/Avaiga/taipy Star Taipy ⭐️ --- 2. [Hoppscotch](https://github.com/hoppscotch/hoppscotch) - API 開發生態系統。 ----------------------------------------------------------------------- ![跳房子](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/75cjol6454uvrnth524y.png) Hoppscotch 是一個輕量級、基於 Web 的 API 開發套件。它是從頭開始建置的,考慮到了易用性和可存取性。 Hoppscotch 與 Postman 非常相似,但提供了一些不同的功能。這就是儀表板的樣子,您可以在[hoppscotch.io](https://hoppscotch.io/)上進行即時測試。 ![跳房子](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2f6ck92qdpd99in6wav.png) 即使測試本機 API,Postman 也要求您保持線上狀態。使用 Hoppscotch,您可以在沒有網路連線的情況下使用 API。 甚至 Web 應用程式也可以透過本機快取離線執行並充當 PWA,讓您可以隨時隨地測試 API! Hoppscotch 也提供私人工作空間。請參閱[完整功能清單](https://github.com/hoppscotch/hoppscotch?tab=readme-ov-file#features)。 ![特徵](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d36kmr72z11h71nnvhf5.png) 最好的部分也是必要的部分是他們提供完整的[文件](https://docs.hoppscotch.io/),其中包括指南、文章、支援和變更日誌,以便您可以在這裡看到所有內容。 ![2023年已結束](https://hoppscotch.com/images/blog-hoppscotch-wrapped-2023.png) - 💰 獲得總資金 300 萬美元。 - 🚀 使用的主要語言是 TypeScript。 Hoppscotch 在 GitHub 上擁有超過 60k 顆星,有 300 多個活躍問題和 200 多個貢獻者。 https://github.com/hoppscotch/hoppscotch 明星跳房子 ⭐️ --- 3. [Daily](https://github.com/dailydotdev/daily) - 每個開發者都值得擁有的首頁。 ----------------------------------------------------------------- ![日常的](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qvzd1auk8wet7vv5ev37.png) 這是一個專業網絡,您可以在其中閱讀與開發者生態系統相關的文章和個人化動態訊息。 他們匯總了來自許多組織(例如 Hacker News、Dev、Hashnode 等)的各種主題的有價值的帖子。您可以投票、加書籤,甚至建立自己的小隊。 ![小隊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqqkl42pja53ssywltyl.png) 我是其中一些功能的粉絲,如果我解釋所有內容,我會花費幾個小時,所以最好檢查一下。 這是我個人最喜歡的開源專案之一。你可以查看我的[每日個人資料](https://app.daily.dev/anmolbaranwal)。 - 💰 獲得總資金 1100 萬美元。 - 🚀 使用的主要語言是 TypeScript。 Dailydotdev 在 GitHub 上擁有 17k+ 顆星。 https://github.com/dailydotdev/daily 明星日報 ⭐️ --- 4. [Requestly](https://github.com/requestly/requestly) - 瀏覽器的 HTTP 攔截器。 ----------------------------------------------------------------------- ![請求地](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1jnfzpqe827qxm11a1tm.png) Requestly 的建置是為了透過攔截和修改 HTTP 請求來節省開發人員的時間。 Requestly 為前端開發人員提供必要的工具和整合協助,幫助他們以 10 倍的速度編寫、測試和偵錯程式碼。 Requestly 減少了對後端開發人員和開發和測試需求環境的依賴。 使用 Requestly,開發人員可以建立模擬、測試、驗證和覆蓋 API 回應,修改請求和回應標頭,設定重定向(映射本機、映射遠端),並使用 Requestly 會話進行更快的偵錯。 您可以看到[完整功能](https://github.com/requestly/requestly?tab=readme-ov-file#-features)的清單。 - 💰 獲得 50 萬美元的種子資金。 - 🚀 使用的主要語言是 TypeScript。 Requestly 在 GitHub 上擁有超過 1,800 顆星,並且正在快速成長。 https://github.com/requestly/requestly 為請求加星號 ⭐️ --- 5.[重新發送](https://github.com/resend)- 給開發人員的電子郵件。 ------------------------------------------------ ![重發](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a7diqqs4n4yrshxf22l3.png) 電子郵件可能是人們溝通的最重要的媒介。然而,我們需要停止像 2010 年那樣開發電子郵件,並重新思考 2022 年及以後如何開發電子郵件。它應該針對我們今天建立網頁應用程式的方式進行現代化。 他們提供了許多與我們正在使用的技術堆疊相對應的不同儲存庫。請隨意探索其中每一個。 ![重新發送集成](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4jmx7q5i4wrsnwgcuvwk.png) - 💰 獲得 350 萬美元種子資金。 - 🚀 使用的主要語言是 TypeScript(React 電子郵件)。 Resend(React email)在 GitHub 上擁有超過 12,500 顆星,並被超過 7,500 名開發者使用。 https://github.com/resend 星標重新發送 ⭐️ --- 6. [Buildship](https://github.com/rowyio/buildship/) - 由人工智慧驅動的低程式碼視覺後端建構器。 --------------------------------------------------------------------------- ![建造船](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzlrynz5xephv4t9layd.png) 對於您正在使用無程式碼應用程式建構器(FlutterFlow、Webflow、Framer、Adalo、Bubble、BravoStudio...)或前端框架(Next.js、React、Vue...)建立的應用程式,您需要一個後端來支援可擴展的 API、安全工作流程、自動化等。 BuildShip 為您提供了一種完全視覺化的方式,可以在易於使用的完全託管體驗中可擴展地建立這些後端任務。 這意味著您無需在雲端平台上爭論或部署事物或執行 DevOps。只需立即建造和發貨 🚀 他們甚至與 TypeSense 合作並且發展得非常快! ![建造船](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6oc3rc713mjg9cwqj7d4.png) 我嘗試過Buildship,它很強大。 - 💰 私人資金(由 Google、Vercel、Figma 等支持)。 - 🚀 使用的主要語言是 TypeScript。 它在 GitHub 上有 260 多顆星,使用 Rowy 完成,有 5800 顆星。 https://github.com/rowyio/buildship/ 明星 BuildShip ⭐️ --- 7. [Cal](https://github.com/calcom/cal.com) - 為所有人安排基礎設施。 --------------------------------------------------------- ![卡爾](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ccagnexb805xzpewfy5.png) 這是有史以來最活躍的專案之一。我也透過 Cal 的 Algora 看過很多付費演出。 早些時候,我使用 Calendly,但我將其切換到 Cal,特別是因為它們在您可以建立的連結方面提供了更大的靈活性。 例如,我有一個協作連結,人們可以在其中選擇會議的持續時間並修復其他連結中的時間安排。您可以將其附加到幾乎所有應用程式,例如 GMeet、Zoom,如果您想參加付費會議,甚至可以同步付款。應用程式整合的[總選項](https://cal.com/apps)幾乎令人難以置信:) ![整合](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/anesuu0ux6ejz886irnt.png) 您可以做很多事情,包括自動化工作流程,所以只需檢查一下即可。 ![工作流程儀表板](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kc0x5vq54joov98wwq9h.png) - 💰 獲得總資金(A 輪)3240 萬美元。 - 🚀 使用的主要語言是 TypeScript。 Cal 在 GitHub 上擁有超過 29,000 顆星,並擁有超過 600 名貢獻者。 https://github.com/calcom/cal.com Star Cal ⭐️ --- 8. [Penpot](https://github.com/penpot/penpot) - 完美協作的設計工具。 ---------------------------------------------------------- ![筆筒](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mooryn8zodod2mkpzefn.png) Penpot 是第一個用於設計和程式碼協作的開源設計工具。設計師可以大規模建立令人驚嘆的設計、互動式原型和設計系統,而開發人員則可以享受現成的程式碼,並使他們的工作流程變得簡單、快速。所有這一切都沒有任何切換戲劇性的情況。 完全免費並符合開放標準(SVG、CSS 和 HTML)。 一次性查看[庫、模板](https://penpot.app/libraries-templates)和[功能](https://penpot.app/features)的清單。 觀看以下影片體驗`Penpot 2.0` 。 - 💰 獲得總資金 800 萬美元。 - 🚀 使用的主要語言是 Clojure。 Penpot 在 GitHub 上擁有超過 28,500 顆星,目前已發布`v2.0`版本。 https://github.com/penpot/penpot 星星筆罐 ⭐️ --- 9. [Appsmith](https://github.com/appsmithorg/appsmith) - 建立管理面板、內部工具和儀表板的平台。 ---------------------------------------------------------------------------- ![應用史密斯](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rt7s0r3wz2leec83cl17.png) 管理面板和儀表板是任何軟體創意(在大多數情況下)的一些常見部分,我嘗試從頭開始建立它,這會帶來很多痛苦和不必要的辛苦工作。 您可能已經看到組織建立了內部應用程式,例如儀表板、資料庫 GUI、管理面板、批准應用程式、客戶支援儀表板等,以幫助其團隊執行日常操作。正如我所說,Appsmith 是一個開源工具,可以實現這些內部應用程式的快速開發。 首先,請觀看這個 YouTube 影片,該影片在 100 秒內解釋了 Appsmith。 嵌入 https://www.youtube.com/watch?v=NnaJdA1A11s 他們提供拖放小部件來建立 UI。 您可以使用 45 多個可自訂的小工具在幾分鐘內建立漂亮的響應式 UI,而無需編寫一行 HTML/CSS。尋找[小部件的完整清單](https://www.appsmith.com/widgets)。 ![按鈕點擊小工具](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kqpnnslvsvjl4gifseon.png) ![驗證](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/489fly7tvknz2uv2mgei.png) 您可以閱讀[文件](https://docs.appsmith.com/)並使用這[20 多個範本](https://www.appsmith.com/templates)中的任何一個,以便您可以快速入門。 - 💰 獲得 500 萬美元種子資金。 - 🚀 使用的主要語言是 TypeScript。 Appsmith 在 GitHub 上擁有超過 32k 顆星,發布了 200 多個版本。 https://github.com/appsmithorg/appsmith Star Appsmith ⭐️ --- 10.[二十](https://github.com/twentyhq/twenty)- Salesforce 的現代替代品。 --------------------------------------------------------------- ![二十](https://framerusercontent.com/images/oclg8rdRgBnzeLnSJOfettLFjI.webp) 我們花了數千個小時來研究Pipedrive 和Salesforce 等傳統CRM,以使它們與我們的業務需求保持一致,但最終卻感到沮喪——定制非常複雜,而且這些平台的封閉生態系統可能會讓人感到受到限制。 Twenty 是一個現代化、功能強大、價格實惠的平台,用於管理您的客戶關係。您可以閱讀[使用者指南](https://twenty.com/user-guide)。 ![二十](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tucrt5pk9piyswnt9q77.png) - 💰 獲得 75.9 萬美元的種子資金。 - 🚀 使用的主要語言是 TypeScript。 Twenty 在 GitHub 上擁有超過 14,500 顆星,擁有 200 多名貢獻者。 https://github.com/twentyhq/twenty 二十星 ⭐️ --- 11.[繼續](https://github.com/continuedev/continue)-AI程式碼助手。 -------------------------------------------------------- ![繼續 gif](https://github.com/continuedev/continue/raw/main/docs/static/img/understand.gif) Continue 是領先的開源 AI 程式碼助理。您可以連接任何模型和任何上下文,以在[VS Code](https://marketplace.visualstudio.com/items?itemName=Continue.continue)和[JetBrains](https://plugins.jetbrains.com/plugin/22707-continue-extension)內建立自訂自動完成和聊天體驗。 > 選項卡可自動完成程式碼建議。 ![自動完成 gif](https://github.com/continuedev/continue/raw/main/docs/static/img/autocomplete.gif) > 重構您正在編碼的函數。 ![重構影像](https://github.com/continuedev/continue/raw/main/docs/static/img/inline.gif) > 詢問有關您的程式碼庫的問題。 ![程式碼庫](https://github.com/continuedev/continue/raw/main/docs/static/img/codebase.gif) > 快速使用文件作為上下文 ![文件上下文 gif](https://github.com/continuedev/continue/raw/main/docs/static/img/docs.gif) 閱讀[快速入門指南](https://docs.continue.dev/quickstart)。 - 💰 獲得 210 萬美元種子資金。 - 🚀 使用的主要語言是 TypeScript。 Continue 在 GitHub 上有 12k+ 顆星,並且發布了`v0.8`版本。 https://github.com/continuedev/continue 星繼續 ⭐️ --- [12.Refine](https://github.com/refinedev/refine) - 面向企業的開源 Retool。 ------------------------------------------------------------------ ![精煉](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7wsti2yfikrhc9nggov5.png) Refine 是一個元 React 框架,可以快速開發各種 Web 應用程式。 從內部工具到管理面板、B2B 應用程式和儀表板,它可作為建立任何類型的 CRUD 應用程式(例如 DevOps 儀表板、電子商務平台或 CRM 解決方案)的全面解決方案。 ![電子商務](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xry9381y4s36emgb9psr.png) 您可以在一分鐘內使用單一 CLI 命令進行設定。 它具有適用於 15 多個後端服務的連接器,包括 Hasura、Appwrite 等。 但最好的部分是,Refine `headless by design` ,從而提供無限的樣式和自訂選項。 你可以看到[模板](https://refine.dev/templates/)。 ![範本](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87vbx5tqyicb9gmgirka.png) - 💰 獲得總資金 380 萬美元。 - 🚀 使用的主要語言是 TypeScript。 它們在 GitHub 上擁有大約 25,000 顆星,並被超過 3,000 名開發人員使用。 https://github.com/refinedev/refine 星際精煉 ⭐️ --- 13. [Revideo](https://github.com/redotvideo/revideo) - 使用程式碼建立影片。 ----------------------------------------------------------------- ![審查](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ttwzahj6kfgllj0aknt1.png) Revideo 是一個用於程式化影片編輯的開源框架。它是從令人驚嘆的 Motion Canvas 編輯器分叉出來的,將其從獨立的應用程式轉變為開發人員可以用來建立整個影片編輯應用程式的庫。 Revideo 可讓您在 Typescript 中建立視訊範本並部署 API 端點以使用動態輸入呈現它們。它還提供了一個React播放器元件來即時預覽瀏覽器中的變化。 - 💰 獲得總資金 500 萬美元。 - 🚀 使用的主要語言是 TypeScript。 Revideo 在 GitHub 上有 1.2k 顆星,活躍問題非常少。簡而言之,這是一個完美的、不那麼擁擠的貢獻專案。 https://github.com/redotvideo/revideo 明星重錄 ⭐️ --- 14.[百萬](https://github.com/aidenybai/million)- 讓你的 React 速度提高 70%。 ------------------------------------------------------------------ ![百萬](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/afs9dm1eujmajxn0rng9.png) Million.js 是一個極其快速且輕量級的最佳化編譯器,可將元件速度提高 70%。自己探索吧! ![特徵](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vozcs5gd57rwlp3jjmr4.png) - 💰 獲得總計 50 萬美元的資金。 - 🚀 使用的主要語言是 TypeScript。 Million 在 GitHub 上擁有超過 15,500 顆星,並被超過 3000 名開發者使用。 https://github.com/aidenybai/million 明星百萬⭐️ --- 15. [FlowiseAI](https://github.com/FlowiseAI/Flowise) - 拖放 UI 來建立您的客製化 LLM 流程。 ------------------------------------------------------------------------------ ![弗洛伊薩伊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r5bp43nil764fhe4a05z.png) Flowise 是一款開源 UI 視覺化工具,用於建立客製化的 LLM 編排流程和 AI 代理程式。 ![整合](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ahk2ovjrpq1qk3r5pfot.png) 您可以閱讀[文件](https://docs.flowiseai.com/)。 ![流程化人工智慧](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trkltpn5lk1y1pte0smd.png) - 💰 從 YCombinator 獲得資金(不知道多少)。 - 🚀 使用的主要語言是 TypeScript。 FlowiseAI 在 GitHub 上擁有超過 26,500 個 Star,並擁有超過 13,000 個分叉,因此具有良好的整體比率。 https://github.com/FlowiseAI/Flowise 明星 FlowiseAI ⭐️ --- 16.[觸發器](https://github.com/triggerdotdev/trigger.dev)——後台作業平台。 --------------------------------------------------------------- ![扳機](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iaoox3qwmc397x9ckmw4.png) Trigger.dev v3 可以輕鬆編寫可靠的長時間執行任務而不會逾時。 在它們所屬的地方建立作業:在您的程式碼庫中。像您已經習慣的那樣進行版本控制、本地主機、測試、審查和部署。 您可以選擇在自己的基礎架構上使用觸發器雲端或自架觸發器。 閱讀文件中的[快速入門指南](https://trigger.dev/docs/v3/quick-start)。 - 💰 獲得總資金 300 萬美元。 - 🚀 使用的主要語言是 TypeScript。 Trigger 在 GitHub 上有 7,500 顆星,目前已發布`v3.1`版本。 https://github.com/triggerdotdev/trigger.dev 星觸發器 ⭐️ --- 17. [Tiptap](https://github.com/ueberdosis/tiptap) - 無頭富文本編輯器框架。 ---------------------------------------------------------------- ![尖擊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gdtmi7do65ks6f2mpsjd.png) Tiptap 編輯器是一個無頭、與框架無關的富文本編輯器,可以透過擴充功能進行自訂和擴充。它的無頭性質意味著它沒有固定的使用者介面,提供完全的設計自由(要快速入門,請參閱下面連結的 UI 模板)。 Tiptap 是基於高度可靠的 ProseMirror 庫。 Tiptap Editor 得到協作開源後端 Hocuspocus 的補充。 Editor 和 Hocuspocus 構成了 Tiptap Suite 的基礎。 我建議閱讀包含[範例](https://tiptap.dev/docs/editor/examples/default)和詳細程式碼的[文件](https://tiptap.dev/docs/editor/introduction)。 - 💰 獲得總資金 260 萬美元。 - 🚀 使用的主要語言是 TypeScript。 ![尖擊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20c83ios6ugr1q6blqfq.png) Tiptap 在 GitHub 上擁有超過 24k 顆星,擁有 300 多名貢獻者。 https://github.com/ueberdosis/tiptap 明星 Tiptap ⭐️ --- 18. [Infisical](https://github.com/Infisical/infisical) - 秘密管理平台。 ----------------------------------------------------------------- ![內部的](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jrolzjdnkky1r694h9av.png) Infisical 是一個開源秘密管理平台,團隊可以用它來集中 API 金鑰、資料庫憑證和設定等秘密。 他們讓每個人(而不僅僅是安全團隊)都可以更輕鬆地進行秘密管理,這意味著從頭開始重新設計整個開發人員體驗。 ![內部](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3eu288l470du91b66pd.png) Infisical 還提供了一組工具來自動防止 git 歷史記錄的秘密洩露。可以使用預提交掛鉤或透過與 GitHub 等平台直接整合在 Infisical CLI 層級上設定此功能。 您可以閱讀[文件](https://infisical.com/docs/documentation/getting-started/introduction)並檢查如何[安裝 CLI](https://infisical.com/docs/cli/overview) ,這是使用它的最佳方式。 在使用整個原始程式碼之前一定要檢查他們的[許可證](https://github.com/Infisical/infisical/blob/main/LICENSE),因為他們有一些受 MIT Expat 保護的企業級程式碼,但不用擔心,大部分程式碼都是免費使用的。 - 💰 獲得總資金 290 萬美元。 - 🚀 使用的主要語言是 TypeScript。 他們在 GitHub 上擁有超過 12,500 顆星,發布了 130 多個版本。另外,Infiscial CLI 的安裝次數超過 540 萬次,因此非常值得信賴。 https://github.com/Infisical/infisical 明星 Infisical ⭐️ --- 19. [HyperDX](https://github.com/hyperdxio/hyperdx) - 統一會話重播、日誌、指標、追蹤和錯誤的可觀察平台。 ------------------------------------------------------------------------------- ![超DX](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6r38lckflg0wmwlq6i4.png) HyperDX 透過將日誌、指標、追蹤、異常和會話重播集中並關聯到一處,幫助工程師快速找出生產中斷的原因。 Datadog 和 New Relic 的開源且開發人員友善的替代方案。閱讀[文件](https://www.hyperdx.io/docs)。 ![超DX](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9g83r7408vr2oawc8s8p.png) - 💰 獲得總計 50 萬美元的資金。 - 🚀 使用的主要語言是 TypeScript。 HyperDX 在 GitHub 上擁有超過 6k 顆星。 https://github.com/hyperdxio/hyperdx 明星 HyperDX ⭐️ --- 20.[亮點](https://github.com/highlight/highlight)-全端監控平台。 ------------------------------------------------------- ![強調](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3p2ecjnrwbtskuqrkjv7.png) highlight.io 是為下一代開發人員(像您一樣!)提供的監控工具。與現有的古老、過時的工具不同,它們的目標是建立一個有凝聚力的、現代的、功能齊全的監控解決方案。 ![支援框架](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/afaoao8954hobs7d2igw.png) - 💰 獲得總資金 850 萬美元。 - 🚀 使用的主要語言是 TypeScript。 Highlight 在 GitHub 上有超過 7k 顆星。 https://github.com/highlight/highlight 星標亮點 ⭐️ --- 21. [Panora](https://github.com/panoratech/Panora) - 在幾分鐘內將整合目錄新增至您的 SaaS 產品。 ----------------------------------------------------------------------------- ![全景](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzhhyl8t0xy2ueln8d4t.png) Panora 協助您將產品置於客戶日常工作流程的核心。 您的客戶希望他們的所有工具都能很好地協同工作。 Panora 避免您的團隊花費數百小時來建立和維護集成,而不是核心產品。 查看[快速入門指南](https://docs.panora.dev/quick-start)。 - 💰 獲得了 50 萬美元的總資金(可能更多)。 - 🚀 使用的主要語言是 TypeScript。 Panora 在 GitHub 上擁有 300 多個 star,並且處於非常早期的階段。 https://github.com/panoratech/Panora 明星 Panora ⭐️ --- 22. [Fleet](https://github.com/fleetdm/fleet) - IT、安全和基礎設施團隊的平台。 ---------------------------------------------------------------- ![艦隊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d47vi9uyn2hq3kx6s2h6.png) 針對擁有數千台電腦的 IT 和安全團隊的開源平台。專為 API、GitOps、webhooks、YAML 和人類而設計。 Fastly 和 Gusto 等組織使用 Fleet 進行漏洞報告、偵測工程、裝置管理 (MDM)、裝置運作狀況監控、基於狀態的存取控制、管理未使用的軟體授權等。 ![艦隊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vfn75mjk5rfhb4bfjwp8.png) - 💰 獲得總資金 2500 萬美元。 - 🚀 使用的主要語言是 Go。 Fleet 在 GitHub 上擁有 2,500 顆星。 https://github.com/fleetdm/fleet 星際艦隊 ⭐️ --- 23. [Ballerine](https://github.com/ballerine-io/ballerine) - 用於風險決策的基礎設施和資料編排平台。 -------------------------------------------------------------------------------- ![舞者](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnnrhyf6oj3dexdeyyuf.png) Ballerine 是一種開源風險管理基礎設施,可協助全球支付公司、市場和金融科技公司在整個客戶生命週期中自動為商家、賣家和使用者做出決策。 從開戶(KYC、KYB)、承銷和交易監控,使用靈活的規則和工作流程引擎、第 3 方插件系統、手動審核後台以及文件和資訊收集前端流程。 - 💰 獲得總資金 550 萬美元。 - 🚀 使用的主要語言是 TypeScript。 Ballerine 在 GitHub 上擁有 2000 顆星,發布了 700 多個版本。 https://github.com/ballerine-io/ballerine 明星芭蕾舞者 ⭐️ --- 24. [Tooljet](https://github.com/ToolJet/ToolJet) - 用於建立業務應用程式的低程式碼平台。 ---------------------------------------------------------------------- ![工具噴射器](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xhipvjl2wnthjccgrpij.png) 我們都建立前端,但它通常非常複雜,並且涉及許多因素。這樣可以省去很多麻煩。 ToolJet 是一個開源低程式碼框架,可以用最少的工程工作來建置和部署內部工具。 ToolJet 的拖放式前端建構器可讓您在幾分鐘內建立複雜的響應式前端。 您可以整合各種資料來源,包括PostgreSQL、MongoDB、Elasticsearch等資料庫;具有 OpenAPI 規範和 OAuth2 支援的 API 端點; SaaS 工具,例如 Stripe、Slack、Google Sheets、Airtable 和 Notion;以及 S3、GCS 和 Minio 等物件儲存服務來取得和寫入資料。一切 :) 這就是 Tooljet 的工作原理。 ![工具噴射器](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6vv09z7ioma1ce2ttei.png) 您可以在 ToolJet 中開發多步驟工作流程以自動化業務流程。除了建置和自動化工作流程之外,ToolJet 還可以在您的應用程式中輕鬆整合這些工作流程。 ![工作流程](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eh2vk3kih9fhck6okf67.png) 您可以閱讀[文件](https://docs.tooljet.com/docs/)並查看[操作指南](https://docs.tooljet.com/docs/how-to/use-url-params-on-load)。 - 💰 獲得總融資 620 萬美元(GitHub 是其中一名投資者)。 - 🚀 使用的主要語言是 JavaScript。 Tooljet 在 GitHub 上擁有超過 27,800 顆星和 500 多名貢獻者。 https://github.com/ToolJet/ToolJet Star Tooljet ⭐️ --- 25. [Mattermost-](https://github.com/mattermost/mattermost)整個軟體開發生命週期的安全協作。 --------------------------------------------------------------------------- ![最重要的](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/43p8f052h71ryhavrkms.png) Mattermost 是一個開源平台,用於在整個軟體開發生命週期中進行安全協作。 該儲存庫是 Mattermost 平台上核心開發的主要來源;它是用 Go 和 React 編寫的,並作為單一 Linux 二進位與 MySQL 或 PostgreSQL 一起執行。每個月 16 日都會在 MIT 許可下發布新的編譯版本。 - 💰 獲得總資金 7350 萬美元。 - 🚀 使用的主要語言是 TypeScript。 Mattermost 在 GitHub 上擁有超過 28,400 顆星,有 600 多個活躍問題和 900 多個貢獻者。 https://github.com/mattermost/mattermost Star Mattermost ⭐️ --- 我很驚訝這麼多受資助的專案使用 TypeScript 而不是 JavaScript。你是? 如果您知道任何其他資助專案或希望我製作第二部分。 請在評論中告訴我您最喜歡的清單。 祝你有美好的一天!直到下一次。 您可以加入我的開發者和技術作家社區,網址為[dub.sh/opensouls](https://dub.sh/opensouls) 。 關注 Taipy 以了解更多此類內容。 嵌入 https://dev.to/taipy --- 原文出處:https://dev.to/taipy/25-funded-projects-you-can-contribute-in-open-source-40lh

你的 side project 無法賺錢的 5 個原因以及如何避免它們

介紹 -- ![](https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExcjA0MGM0NjN0YjR3aGRicHM3YzUyc254ZmxxNjkxdzlnZWZ0NHRjbCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ljtfkyTD3PIUZaKWRi/giphy.webp) 你好呀!如果您像許多有抱負的企業家(包括我)一樣,您可能已經有不少聰明的想法,但很難將它們轉化為有利可圖的副業專案。你不是一個人。許多副業專案都無法賺錢,了解原因是邁向成功的第一步。因此,讓我們深入探討個人創業家/獨立駭客之旅中的常見陷阱,並學習如何避免它們。 開始這段旅程時,重要的是要記住失敗不是敵人。事實上,這是這個過程的關鍵部分。是的,這是殘酷的事實:沒有人是第一次嘗試就成功的。 擁抱失敗並從中學習可以幫助我們避免在未來犯下同樣的錯誤。所以請繫好安全帶,因為我們即將探討業餘專案失敗的常見原因以及如何解決這些問題。 錯誤#1——沒有嘗試 ---------- ![來自levelsio的推文](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2bcwyxlln68kmzv853oc.png) 這是來自[@levelsio](https://twitter.com/levelsio)的一條推文,他是一位成功的個體企業家,每月收入超過 15 萬美元,這是一個值得一看的好例子。對失敗的恐懼常常阻礙我們踏出第一步。不要讓這種恐懼阻止你!**嘗試但失敗比根本不嘗試好。** 此外,請記住,完全不嘗試意味著您會錯過寶貴的經驗和成長機會。即使您的專案沒有盈利,您獲得的技能和經驗確實是重點。無論是提高您解決問題的能力,請多了解新市場,還是了解其動態,這些技能都對您未來的專案和麵試非常有益。 所以,下次當你有一個業餘專案的想法時,就去做吧!讓你的好奇心和熱情驅動你,不要讓失敗的恐懼阻礙你。一次又一次地失敗並從錯誤中學習——這是成長的最佳方式,如[@levelsio](https://twitter.com/levelsio)所示。 錯誤#2-失敗的創意 ---------- ![](https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExMzZ5ejdzZWFhbHl6anF1NXNtN2ZwdXJvbmE5NDBxdjZjY2J1Mm84cSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/PbzwVUojP4d8RcRgK0/giphy.webp) 你有這個想法。但它是透過有效的腦力激盪和解決問題形成的嗎?業餘專案的一個常見陷阱是倉促的構思過程。徹底的腦力激盪過程對於確保您的想法的可行性至關重要。 試著用你自己的視角來過濾掉那些與你沒有太多共同點的想法。問題對你來說越是原生,解決方案看起來就越明顯可行。 - 驗證你的想法:僅僅認為它是好的還不夠。您至少需要保證它有市場。進行調查,詢問您信任的人,並收集盡可能多的初始資料。 - 確保你的想法能夠解決問題:一個好的商業想法是能夠填補市場空白或解決人們遇到的問題的想法。 - 評估您的資源:您是否有技能、時間和金錢將您的想法轉化為業務?不要自欺欺人。永遠記住,你可以做一個 MVP(最小可行產品),但是,如果 MVP 不能為用戶帶來真正的價值,那麼它是不夠的。 想要一個例子嗎?查看對[amicus.work](https://www.amicus.work/)的建立者 Erlis 的[訪談](https://wasp-lang.dev/blog/2023/02/14/amicus-indiehacker-interview)。它準確地表明了接近問題如何使解決方案變得直觀。如果您發現自己陷入困境,您可以快速閱讀另一篇[文章](https://dev.to/llxd/creating-a-more-than-minor-side-project-from-planning-to-release-3be8),或者,如果您希望更深入地了解, [Make Book](https://makebook.io/)或[The Lean Startup](https://www.amazon.com/Lean-Startup-Entrepreneurs-Continuous-Innovation/dp/0307887898)也是很好的參考資料,因為它們提供了寶貴的見解,幫助您避免在創業過程中出現常見錯誤。 錯誤 #3 - 無限建置 ------------ ![](https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExNmoxdm1nN2I4dml0OXNibTg5a2N3bGxhbGprZG10eHR4MmllNzJ0dSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/UAHZijO91QCl2/200.webp) 現在,您的腦海中浮現出技術選擇,您實際上正在考慮學習一種全新的程式語言,只是為了解決這個新問題。來吧,你已經讀過一篇[關於學習的文章](https://dev.to/wasp/the-art-of-self-learning-how-to-teach-yourself-any-programming-concept-5de4)了!沒有什麼可以阻止你! 可是等等!想一想。現在你必須同時處理兩個問題: 1. 學習一門新語言, 2. **並為您的問題建立解決方案。** 將一個奇妙的想法變成一項蓬勃發展的業務已經足夠具有挑戰性了。而且您已經知道許多副專案**在建置階段**都會失敗,那麼為什麼要對自己這樣做呢? 這裡的秘密?創新,但要謹慎! 嘗試那些總是能讓你加速的事情,而不是給你帶來負擔和減慢你的速度的事情。一個例子?已經了解 React 了?嘗試[Wasp](https://wasp-lang.dev/) ,這是一個全端框架,它可以為您處理 Boilerplate(例如 Auth),並使用 AI 生成功能來幫助您更快地建立產品。 當嘗試建立和測試一個想法時,我們不會過度專注於學習新東西,而是**更專注於建立想法本身。**因此,在選擇工具時,請選擇基於您已知的技術並能幫助您快速前進的工具! --- 順便一提: [Wasp](https://wasp-lang.dev/)使本文成為可能,最近,我們發布了 Open SaaS — 一種出色的、100% 免費的開源方式,可用於快速啟動新的 SaaS。一探究竟! https://github.com/wasp-lang/open-saas ⭐️ 使用 Open SaaS 建立您的 SaaS 🙏 [![打開 SaaS 橫幅](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9t2q03c6a86dd4oi1xt.png)](https://opensaas.sh) --- 其他真正常見的錯誤是追求完美,這通常會導致無休止的調整和延誤。請記住,「完成比完美更好」。完成您的專案並將其推向世界至關重要。如果你的專案沒有人看到,那麼它只是一個想法。 錯誤#4 - 從未到達的回饋 -------------- 延誤並不是此階段的唯一障礙。有時,我們過於專注於創造完美的產品,以至於我們忘記了與實際用戶一起驗證它。定期回饋至關重要 - 它可以幫助您做出必要的更改並確保您的產品滿足用戶的需求。 沒有回饋,您永遠不會知道自己是否中了大獎,或者是否正在為無人解決的問題建立解決方案。 ![](https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExM294bHQyaGN3NHVsaWFncW1lNWc3aGIzaG50YWR3c3d2bThxMHdkNyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/4LsN0YwgIsvaU/giphy.webp) 那麼,如何確保獲得必要的回饋呢?首先與一小群用戶測試您的產品。這可以是一群朋友、家人,甚至是一個專門的焦點團體。他們的回饋對於辨識任何問題或需要改進的領域非常有價值。 我們也面臨著收到負面回饋的恐懼,這很常見,這通常會導致產品被拒絕進入市場,直到它「完美」為止。然而,這種方法可能是有害的。儘早發布您的產品至關重要,即使它缺少您計劃加入的一些很酷的功能。用戶的早期回饋可以引導您加入以前沒有想到的功能,但這是實際用戶想要的功能。 請記住,回饋是一份禮物。它可以讓您改進您的產品,使其成為人們不僅使用而且喜歡的東西。所以,不要迴避它,擁抱它! 錯誤#5——羞澀的發布 ----------- 並談論害羞:所以,你已經建立了它,現在怎麼辦?是時候向世界展示它了。然而,請記住,時機就是一切。如果你的發布是羞澀的、計劃不周的,你就不會獲得你需要的用戶(也不會是收入)。 第一步是了解您的受眾並選擇合適的平台。 [Reddit](https://www.reddit.com/)非常適合開源或主要不是由利潤驅動的專案,而[Dev Hunt](https://devhunt.org/) 、 [Product Hunt](https://www.producthunt.com/)和[Hacker News (YC) 則](https://news.ycombinator.com/)非常適合更廣泛的專案。選擇正確的啟動地點可能意味著企業與空無一物之間的差異。 此外,制定策略發布計劃至關重要。儘管有可能發生,但僅發布您的專案並希望獲得最好的結果是不夠的。您需要規劃您的發布,考慮合適的發佈時間、平台的習慣等因素,並調整與目標受眾的溝通。 深思熟慮的啟動計劃不僅可以幫助您吸引更廣泛的受眾,還可以增加專案成功的機會。您應該使用[Screen Studio](https://www.screen.studio/)和[Canva](https://canva.com)等工具來幫助您建立精美的螢幕錄製和宣傳圖像/橫幅。 作為獎勵,這裡有一個啟動計劃範例,可以幫助您入門: - 第一周:準備所有宣傳材料,例如圖像和影片 - 第 2 週:在[Dev Hunt](https://devhunt.org/)上啟動 + 在社群媒體上進行推廣 - 第 3 週:推出[Product Hunt](https://www.producthunt.com/) + [Show HN](https://news.ycombinator.com/show) - 第 4 週及以後:大聲點!繼續在 Reddit、HN 和其他社交媒體平台上進行推廣(不被禁止)。 ![](https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExNmFzZG14azQ1cjJrc25mY3hoNnk1aWI3bHpnNW45MHkxOWJ6ejd6ciZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/P0ZRTYaCmPsJPNd3r0/giphy.webp) 嘿,你在網路上,所以,儘管你可能會得到很好的回饋,但有些用戶只會對你進行人身攻擊。這很正常,所以不要理會那些生氣的人。如果你的想法被一些隨機的 Reddit 用戶消滅,這絕對不是一種很好的感覺,但時不時地,你實際上也會從誠實的用戶那裡得到一些很棒的見解。這並不容易,但試著辨識哪些回饋應該認真對待,哪些回饋應該忽略:) --- 尋找更多? ----- ![](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNWNraHJwazF1cGtxZWI5YmZmaXc1YzZwZms3djJ0eXY4NDhkMGZjZyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/IwAZ6dvvvaTtdI8SD5/giphy.gif) 對更多這樣的內容有興趣嗎?關注我們在[Wasp - DEV Community 的](https://dev.to/wasp)博客,並在 github 上給我們一個星星。這是支持我們的最簡單的方式! https://www.github.com/wasp-lang/wasp ⭐️ GitHub 上的 Star Wasp 🙏 --- 結論 -- 總之,將業餘專案轉變為成功的企業是一個充滿挑戰和勝利的旅程。一路走來,每一步,無論是坎坷或勝利,都是一次寶貴的學習和成長的機會。 每一次失敗都不是終點,而是邁向更大成功的墊腳石,是推動我們前進的教訓。每一次挫折都是重新評估、完善並變得更強大的機會。擁抱這個過程的迭代本質:繼續完善你的想法,堅持不懈地努力改進,最重要的是,永遠不要停止嘗試和學習。 --- 原文出處:https://dev.to/wasp/5-reasons-why-your-side-projects-fail-to-make-money-and-how-to-avoid-them-4l5m

🙅 為什麼我不使用 AI 作為我的副駕駛 🤖

\*\*耶穌,掌管方向盤。 🚗 還有 Github Copilot,使用 IDE。 💻\*\* **[Github 表示](https://github.blog/2023-06-13-survey-reveals-ais-impact-on-the-developer-experience/)**,92% 的美國開發者都在使用 Copilot。 什麼。嚴重地? 什麼時候聽過 92% 的人口使用單一事物? 當然,除非…你說全世界**100%**的人都消耗過一氧化二氫。 *(這條線只有一種變黑的方式。不要去那裡。👀)* 和我一起快速旅行,我將談論: - [我真正擔心的是什麼。](#what-im-actually-worried-about) - [其他經驗豐富的開發人員對此有何看法?](#from-the-experienced-devs-point-of-view) - [也許我什麼都不擔心?](#lets-take-a-step-back-for-a-moment) - [以及我們如何對我們如何使用LLMs負責!](#where-the-heck-does-llmai-fit-in) ### 🔥 當機器在 2024 年佔領世界時 經過谷歌快速搜尋後,似乎大多數開發人員都在使用人工智慧輔助來編寫程式碼。如果我說我根本沒有使用人工智慧來編寫程式碼,**那我就是在撒謊**。當然,我有。我並不住在岩石下。 我發現開發人員對與第三方雲端服務共享程式碼相關資料的想法感到奇怪,這些第三方雲端服務通常沒有 SOC2(或類似的東西)認證,並且充其量只能做出模糊且無法證明的隱私聲明。 Github Copilot(和 Copilot 聊天)、Bito.ai 以及 VS Code 市場上的其他幾個 AI 程式碼擴充的安裝量已超過 3000 萬。瘋狂的! 🤯 然後是我。**我還沒有將人工智慧輔助**納入我的常規程式碼工作流程中。當然,我有幾次在 GPT 的幫助下編寫了一些樣板檔案。但那些時候是個例外。像 Github Copilot 這樣的東西,或任何類型的程式碼審查、程式碼產生工具、PR 建立或提交協助,都不屬於我的 IDE 或 CLI 流程的一部分。 也許它會隨著時間而改變。我們拭目以待。 > ## “但為什麼?” ![但為什麼](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpc1fc4t5a10j0i5r3wj.gif) ### 😟我真正擔心的是 答案很簡單。 👇 #### 1.我擔心我的程式設計技能會生疏 我擔心如果我太習慣人工智慧的幫助,我編寫和閱讀程式碼的方式將會受到影響。 - 我擔心我會開始**忽略**程式碼中的缺陷,否則我可以發現這些缺陷。 - 我將開始認為人工智慧產生的程式碼是**理所當然的**。 - 尋找 API、內建方法或其他文件將開始變得像一件**苦差事**。 我擔心……我會開始滑倒。 #### 2. 我不願意與第三方服務分享我的所有程式碼 公司可以非常聰明地從你提供的資料中推斷出一些事情。有時他們會知道[你的家人不知道的](https://www.forbes.com/sites/kashmirhill/2012/02/16/how-target-figured-out-a-teen-girl-was-pregnant-before-her-father-did/)事。 敏感的業務邏輯可能會洩漏給第三方服務,最終可能會被用來做出我不滿意的推論,或者只是…直接洩漏?我的意思是,軟體總是被駭客攻擊。 我認為我很合理地認為我不想以不受限制的方式向第三方公司公開像程式碼這樣敏感的東西。即使那家公司是微軟,[因為即使他們也搞砸了](https://www.wired.com/story/total-recall-windows-recall-ai/)。 ### 👀 從經驗豐富的開發人員的角度來看 這也不是我獨有的想法! #### 1. 經驗豐富的開發人員往往**不想依賴**「拐杖」來寫程式碼。 我甚至很高興與不想在 IDE 上使用彩色主題的高級開發人員合作,因為他們認為這會損害他們掃描、閱讀或偵錯程式碼的能力! (這對我來說也有點太多了) 畢竟,「程式設計技能」**不僅僅是編寫程式碼**。 #### 2. 老開發者看過各種**軟體被駭**、資料外洩等。 我的意思是,十多年來, [haveibeenpwned.com](https://haveibeenpwned.com/)每年都會向您發送有關您的憑證、電子郵件和其他資料外洩的電子郵件…很多時候來自[價值數十億](https://en.wikipedia.org/wiki/2017_Equifax_data_breach)[美元的](https://www.news18.com/india/indias-biggest-data-leak-so-far-covid-19-test-info-of-81-5cr-citizens-with-icmr-up-for-sale-exclusive-8637743.html)[公司](https://www.nytimes.com/2017/10/03/technology/yahoo-hack-3-billion-users.html)… 當你無數次聽到**「當你不為產品付費時,你就是產品」** ,然後又得到另一家將資料出售給第三方的公司的支持... 是啊……會很累。 只需斷開盡可能多的電線即可輕鬆回到石器時代。 > ![老馬特達蒙](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03pmbpqix6e199ewey5t.gif) > “老開發人員”?我是……我變老了嗎? > 不,我才 22 歲,現在已經是 2016 年了……對吧?正確的? **順便說一句,標題中問題的答案是👆這個。**恭喜!貼文結束了!轉到下一個… Buuuuut…如果你想繼續閱讀… ![喬伊還有更多](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jk0ywd7yjqukeokd0t2d.gif) ### 🚶 讓我們退後一步...... #### 我認為我的擔心可能被誇大了。 > *現在讓我們把整個資料隱私的角度放在一邊,因為這本身就是一個我非常熱衷的另一個主題。* 我個人沒有足夠的資料來經驗說使用人工智慧輔助會帶來我擔心的厄運……它會將我從今天的樣子降級為[SDE1](https://dev.to/middleware/going-from-sde1-to-sde2-and-beyond-what-it-actually-takes-1cld) 。 但我已經看到了模式。 - 我見過人工智慧生成的低於標準品質的程式碼經過程式碼審查並最終出現在`main`分支上。 - 我見過一些函式庫函數在沒有正確理解存在什麼或存在什麼替代方案的情況下被使用,只是因為LLMs產生了它。 - 我什至見過為解決某個問題而生成的程式碼,對於該問題,程式碼庫中已經存在一個實用程式函數,但沒有使用它,因為知道這個實用程式的存在比要求GPT 為您生成它要多得多的工作。 ### 💎 ~~鑽石是~~ 糟糕的程式碼是永遠的 **“等一下……我以前看過這部電影!”** ![似曾相識](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvun4635neb2dflv5yto.gif) - LLM 是一個相當新的事物…但是💩程式碼是**永恆的!** - 每一個。單身的。開發。曾經。在沒有完全**理解**或尋找替代方案的情況下使用了函式庫函數。你和我都對此有罪。 (什麼?您認為`Array.prototype.sort`是對任何內容進行排序的最佳方式?在大多數情況下它就足夠了!) - 一段邏輯總是被重新發明(重新複製貼上)!只是之前它來自**StackOverflow** ,現在它來自 ChatGPT 。 ### 🤷 那麼,有什麼好大驚小怪的呢? > “使用 ChatGPT 會讓我成為一個糟糕的程式設計師嗎?” 我想不是。 重點是您只需要關心您建立的內容。 為您所**建造的**東西感到**自豪**。 ### 🤖 LLM/AI 到底適合什麼? **LLM 本身並不是邪惡的。** 事實上,如果負責任地使用它們,它們會非常有用: - **品質程式碼:**LLMs可能會處理不太勤奮的開發人員不會考慮的邊緣情況。 - **綜合測試:**LLMs可能會編寫比某些開發人員編寫的測試更全面的測試。 - **綜合類型:**它甚至可能比普通開發人員自己編寫的類型或可能具有編寫技能的類型更「完整」地編寫類型。 然而,開發人員有責任確保程式碼輸出受到保護和良好監控。一個不在乎的人在歷史上的任何時候都會做得很糟糕。LLMs的存在並沒有改變這一點。 ### 😎 真正給予 a\*ck 的藝術 有很多開發者對此並不關心。 但你不是這樣的開發者。**你確實關心。** 否則你就不會在這裡開發並學習人們的經驗。 我最近寫了一篇關於新開發人員在職涯中應該關心什麼成長的文章。它不僅僅是程式碼。 https://dev.to/middleware/going-from-sde1-to-sde2-and-beyond-what-it-actually-takes-1cld **也許我會在 VSCode 中引入一些 AI。** 我認為這只是時間問題,而不是**是否有問題**。 更重要的是……只要我關心確保我的程式輸出**可讀、高效能、高品質且易於審查**,我想我會沒事的,你也一樣。 --- ### 👇 PS 如果您想要一個我非常關心的範例,並且具有出色的程式碼 💪 和…不太出色的程式碼 🤣,請查看我們的**開源**儲存庫! 它可以讓您了解交付程式碼需要多長時間、PR 陷入審查循環的次數以及您的團隊交付程式碼的整體情況。 https://github.com/middlewarehq/middleware --- 原文出處:https://dev.to/middleware/why-i-dont-use-ai-as-my-copilot-47k3

如何在行動裝置上測試本地網站

在建立網站時,開發人員通常需要測試他們的網站是否響應靈敏、經過優化並且在行動裝置上運作良好。如果他們不知道一種簡單且正確的方法來進行測試,那麼測試可能會令人沮喪。 在這篇文章中,我將向您展示如何透過三個簡單的步驟在行動裝置上測試本地網站。儘管瀏覽器開發工具可以提供幫助,但有時您可能需要更好的視覺化、清晰度和與專案的觸控互動。在這種情況下,在實際手機上進行測試可能比使用瀏覽器的行動螢幕更好。 要在手機上查看本地網站的即時預覽,請確保您的手機和桌面連接到相同 WiFi 網路。如果尚未安裝,請安裝[VS Code](https://code.visualstudio.com/)編輯器和[Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer)擴充功能。 在電話上測試本地網站的步驟 ------------- 下載 VS Code 編輯器及其 Liver Server 擴充功能後,現在請按照給定的 3 個步驟逐行查看手機上的本機專案: ### 1. 執行實時伺服器 首先,在 VS Code 中開啟專案資料夾。然後,點擊右下角的「上線」按鈕。這將為您的專案啟動本機開發伺服器,通常在連接埠`5500`上執行。 您的專案現在應該在預設的 Web 瀏覽器中執行。記下連接埠號碼(5500 或其他數字,如果不同)。 ![執行實時伺服器](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5bxampc1npsnupyvfwrf.jpg) ### 2. 尋找您的本地 IPv4 位址 接下來,您需要本機 IPv4 位址。開啟命令提示字元 (CMD),鍵入 ipconfig,然後按 Enter。在「無線 LAN 適配器 Wi-Fi」部分下尋找您的 IPv4 位址。它看起來像`192.168.1.68` 。 請記住,如果新設備連接或斷開與您的 WiFi 網路的連接,您的本地 IP 位址可能會發生變化。 ![尋找您的本機 IPv4 位址](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ggaldbbpfdf26cbbqebk.jpg) ### 3. 在手機上查看您的專案 開啟手機上的瀏覽器並輸入您的 IPv4 位址,然後輸入連接埠號碼。 URL 應如下所示: `192.168.1.68:5500` 。 如果您的主 HTML 檔案未命名為 index.html,則需要在 URL 中包含檔案名,如下所示: `192.168.1.68:5500/filename.html` 。 ![在手機上查看您的專案](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qoy2k744fqngq9bsz35.jpg) 現在您應該在手機上看到專案的即時預覽。您在桌面上的 VS Code 中所做的任何更改都會立即反映在您的手機上,無需手動刷新。 常見錯誤故障排除 -------- 如果您遇到「無法存取網站」或類似內容的錯誤,請嘗試以下故障排除步驟: - **仔細檢查 IPv4 位址和連接埠號碼:**確保您在手機瀏覽器中輸入了正確的 IPv4 位址和連接埠號碼。 - **檢查網路連線:**確保您的手機和桌面連接到相同 WiFi 網路。 - **檢查檔案路徑:**如果您的主 HTML 檔案不是`index.html` ,請確保 URL 中包含正確的檔案路徑。 - **防火牆設定:**您電腦的防火牆可能阻止連線。調整設定以允許 Live Server 使用的連接埠號碼上的流量。 結論 -- 在這篇文章中,您學習如何在手機上查看專案的即時預覽。此方法適用於使用[HTML、CSS](https://www.codingnepalweb.com/category/html-and-css/)和[JavaScript](https://www.codingnepalweb.com/category/javascript/)以及其他框架專案建立的靜態專案。 如果您想提高編碼的準確性、速度和效能,請查看我的部落格文章《[面向 Web 開發人員的十大有用 VS 程式碼擴充》](https://www.codingnepalweb.com/top-vs-code-extensions-for-web-developers/) 。 如果您發現本指南有幫助,請與其他人分享! --- 原文出處:https://dev.to/codingnepal/how-to-test-local-website-on-mobile-devices-2p69

對 console.log 說不!

您在開發過程中是否總是在專案中使用`console.log` ? 儘管我們將繼續使用`console.log` ,但還有其他替代方案可以讓您的開發更加有趣和有效率。 console.dir() --------- 用於陣列和物件的分層清單。 ``` console.dir(["apples", "oranges", "bananas"]); ``` ![console.dir 範例](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ksvxyavsmejk1eb73u5.png) console.table() ------- 用於物件和陣列的行和列列表。 ``` console.table(["apples", "oranges", "bananas"]); ``` ![console.table 陣列範例](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zwzq9uf4t643lorq1qbu.png) ``` console.table({"a": 1, "b": 2, "c": 3}); ``` ![console.table 物件範例](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r45pzliuaaxbx4preo4k.png) console.group() ----------- ``` console.log("This is the top outer level"); console.group("Task 1"); console.log("Task activity 1"); console.log("Task activity 2"); console.groupEnd(); console.log("Back to the top outer level"); ``` console.time() 和 console.timeEnd() ---------------------------------- ``` try { console.time("recording..."); await someAsyncTask(); } catch (error) { // handle error } finally { console.timeEnd("completed"); } ``` console.clear() ----------- 這將清除console。 我希望這可以幫到你! 🚀 --- 原文出處:https://dev.to/alishgiri/say-no-to-consolelog-556n

2024 年您需要了解的免費 API

API(應用程式介面)是開發人員必不可少的工具,使他們能夠將第三方服務整合到他們的應用程式中。以下是 2024 年跨不同類別的免費 API 的詳細列表,以及每個 API 的網站連結、描述和範例程式碼。 遊戲 API ------ ### Steam 社群 API - **網址**: [steamcommunity.com/dev](https://steamcommunity.com/dev) - **描述**:Steamworks Web API 提供了各種 Steam 功能的接口,例如使用者驗證、庫存管理和遊戲資料。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const steamApiKey = 'YOUR_STEAM_API_KEY'; const steamId = 'STEAM_USER_ID'; const url = `http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=${steamApiKey}&steamids=${steamId}`; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### Riot 遊戲 API - **網址**: [developer.riotgames.com](https://developer.riotgames.com) - **描述**:存取《英雄聯盟》、《雲頂之弈》、《Valorant》等遊戲的資料。提供比賽、排名、冠軍和其他遊戲相關統計資料。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const riotApiKey = 'YOUR_RIOT_API_KEY'; const summonerName = 'SUMMONER_NAME'; const url = `https://na1.api.riotgames.com/lol/summoner/v4/summoners/by-name/${summonerName}?api_key=${riotApiKey}`; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 語言API ----- ### 邪惡侮辱生成器 API - **網址**: [evilinsult.com/api](https://evilinsult.com/api) - **描述**:出於娛樂或測試目的,以各種語言產生隨機侮辱。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://evilinsult.com/generate_insult.php?lang=en&type=json'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 趣味翻譯 API - **網址**: [funtranslations.com/api](https://funtranslations.com/api) - **描述**:將文字翻譯成各種有趣的語言,如尤達語言、莎士比亞語言、小小兵語言等等。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const text = 'Hello, world!'; const url = `https://api.funtranslations.com/translate/yoda.json?text=${encodeURIComponent(text)}`; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 音樂 API ------ ### Spotify 網路 API - **網址**: [developer.spotify.com/documentation/web-api](https://developer.spotify.com/documentation/web-api) - **描述**:存取音樂資料,例如專輯、藝術家、播放清單和用戶資料。控制 Spotify 播放等。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const accessToken = 'YOUR_SPOTIFY_ACCESS_TOKEN'; const url = 'https://api.spotify.com/v1/me/player/recently-played'; fetch(url, { headers: { 'Authorization': `Bearer ${accessToken}` } }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 安全API ----- ### 我被偷了嗎 API - **網址**: [haveibeenpwned.com/API/v2](https://haveibeenpwned.com/API/v2) - **描述**:檢查您的電子郵件或使用者名稱是否屬於資料外洩的一部分。提供有關違規、貼上和密碼洩露的資料。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const email = '[email protected]'; const url = `https://haveibeenpwned.com/api/v2/breachedaccount/${email}`; fetch(url, { headers: { 'User-Agent': 'Node.js' } }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 首丹API - **網址**: [developer.shodan.io](https://developer.shodan.io) - **描述**:Shodan 是一個針對網路連線裝置的搜尋引擎。它提供全球各種伺服器、設備和系統的資料。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const shodanApiKey = 'YOUR_SHODAN_API_KEY'; const query = 'apache'; const url = `https://api.shodan.io/shodan/host/search?key=${shodanApiKey}&query=${query}`; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 科學與數學 API --------- ### 美國太空總署火災 - **網址**: [api.nasa.gov](https://api.nasa.gov) - **描述**:存取 NASA 資料集中的資料,包括天文照片、行星資料等。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const nasaApiKey = 'YOUR_NASA_API_KEY'; const url = `https://api.nasa.gov/planetary/apod?api_key=${nasaApiKey}`; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### Wolfram Alpha API - **網址**: [products.wolframalpha.com/api](https://products.wolframalpha.com/api) - **描述**:提供對 Wolfram Alpha 的大量計算知識的存取,包括數學計算、資料分析等。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const wolframAppId = 'YOUR_WOLFRAM_APP_ID'; const query = 'integrate x^2'; const url = `http://api.wolframalpha.com/v2/query?input=${encodeURIComponent(query)}&appid=${wolframAppId}&output=json`; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 開放科學框架 API - **網址**: [developer.osf.io](https://developer.osf.io) - **描述**:從開放科學框架存取研究資料、專案管理工具和其他科學資源。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://api.osf.io/v2/nodes/'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 體育 API ------ ### NBA應用程式介面 - **網址**: [any-api.com/nba\_com/nba\_com/docs/API\_Description](https://any-api.com/nba_com/nba_com/docs/API_Description) - **描述**:存取 NBA 球隊、球員和比賽的資料。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://api-nba-v1.p.rapidapi.com/teams/league/standard'; const options = { method: 'GET', headers: { 'X-RapidAPI-Key': 'YOUR_RAPIDAPI_KEY', 'X-RapidAPI-Host': 'api-nba-v1.p.rapidapi.com' } }; fetch(url, options) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 網路應用 API -------- ### Discord API - **網址**: [discord.com/developers/docs/intro](https://discord.com/developers/docs/intro) - **描述**:將您的應用程式與 Discord 集成,允許用戶身份驗證、訊息傳遞等。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const discordToken = 'YOUR_DISCORD_BOT_TOKEN'; const url = 'https://discord.com/api/users/@me'; fetch(url, { headers: { 'Authorization': `Bot ${discordToken}` } }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### Slack API - **網址**: [api.slack.com](https://api.slack.com) - **描述**:存取 Slack 功能,例如訊息傳遞、使用者資料和工作區管理。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const slackToken = 'YOUR_SLACK_API_TOKEN'; const url = 'https://slack.com/api/conversations.list'; fetch(url, { headers: { 'Authorization': `Bearer ${slackToken}` } }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 產品和事物 API --------- ### 汽車查詢API - **網址**: [carqueryapi.com](https://carqueryapi.com) - **描述**:存取汽車資料,包括 品牌、型號和年份資訊。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://www.carqueryapi.com/api/0.3/?cmd=getMakes'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### Yelp API - **網址**: [yelp.com/developers](https://yelp.com/developers) - **描述**:存取本地企業的資料,包括評論、評級和企業詳細資訊。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const yelpApiKey = 'YOUR_YELP_API_KEY'; const url = 'https://api.yelp.com/v3/businesses/search?location=San Francisco'; fetch(url, { headers: { 'Authorization': `Bearer ${yelpApiKey}` } }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 健康API ----- ### 醫療保健.gov API - **網址**: [healthcare.gov/developers](https://healthcare.gov/developers) - **描述**:存取醫療保健計劃、提供者目錄和其他健康相關資訊的資料。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://data.healthcare.gov/resource/xyz123.json'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 政府和地理 API --------- ### 程式碼.gov API - **網址**: [code.gov](https://code.gov) - **描述**:存取聯邦政府軟體專案的資料,包括程式碼儲存庫和專案詳細資訊。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://api.code.gov/projects'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 資料政府API - **網址**: [data.gov/developers/apis](https://data.gov/developers/apis) - **描述**:存取美國政府提供的各種資料集,包括天氣、教育和健康資料。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://api.data.gov/ed/collegescorecard/v1/schools.json?api_key=YOUR_DATA_GOV_API_KEY'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 資料.europa.eu API - **網址**: [data.europa.eu/en](https://data.europa.eu/en) - **描述**:存取歐盟機構和團體的開放資料。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://data.europa.eu/api/hub/search/datasets'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 傳輸定位API - **網址**: [rapidapi.com/transloc/api/openapi-1-2/details](https://rapidapi.com/transloc/api/openapi-1-2/details) - **描述**:存取即時公共交通資料,包括到達預測、車輛位置等。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const translocApiKey = 'YOUR_TRANSLOC_API_KEY'; const url = 'https://transloc-api-1-2.p.rapidapi.com/agencies.json'; fetch(url, { headers: { 'X-RapidAPI-Key': translocApiKey, 'X-RapidAPI-Host': 'transloc-api-1-2.p.rapidapi.com' } }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 食品原料藥 ----- ### 開放食品事實 API - **網址**: [world.openfoodfacts.org/data](https://world.openfoodfacts.org/data) - **描述**:存取全球食品資料,包括成分、營養成分和過敏原資訊。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://world.openfoodfacts.org/api/v0/product/737628064502.json'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 塔克花式 API - **網址**: [github.com/evz/tacofancy-api](https://github.com/evz/tacofancy-api) - **描述**:存取玉米捲食譜資料,包括成分和製備方法。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'http://taco-randomizer.herokuapp.com/random/'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 開源專案 API -------- ### 圖書館.io API - **網址**: [libraries.io/api](https://libraries.io/api) - **描述**:存取開源專案的資料,包括相依性資訊、版本歷史記錄等。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const librariesApiKey = 'YOUR_LIBRARIES_IO_API_KEY'; const url = `https://libraries.io/api/platforms?api_key=${librariesApiKey}`; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 電影和漫畫 API --------- ### 查克諾里斯笑話 API - **網址**: [api.chucknorris.io](https://api.chucknorris.io) - **描述**:參觀查克諾里斯笑話集。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://api.chucknorris.io/jokes/random'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 最終空間 API - **網址**: [finalspaceapi.com](https://finalspaceapi.com) - **描述**:存取《最終太空》電視節目的資料,包括角色、劇集等。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://finalspaceapi.com/api/v0/character'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 木津API - **網址**: [kitsu.docs.apiary.io](https://kitsu.docs.apiary.io) - **描述**:存取動漫和漫畫的資料,包括系列資訊、評論和用戶評分。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://kitsu.io/api/edge/anime'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 漫威API - **網址**: [developer.marvel.com](https://developer.marvel.com) - **描述**:存取有關 Marvel 漫畫、角色和創作者的資料。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const marvelPublicKey = 'YOUR_MARVEL_PUBLIC_KEY'; const marvelPrivateKey = 'YOUR_MARVEL_PRIVATE_KEY'; const ts = new Date().getTime(); const hash = require('crypto').createHash('md5').update(ts + marvelPrivateKey + marvelPublicKey).digest('hex'); const url = `https://gateway.marvel.com/v1/public/characters?ts=${ts}&apikey=${marvelPublicKey}&hash=${hash}`; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 戳API - **網址**: [pokeapi.co](https://pokeapi.co) - **描述**:存取神奇寶貝的資料,包括物種、能力和遊戲資訊。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://pokeapi.co/api/v2/pokemon/ditto'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 瑞克和莫蒂 API - **網址**: [rickandmortyapi.com](https://rickandmortyapi.com) - **描述**:存取瑞克和莫蒂電視節目的資料,包括角色、劇集和地點。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://rickandmortyapi.com/api/character'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 辛普森一家行情 API - **網址**: [thesimpsonsquoteapi.glitch.me](https://thesimpsonsquoteapi.glitch.me) - **描述**:造訪《辛普森家庭》電視節目中的台詞集。 #### 樣本 程式碼 ``` const fetch = require('node-fetch'); const url = 'https://thesimpsonsquoteapi.glitch.me/quotes'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 星際大戰 API - **網站**: [swapi.tech](https://swapi.tech) - **描述**:存取星際大戰宇宙的資料,包括電影、角色、星際飛船和行星。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const url = 'https://swapi.tech/api/people/1'; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### 超級英雄API - **網址**: [superheroapi.com](https://superheroapi.com) - **描述**:存取各種超級英雄的資料,包括他們的力量、傳記和圖像。 #### 範例程式碼 ``` const fetch = require('node-fetch'); const superheroApiKey = 'YOUR_SUPERHERO_API_KEY'; const url = `https://superheroapi.com/api/${superheroApiKey}/1`; fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` 結論 -- 這份 2024 年免費 API 的完整清單涵蓋了廣泛的類別,為開發人員提供了大量機會,透過強大且多樣化的功能來增強其應用程式。從遊戲和音樂到科學和政府資料,這些 API 為建立創新且引人入勝的專案提供了寶貴的資源。 請隨意探索這些 API 並將它們整合到您的專案中,以解鎖新的可能性和功能。快樂編碼! --- 原文出處:https://dev.to/dk119819/free-apis-you-need-to-know-about-in-2024-2ieg

讓我們練習在 React 中編寫乾淨、可重複使用的元件

🔑 關鍵概念 ------ **什麼是可重複使用的 React 元件?**將它們視為建置塊。 它們是您可以在網站的不同部分使用的程式碼片段,以節省時間。它們可以是從簡單按鈕到複雜表單的任何內容。 ### **為什麼要使用可重複使用的元件?** 它們可以輕鬆加入新功能並提高程式碼的可擴展性。另外,您可以在未來的專案中使用它們而無需重寫。 --- 🧩 如何寫出乾淨、可重複使用的 React 元件 ------------------------ 兩個關鍵點: **1. 避免副作用:**不要在元件中直接包含與外部資料互動的邏輯(例如 API 呼叫)。相反,將此邏輯作為`props`傳遞。 簡單但不可重複使用的按鈕範例: ``` const Button = () => { return ( <button>Click Me</button> ); } ``` 該按鈕缺乏靈活性,因為文字是硬編碼的。 **2. 使用 Props:** Props 是傳遞給元件以對其進行自訂的參數。 更好的按鈕範例: ``` const Button = ({ color, label }) => { return ( <button style={{ backgroundColor: color }}>{label}</button> ); } ``` 此按鈕可以有不同的顏色和標籤,使其更易於重複使用。 ### **挑戰:** 考慮如何在不同情況下使用您的元件,並將其設計得靈活。 --- 🍃 可重複使用 React 元件的範例 ------------------- **1. 按鈕:**自訂不同樣式和功能的按鈕。 ``` const Button = ({ color, label, onClick }) => { return ( <button style={{ backgroundColor: color }} onClick={onClick}> {label} </button> ); }; // Using the Button component <Button color="blue" label="Click Here" onClick={() => console.log("Button clicked!")} /> ``` **2. 導覽列:**整個網站的一致導覽。 ``` const Navbar = ({ isLoggedIn }) => { return ( <div className="navbar"> <a href="/">Home</a> <a href="/about">About</a> <a href="/contact">Contact</a> {isLoggedIn ? <a href="/profile">Profile</a> : <a href="/login">Login</a>} </div> ); }; // Using the Navbar component <Navbar isLoggedIn={true} /> ``` **3. 為什麼要避免在元件中呼叫 API** 在元件中包含 API 呼叫等副作用會降低可重複使用性。將副作用作為 prop 傳遞: ``` const SaveButton = ({ onClick, label }) => { return ( <button onClick={onClick}> {label} </button> ); }; // Using SaveButton <SaveButton onClick={saveUser} label="Save User" /> <SaveButton onClick={saveProject} label="Save Project" /> ``` --- 在沒有適當可視化的情況下建立元件可能會讓人不知所措。對於設計而言,Figma 是開發人員用來建立網頁設計元件和原型的絕佳工具。它因其簡潔的用戶介面和協作功能而廣受歡迎。您可以[在這裡免費註冊](https://psxid.figma.com/0s98tq)。 ![菲格瑪](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/io4stx0ue62guwclfksb.png) --- 👏 結論 ---- 恭喜!您已經學習如何建立乾淨、可重複使用的 React 元件。它們是穩健 React 開發的基礎。您練習得越多,您就越能在專案中更好地使用它們。 如果你喜歡這個,請關注我[𝕏](https://twitter.com/shahancd)以獲取更多前端開發技巧。 **閱讀更多:**[前端開發的未來](https://dev.to/codewithshahan/the-future-of-frontend-development-1amd) --- 原文出處:https://dev.to/codewithshahan/lets-practice-clean-reusable-components-in-react-5flj

掌握整潔程式碼:開發人員的基本實踐

乾淨的程式碼是每個成功的軟體專案的基石。作為開發人員,編寫乾淨、可維護的程式碼的能力對於應用程式的效率和壽命至關重要。在本文中,我們將深入研究 JavaScript 中好的和壞的編碼實踐的十個範例,強調編寫乾淨程式碼並提供可操作的見解以幫助您提高開發技能的重要性。 例子 -- - 描述性變數名稱: ``` // Good: const totalPrice = calculateTotalPrice(quantity, unitPrice); ``` ``` // Bad: const t = calcPrice(q, uP); ``` 在一個很好的例子中,變數名稱具有描述性並清楚地表達了它們的目的,從而增強了程式碼的可讀性。相反,糟糕的範例使用神秘的縮寫,使其他人難以理解程式碼的意圖。 - 一致的格式: ``` // Good: function greet(name) { return `Hello, ${name}!`; } ``` ``` // Bad: function greet(name){ return `Hello, ${name}!` } ``` 一致的格式提高了程式碼的可讀性和可維護性。在一個很好的例子中,採用了適當的縮排和間距,並增強了程式碼結構。相反,壞例子缺乏一致性,使得程式碼更難遵循。 - 避免魔法數字: ``` // Good: const TAX_RATE = 0.1; const totalPrice = subtotal + (subtotal * TAX_RATE); ``` ``` // Bad: const totalPrice = subtotal + (subtotal * 0.1); ``` 幻數掩蓋了值的含義,並使程式碼更難維護。在很好的例子中,常數用於表示幻數,提高了程式碼的清晰度和可維護性。 - 單一責任原則: ``` // Good: function calculateTotalPrice(quantity, unitPrice) { return quantity * unitPrice; } function formatPrice(price) { return `$${price.toFixed(2)}`; } ``` ``` // Bad: function calculateAndFormatTotalPrice(quantity, unitPrice) { const totalPrice = quantity * unitPrice; return `$${totalPrice.toFixed(2)}`; } ``` 函數應該有單一的責任來提高程式碼的可重複使用性和可維護性。在這個很好的例子中,每個函數都執行特定的任務,並遵循單一職責原則。相反,壞例子將多個職責組合到一個函數中,違反了這個原則。 - 錯誤處理: ``` // Good: function fetchData(url) { return fetch(url) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .catch(error => { console.error('Error fetching data:', error); throw error; }); } ``` ``` // Bad: function fetchData(url) { return fetch(url) .then(response => response.json()) .catch(error => console.error(error)); } ``` 正確的錯誤處理可以提高程式碼的穩健性,並有助於更有效地辨識和解決問題。在好的範例中,錯誤得到了妥善處理,為開發人員提供了有意義的回饋。相反,壞範例缺乏全面的錯誤處理,可能導致靜默故障。 - 評論和文件: ``` // Good: // Calculate the total price based on quantity and unit price function calculateTotalPrice(quantity, unitPrice) { return quantity * unitPrice; } ``` ``` // Bad: function calculateTotalPrice(quantity, unitPrice) { // calculate total price return quantity * unitPrice; } ``` 註釋和文件增強了程式碼的可理解性並促進了開發人員之間的協作。在一個很好的範例中,清晰的註解描述了函數的用途,有助於程式碼理解。相反,壞例子提供的模糊評論幾乎沒有什麼價值。 - 適當的模組化: ``` // Good: export function add(a, b) { return a + b; } export function subtract(a, b) { return a - b; } ``` ``` // Bad: function add(a, b) { return a + b; } function subtract(a, b) { return a - b; } ``` 模組化程式碼透過將功能組織成內聚的單元來提高可重複使用性和可維護性。在好的例子中,函數被正確地封裝和匯出,促進程式碼重用。相反,壞例子缺乏模組化,使其更難以管理和擴展。 - DRY 原則(不要重複): ``` // Good: const greeting = 'Hello'; function greet(name) { return `${greeting}, ${name}!`; } ``` ``` // Bad: function greet(name) { const greeting = 'Hello'; return `${greeting}, ${name}!`; } ``` 重複的程式碼會增加錯誤的風險並使維護變得困難。一個很好的例子是,將重複的字串提取為常數,遵循DRY原則並提高程式碼的可維護性。相反,壞範例在函數內冗餘地定義了問候語。 - 有意義的函數名稱: ``` // Good: function calculateArea(radius) { return Math.PI * radius ** 2; } ``` ``` // Bad: function calc(r) { return Math.PI * r ** 2; } ``` 函數名稱應準確反映其用途,以增強程式碼可讀性。在這個很好的例子中,函數名稱“calculateArea”清楚地表明了它的功能。相反,糟糕的例子使用了神秘的縮寫(“calc”),讓人不清楚函數的作用。 - 可測試性: ``` // Good: function sum(a, b) { return a + b; } module.exports = sum; ``` ``` // Bad: function sum(a, b) { console.log(a + b); } ``` 編寫可測試的程式碼有利於自動化測試,確保程式碼的可靠性和穩定性。在很好的範例中,函數被匯出用於測試目的,從而可以輕鬆設定和執行測試。相反,壞範例包含副作用(console.log),使得測試函數的行為變得具有挑戰性。 - 正確使用資料結構: ``` // Good: const studentGrades = [90, 85, 95, 88]; const averageGrade = studentGrades.reduce((total, grade) => total + grade, 0) / studentGrades.length; ``` ``` // Bad: const grade1 = 90; const grade2 = 85; const grade3 = 95; const grade4 = 88; const averageGrade = (grade1 + grade2 + grade3 + grade4) / 4; ``` 使用適當的資料結構可以增強程式碼的可讀性和可維護性。在很好的例子中,陣列用於儲存學生成績,以便於操作和計算。相反,壞範例依賴單一變數,導致重複且容易出錯的程式碼。 - 處理非同步操作: ``` // Good: async function fetchData(url) { try { const response = await fetch(url); if (!response.ok) { throw new Error('Network response was not ok'); } return await response.json(); } catch (error) { console.error('Error fetching data:', error); throw error; } } ``` ``` // Bad: function fetchData(url) { return fetch(url) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .catch(error => { console.error('Error fetching data:', error); throw error; }); } ``` 正確處理非同步操作可確保程式碼的可靠性和健全性。在一個很好的例子中,async/await 語法用於簡化非同步程式碼並優雅地處理錯誤。相反,壞範例使用嵌套的 Promise,導致回調地獄並降低程式碼可讀性。 - 依賴管理: ``` // Good: import { format } from 'date-fns'; ``` ``` // Bad: const dateFns = require('date-fns'); ``` 有效的依賴管理可以促進程式碼模組化和可擴展性。在一個很好的範例中,ES6 導入語法用於僅從“date-fns”庫導入所需的功能,從而減少不必要的導入並提高效能。相反,糟糕的範例使用 CommonJS require 語法,該語法導入整個“date-fns”模組,可能會使應用程式套件膨脹。 - 效能優化: ``` // Good: const sortedNumbers = [5, 2, 8, 1, 9]; sortedNumbers.sort((a, b) => a - b); ``` ``` // Bad: const unsortedNumbers = [5, 2, 8, 1, 9]; const sortedNumbers = unsortedNumbers.sort(); ``` 優化程式碼效能可確保高效執行並增強使用者體驗。在一個很好的範例中,使用自訂比較函數呼叫 sort() 方法來按升序對數字進行排序,與預設排序演算法相比,可以獲得更好的效能。相反,壞範例依賴於預設排序演算法,這對於數值陣列可能不是最有效的。 - Node.js API 中的正確錯誤處理: ``` // Good: app.get('/user/:id', async (req, res) => { try { const user = await getUserById(req.params.id); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user); } catch (error) { console.error('Error fetching user:', error); res.status(500).json({ error: 'Internal server error' }); } }); ``` ``` // Bad: app.get('/user/:id', async (req, res) => { const user = await getUserById(req.params.id); if (!user) { res.status(404).json({ error: 'User not found' }); } res.json(user); }); ``` 在 Node.js API 中,正確的錯誤處理對於確保穩健性和可靠性至關重要。在好的範例中,錯誤被捕獲並記錄,並且適當的 HTTP 狀態程式碼被返回到客戶端。相反,壞範例無法處理錯誤,可能導致未處理的承諾拒絕和不一致的錯誤回應。 - 高效率的檔案系統操作: ``` // Good: const fs = require('fs').promises; async function readFile(filePath) { try { const data = await fs.readFile(filePath, 'utf-8'); console.log(data); } catch (error) { console.error('Error reading file:', error); } } ``` ``` // Bad: const fs = require('fs'); function readFile(filePath) { fs.readFile(filePath, 'utf-8', (error, data) => { if (error) { console.error('Error reading file:', error); return; } console.log(data); }); } ``` 在檔案系統操作中使用 Promise 可以增強程式碼可讀性並簡化錯誤處理。在一個很好的範例中,fs.promises.readFile() 用於非同步讀取文件,並使用 try-catch 處理錯誤。相反,壞範例使用基於回調的方法,這可能導致回調地獄和可讀性較差的程式碼。 - 高效率的記憶體管理: ``` // Good: const stream = fs.createReadStream('bigfile.txt'); stream.pipe(response); ``` // 壞的: ``` fs.readFile('bigfile.txt', (error, data) => { if (error) { console.error('Error reading file:', error); return; } response.write(data); }); ``` 在 Node.js 中使用流進行大檔案處理可以節省記憶體並提高效能。在一個很好的例子中,fs.createReadStream() 和stream.pipe() 用於有效地將資料從檔案串流傳輸到HTTP 回應。相反,壞示例在將整個文件寫入響應之前將其讀入內存,這可能會導致大文件出現內存問題。 - 正確的模組導出和導入: ``` // Good: module.exports = { add: (a, b) => a + b, subtract: (a, b) => a - b }; ``` ``` // Bad: exports.add = (a, b) => a + b; exports.subtract = (a, b) => a - b; ``` 一致的模組導出和導入實踐提高了程式碼的可讀性和可維護性。在好的例子中, module.exports 用來匯出包含函數的物件,而在壞的例子中,直接使用exports。儘管這兩種方法都有效,但堅持一種約定可以增強程式碼的一致性。 - 非同步控制流程: ``` // Good: async function processItems(items) { for (const item of items) { await processItem(item); } } ``` ``` // Bad: function processItems(items) { items.forEach(item => { processItem(item); }); } ``` 適當的非同步控制流程可確保操作依需求順序或併發執行。在一個很好的範例中,非同步函數與 for...of 迴圈一起使用來順序處理專案,等待每個操作。相反,壞的例子使用了 forEach,它不能很好地處理非同步操作,並且可能會導致意外的行為。 --- 原文出處:https://dev.to/mahabubr/mastering-clean-code-essential-practices-for-developers-1287

掌握 JavaScript 生成器 🔥

JavaScript 是一種以其多功能性和易用性而聞名的語言,它具有多種功能,對於新手和經驗豐富的開發人員來說都非常強大。其中一項功能就是生成器。 ECMAScript 2015 (ES6) 中引入的生成器提供了一種處理迭代和非同步程式設計的獨特方法。在本文中,我們將探討什麼是生成器、它們如何運作以及它們的實際應用。 --- 什麼是 generator? ------- 生成器是一種特殊類型的函數,可以暫停和恢復執行。與呼叫時執行完成的常規函數不同,生成器在指定點將控制權交還給呼叫者。這種暫停和恢復的能力使它們對於需要一系列值或需要更優雅地處理非同步操作的任務特別有用。 --- 文法和基本用法 ------- 生成器函數是使用`function*`語法定義的,並使用`yield`關鍵字來暫停執行。 ``` function* myGenerator() { yield 1; yield 2; yield 3; } const gen = myGenerator(); console.log(gen.next()); // { value: 1, done: false } console.log(gen.next()); // { value: 2, done: false } console.log(gen.next()); // { value: 3, done: false } console.log(gen.next()); // { value: undefined, done: true } ``` 在此範例中, `myGenerator`是產生三個值的生成器函數。 `gen`物件是透過呼叫生成器函數所建立的迭代器。呼叫`gen.next()`傳回一個具有兩個屬性的物件: `value` (產生的值)和`done` (一個布林值,指示生成器是否已完成)。 --- `yield`的力量 ---------- `yield`關鍵字不僅暫停產生器,還允許將值傳回產生器。 ``` function* countingGenerator() { let count = 0; while (true) { count = yield count + 1; } } const counter = countingGenerator(); console.log(counter.next()); // { value: 1, done: false } console.log(counter.next(10)); // { value: 11, done: false } console.log(counter.next(20)); // { value: 21, done: false } ``` 在這裡,每次呼叫`counter.next()`都會恢復生成器,並且可以傳遞一個值來替換變數`count` 。這演示了生成器如何在暫停期間維護和更新其狀態。 --- 實際應用 ---- ### 📌 迭代 生成器在需要自訂迭代邏輯的場景中大放異彩。例如,您可以建立一個生成器來迭代一系列數字甚至複雜的資料結構。 ``` function* range(start, end) { for (let i = start; i <= end; i++) { yield i; } } for (const num of range(1, 5)) { console.log(num); // 1, 2, 3, 4, 5 } ``` --- ### 📌 非同步編程 生成器與 Promise 結合可以簡化非同步程式碼。像`co`這樣的函式庫使用這種模式比嵌套回呼或承諾鏈更自然地管理非同步流。 ``` const fetch = require('node-fetch'); function* fetchData(url) { const response = yield fetch(url); const data = yield response.json(); return data; } const co = require('co'); co(fetchData, 'https://api.example.com/data') .then(data => console.log(data)) .catch(err => console.error(err)); ``` --- ### 📌 無限序列 生成器可以建立無限序列,而由於陣列的有限性,這是不可能的。這在模擬、資料流或任何需要無限系列值的場景中非常有用。 ``` function* fibonacci() { let [prev, curr] = [0, 1]; while (true) { yield curr; [prev, curr] = [curr, prev + curr]; } } const fib = fibonacci(); console.log(fib.next().value); // 1 console.log(fib.next().value); // 1 console.log(fib.next().value); // 2 console.log(fib.next().value); // 3 console.log(fib.next().value); // 5 ``` --- 結論 -- JavaScript 中的生成器提供了一個強大的機制來處理序列、管理函數呼叫之間的狀態以及簡化非同步程式碼。 它們在 ES6 中的引入為該語言增添了顯著的靈活性和強大功能,使複雜的迭代和非同步模式變得更加平易近人。 隨著您深入研究 JavaScript,掌握生成器可以增強您編寫高效且可維護程式碼的能力。無論您是處理資料流、自訂迭代器還是非同步操作,生成器都提供了一個強大的工具來提升您的程式設計工具包。 --- ***快樂編碼!*** 🔥 **[領英](https://www.linkedin.com/in/dev-alisamir)** **[X(推特)](https://twitter.com/dev_alisamir)** **[電報](https://t.me/the_developer_guide)** **[Youtube](https://www.youtube.com/@DevGuideAcademy)** **[不和諧](https://discord.gg/s37uutmxT2)** **[Facebook](https://www.facebook.com/alisamir.dev)** **[Instagram](https://www.instagram.com/alisamir.dev)** --- 原文出處:https://dev.to/alisamirali/mastering-javascript-generators-15g3

掌握 Git 版本控制:超越基礎知識

\_歡迎參加 DevSecOps in 5 的第 2 週:您獲得安全開發超級大國的門票! 嘿,安全冠軍和編碼戰士! 您是否渴望提升 DevSecOps 水平並成為堅如磐石的軟體架構師?好吧,您來對地方了!這個為期 5 週的部落格系列是您掌握安全開發和部署的快速通道。 準備好拋棄開發戲劇,對您的安全實踐建立不可動搖的信心。我們同舟共濟,所以係好安全帶,讓我們踏上這段史詩般的旅程! --- 歡迎來到 Git 的世界,這是一個為無數軟體開發專案提供支援的無處不在的版本控制系統。雖然您可能已經掌握了初始化儲存庫、提交變更和推送程式碼的基本命令,但本部落格將進行更深入的研究,探索進階策略和工作流程以增強您對 Git 的掌握。 分支策略:超越 GitFlow --------------- 分支是 Git 的核心概念,它允許開發人員在不影響主程式碼庫的情況下處理獨立的程式碼行。然而,有效的分支策略對於維護清潔和協作的開發環境至關重要。在這裡,我們將探討流行的分支策略及其細微差別: #### GitFlow 與 GitHub Flow: 這兩種流行的分支策略提供了不同的方法: #### gitflow: 受到較大團隊的青睞,GitFlow 採用了一組專用的分支: #### master: 神聖不可侵犯的生產分支,只保存最穩定且經過徹底測試的程式碼。 #### develop: 整合了持續功能和錯誤修復的中央開發分支。 #### feature: 短期分支從針對特定功能的開發中分支出來,完成後合併回來。 #### hotfix: 短期分支直接從 master 分支出來,用於緊急錯誤修復,然後合併回開發分支和 master 分支。 發布分支:從開發分支出來的短期分支,為不同的環境準備發布。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rd07388its3zftj37eau.png) #### GitHub 流程: GitHub Flow 更輕量級且適合較小的團隊,它利用: #### master: 與 GitFlow 類似,僅儲存可用於生產的程式碼。 #### feature: 這些分支直接從 master 分支出來,包含功能和錯誤修復,在審查和測試後直接合併到 master 中。 #### hotfix: 與GitFlow類似,用於關鍵bug修復,直接合併到master中,然後刪除。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5a1osj6j2n0re1myppe7.png) #### 優點和適用性: GitFlow 為大型團隊提供結構化控制,確保程式碼在投入生產之前的穩定性。但是,它需要更嚴格地執行分支命名約定和工作流程。 GitHub Flow 對於較小的團隊來說更簡單、更快,專注於持續整合和快速迭代。選擇最適合您的專案規模、複雜性和團隊結構的策略。 #### 額外提示: 考慮使用分支模型視覺化工具(例如“git分支”)來獲得分支及其關係的清晰圖形視圖。 功能分支工作流程:最佳實踐 ------------- 功能分支是 Git 開發的主力。以下是如何利用它們來優化您的工作流程: #### 建立清晰且具描述性的分支名稱: 使用一致的命名約定(例如,功能/新登入系統)來提高專案的清晰度和可發現性。 #### 定期程式碼審查: 在合併回主分支之前,請另一位開發人員檢查您的程式碼的品質、效率以及對編碼標準的遵守情況。利用 GitHub 或 GitLab 等平台的內建審核功能來簡化溝通。 #### 合併策略: 採用「合併」或「變基」策略來整合您的功能分支: #### 合併: 建立合併提交,記錄分支和主分支之間的整合點。這更簡單,但可能會導致更複雜的 Git 歷史記錄。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efj71to6b9ahiwtxbson.png) #### 狐狸: 在最新的主分支提交之上重寫功能分支的提交,從而產生更清晰的 Git 歷史記錄。然而,變基需要謹慎,因為它可以重寫其他合作者所看到的歷史。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no72l54ss657ygf3t4dy.png) #### 衝突解決技巧: 當對不同分支所做的變更影響相同的程式碼行時,可能會出現合併衝突。學習使用 Git 的內建合併工具或手動編輯來辨識和解決衝突。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3jkzk7vi9iy1in80qvic.png) 修補程式和版本的分支 ---------- 專用分支服務於功能開發以外的特定目的: #### 修補程式分支: 對於需要立即部署的關鍵錯誤修復,請直接從主伺服器建立修補程式分支。修復問題,在臨時環境中進行徹底測試,並將修補程式合併回主版本(並在適用的情況下進行開發)以快速解決問題。合併後刪除修補程式分支。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9wc9hbgwq8ellvdgv94x.png) #### 發布分支: 使用從開發分支的專用分支準備版本。整合錯誤修復、最終功能完善和文件更新。嚴格測試完成後,將發布分支合併至 master 進行部署。考慮在 master 中標記提交以進行版本控制。 使用 Git 的協作工作流程 -------------- #### 分叉和拉取請求: GitHub 和 GitLab 等平台允許開發人員「分叉」儲存庫,建立個人副本。在他們的分支上,他們可以建立功能分支,實施更改,然後向原始儲存庫提交「拉取請求」。這會觸發程式碼審查流程,維護人員可以審查變更、建議修改並批准拉取請求以將程式碼合併到主分支中。 #### 解決合併衝突: 當多個開發人員在不同的分支中處理相同的檔案時,就會發生合併衝突。 Git 通常會突出顯示這些衝突,您有責任手動編輯文件來解決它們。 Git 的合併工具或 Git 用戶端中的視覺化合併編輯器等工具可以簡化此流程。 #### 使用遠端儲存庫: 使用 GitHub 或 GitLab 等遠端儲存庫服務集中化版本控制。這提供了許多好處: #### 合作: 團隊成員可以輕鬆分叉、克隆程式碼並將其推送到遠端儲存庫,從而促進協作開發。 版本控制歷史記錄:遠端儲存庫維護完整的 Git 歷史記錄,讓您可以恢復到先前的版本或追蹤程式碼演進。 #### 備份和災難復原: 如果本機電腦發生故障,遠端儲存庫可確保程式碼庫的安全備份。 用於自動化任務的 Git Hooks ------------------ Git 掛鉤是在 Git 工作流程中的特定點自動執行的腳本,增加了自動化並實施最佳實踐。 #### Git Hook 的類型: 有幾種預定義的鉤子類型: #### 預提交: 在提交之前執行,允許您強制執行編碼標準或執行 linting 檢查。 #### 提交後: 在提交後執行,對於更新建置版本或發送通知很有用。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gqmapedl10bu9hub5ozt.png) #### 預推: 在程式碼被推送到遠端儲存庫之前執行,通常用於最終檢查或測試。 #### 推後: 在推送程式碼後執行,可能會觸發部署或整合。 常見的 Git Hook 使用案例:Git hook 可以自動執行各種任務: #### 程式碼格式: 使用在提交之前執行程式碼格式化程式(例如 autopep8 或 clang-format)的鉤子來強制執行一致的程式碼風格。 #### 單元測試: 在推送程式碼之前使用 pytest 或 Jest 等掛鉤執行自動化單元測試,確保整合先前的基本功能。 #### 靜態程式碼分析: 透過預先提交掛鉤將 Pylint 或 ESLint 等靜態程式碼分析工具整合到您的工作流程中,以辨識潛在的錯誤或漏洞。 #### 建立自訂 Git Hook: 雖然預先定義的掛鉤可以滿足常見需求,但您可以使用 Bash 或 Python 等腳本語言建立自訂掛鉤。有關建立和配置自訂掛鉤的詳細說明,請參閱 Git 文件。 #### 適用於非程式設計師的 Git: Git 不僅僅適合程式設計師!對於使用基於文字的文件進行協作專案的任何人來說,它都很有價值。使用它來管理文件、設定文件,甚至具有版本控制的創意寫作專案。 高級 Git 主題: #### 藏匿: 暫時儲存未提交的變更以供以後使用。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6ztfitlypw84z9evpgz.png) #### 子模組: 管理較大專案中不同 Git 儲存庫之間的依賴關係。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2aclbe66vn30rv3ipfx7.png) #### 變基 :重新組織您的 Git 歷史記錄,以獲得更清晰的線性進展(謹慎使用!)。 #### 將 Git 與不同的工具和 IDE 結合使用: Visual Studio Code、IntelliJ IDEA 和 Eclipse 等流行的開發工具和 IDE 與 Git 無縫集成,為直接在開發環境中提交、分支和合併程式碼提供了流暢的工作流程。 深入研究 Git:高級技術和高級用戶提示 -------------------- 現在您已經掌握了基礎知識,讓我們為經驗豐富的使用者深入研究進階 Git 概念: #### 進階分支策略: 功能標誌和分支切換:使用功能標誌管理向特定環境或使用者群組推出新功能。將此與 Git 分支結合起來,建立啟用功能標誌的功能分支,從而允許分階段部署和受控部署。 #### Git 鏡像: 使用 Git 映像建立遠端儲存庫的同步副本,以實現災難復原或冗餘目的。這會在另一台伺服器上建立儲存庫的完整副本,確保在發生中斷或意外刪除時的資料安全。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nfgyskg46rxgo4gvsn87.png) #### 高級版本控制的精挑細選和變基: 這些技術提供了對 Git 歷史記錄的精細控制: #### 採櫻桃: 選擇特定提交並將其從一個分支應用到另一個分支,這對於合併來自修補程式分支的錯誤修復而不合併整個分支非常有用。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mi9w8wsnu5n99acsa9a.png) 變基(互動式): 透過重新排列、編輯或壓縮提交來重寫 Git 歷史記錄。互動式變基允許對重寫過程進行更細粒度的控制。謹慎使用這些技術,因為它們可以改變合作者所看到的歷史並且需要仔細協調。 Git Porcelain 命令和重構 ------------------- #### 可拆卸 HEAD 和變基工作流程: Git 中的 HEAD 指的是目前簽出的提交。可拆卸的 HEAD 可讓您將其與工作目錄分離,從而實現複雜的變基等高級工作流程。這是一個強大但在概念上具有挑戰性的功能。 #### 互動式變基: 如前所述,互動式變基允許以互動方式編輯現有提交並重構 Git 歷史記錄。你可以: 將大型提交拆分為更小、更集中的提交。 將多個提交合併為一個提交。 編輯現有提交的提交訊息。 重新排序致力於反映開發的邏輯流程。 用於日常任務的 Git Porcelain 命令:Git 為各種用例提供了一套強大的「Porcelain」命令: `git add -p (patch):` 暫存文件中的特定更改而不是整個文件。 `git stash:` 暫時儲存未提交的變更以供以後檢索,這對於切換上下文或測試分支很有用。 `git lfs (Large File Storage):` 使用 Git LFS 在儲存庫中有效管理大型文件(影片、映像),它可以單獨儲存這些文件,而不會增加儲存庫的大小 具有大型程式碼庫的 Git ------------- #### Git 大檔案儲存 (LFS): 如前所述,Git LFS 對於管理 Git 儲存庫中的大檔案至關重要。它追蹤存儲庫中的這些文件,但將它們存儲在單獨的位置,從而保持主存儲庫的精簡和高效。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pyamfu90d4mlhnksb4e2.png) #### 模組化開發的子模組: 將大型專案分解為較小的模組化元件,由單獨的 Git 儲存庫管理。您可以將這些子模組整合到更大的專案(monorepo)中,同時維護每個模組的獨立版本控制。 適用於分散式團隊和持續整合 (CI) 的 Git: ------------------------- 在分散式團隊中利用 Git:Git 在地理分散的團隊中表現出色。就是這樣: #### 遠端儲存庫: 在 GitHub 或 GitLab 等平台上集中進行版本控制,使每個人都可以無縫地複製、推送和拉取程式碼。 #### 分支策略: 採用 GitFlow 或 GitHub Flow 等清晰的分支策略來管理並發開發並避免衝突。 #### 溝通與協調: 保持清晰的溝通管道並利用拉取請求審查和問題追蹤器等工具進行有效協作。 #### Git 與 CI/CD 管道整合: 持續整合和持續交付 (CI/CD) 管道可自動執行建置、測試和部署。將 Git 與 CI/CD 管道集成,以便在程式碼變更時自動觸發這些流程: #### CI 觸發器: 配置 CI 系統以在程式碼推送到特定分支時觸發建置和測試。 部署自動化:根據成功的建置和測試,自動部署到不同的環境(暫存、生產)。 #### CI 管道的 Git Hooks: 自訂 Git 掛鉤可以觸發 CI 管道中的特定操作: #### 預推掛鉤: 在推送程式碼之前執行程式碼品質檢查或單元測試,以防止在到達遠端儲存庫之前出現回歸。 #### 後推掛鉤: 成功推播後觸發部署或自動通知。 #### Git 用於非程式碼資產的版本控制: Git 不僅限於程式碼。使用它來管理非程式碼資產的版本控制,例如: #### 文件: 追蹤文件檔案隨時間的變化。 設定檔:維護開發、登台和生產環境的不同配置。 #### 設計樣機: 版本控制設計資產(例如模型和原型)可輕鬆協作和迭代。 #### 視覺化 Git 歷史記錄: 「git log --graph」等工具或 GitKraken 等圖形用戶端可以以使用者友好的格式視覺化您的 Git 歷史記錄,幫助您一目了然地了解分支和合併活動。 結論 -- 這本綜合指南為您提供了在基礎知識之外駕馭 Git 的知識和技術。請記住,掌握 Git 是一個持續的旅程。繼續練習、試驗這些概念,並利用龐大的線上 Git 社群進行進一步探索。以下是一些可協助您掌握 Git 的額外資源: 官方 Git 文件:https://git-scm.com/ - Git 所有內容的權威來源,包含深入的解釋、命令和教學。 互動式 Git 訓練:https://learngitbranching.js.org/ - 一個學習 Git 基礎並在模擬環境中進行分支和合併實驗的動手平台。 Git SCM 部落格:https://git-scm.com/ - 隨時了解 Git 團隊的最新 Git 開發、新聞和最佳實踐。 線上 Git 社群:Stack Overflow、GitHub Discussions 和 Git 論壇等平台提供了經驗豐富的 Git 用戶的豐富知識和幫助。 透過積極利用這些資源並將新學到的知識付諸實踐,您將成為 Git 高級用戶,準備好應對專案遇到的任何版本控制挑戰。快樂分支! --- 我很高興有機會今天與您一起深入研究《掌握 Git 版本控制:超越基礎知識》。這是一個令人著迷的領域,具有改善安全狀況的巨大潛力。 感謝您與我一起探索《使用 Git 掌握版本控制:超越基礎》。您持續的興趣和參與推動了這趟旅程! 如果您發現有關使用 Git 進行版本控制:超越基礎知識的討論有幫助,請考慮與您的網路分享!知識就是力量,尤其是在安全方面。 讓我們繼續談話吧!在下面的評論中分享您的想法、問題或經驗《掌握 Git 版本控制:超越基礎知識》。 渴望了解有關 DevSecOps 最佳實踐的更多資訊?請繼續關注下一篇文章! 透過共同努力並採用安全的開發實踐,我們可以建立一個更具彈性和值得信賴的軟體生態系統。 請記住,安全開發之旅是一個持續學習的過程。這是為了持續改進! --- 原文出處:https://dev.to/gauri1504/mastering-version-control-with-git-beyond-the-basics-44ib

如何在NodeJS中實現授權

**介紹:** ------- 身份驗證和授權是 Web 應用程式安全性中的兩個基本概念。當我們建立 Web 應用程式時,確保只有正確的使用者才能存取我們網站的某些部分對於安全性至關重要。這就是身份驗證和授權發揮作用的地方。 在本文中,我們將討論身份驗證和授權,以及如何在 Nodejs 應用程式中實作它們。 那麼事不宜遲,讓我們開始吧! **了解授權** -------- ![顯示 HTML 程式碼的電腦螢幕特寫,並顯示錯誤訊息「驗證失敗。請聯絡管理員」。](https://images.unsplash.com/photo-1618044619888-009e412ff12a?q=80&w=1000&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D) ### **什麼是授權?** 授權是授予使用者執行特定工作/操作的權限的過程。它決定允許經過身份驗證的使用者在應用程式內執行哪些操作。經過驗證後,授權可確保使用者僅執行允許執行的操作,並遵循特定的規則和權限。 一些常見的身份驗證方式是: - 基於角色的存取控制 (RBAC) - 基於屬性的存取控制 (ABAC) - 基於策略的存取控制(PBAC) ### **授權如何運作?** 授權過程如下: - 經過身份驗證的使用者向伺服器發出請求。 - 伺服器驗證使用者並取得其指派的角色和權限。 - 伺服器評估使用者是否有權執行所請求的操作。 - 如果使用者獲得授權,伺服器將允許使用者執行請求的操作。 - 否則,它會拒絕存取並返回適當的回應。 ### **什麼是基於角色的存取控制 (RBAC)?** ![說明基於角色的存取控制 (RBAC) 的圖表。客戶端將帶有使用者憑證的管理服務請求傳送到管理節點管理器。管理節點管理器定義權限層級的角色,與服務 1、服務 2 和服務 3 互動以執行身份驗證並確保用戶端有權存取。然後客戶端接收並處理回應。](https://lh7-us.googleusercontent.com/mpwrmZ13hD2p5SL6s64A4USQOMGxvUT46zMXkyjcHC0nKGRfF_JHIdrkOR6FWZrpmNf35a8mLMGYRow84v--hZUNjNOkxTQj3I1Yi-KCtB4O8dfHqOK3N8Ejv1Xa6-J5-rY8YQNutGpzk_jXT9-pjvg) 基於角色的存取控制是一種存取控制方法,它根據使用者在應用程式中分配的角色向使用者授予權限。簡而言之,它控制用戶在應用程式中可以執行的操作。 RBAC 不是將權限指派給單一用戶,而是將使用者分組為角色,然後將權限指派給這些角色。這使得管理存取控制變得更加容易,因為我們只需要更新角色的權限,而不是每個單獨使用者的權限。 RBAC 的關鍵元件是: - 角色:定義應用程式內的一組職責、任務或功能 - 權限:代表使用者可以執行的特定操作。 - 角色分配:使用者被指派給一個或多個角色,每個角色都與一組權限相關聯。 - 存取控制策略:規定哪些角色可以存取特定資源以及他們可以採取哪些操作。 **在 NodeJS 中實作授權** ------------------ 到目前為止,我們已經了解了身份驗證和授權。讓我們探索如何在 NodeJS 應用程式中實現它們。 在本節中,我們將建立一個簡單的 NodeJs 應用程式並整合身份驗證和授權功能。 ### 基本專案設定和身份驗證 要設定基本的 Node.js 專案並新增 JWT 身份驗證,您可以查看以下文章,其中我詳細解釋了每個步驟: [設定基本 Node.js 專案並新增 JWT Auth](https://arindam1729.hashnode.dev/jwt-authentication-in-nodejs#heading-project-setup) ### **實施授權** 在本節中,我們將在 Nodejs 應用程式中實作授權。 #### 1. 更新用戶架構: 我們將更新使用者架構並新增一個「角色」字段,我們將在其中定義使用者的角色/範圍。我們將在後面的部分中使用這些角色進行授權。 ``` const mongoose = require("mongoose"); const userSchema = new mongoose.Schema({ username: { type: String, required: true, unique: true, }, password: { type: String, required: true, }, role:{ type: String, required: true, default: "user", } }); module.exports = mongoose.model("User", userSchema); ``` #### 2. 更新認證路由: 接下來,我們將更新`/signup`和`/login`路由。我們將從註冊路由的請求正文中獲取新新增的角色。 ``` // updated sign up router.post("/signup", async (req, res) => { try { const { username, password, role } = req.body; const user = new User({ username, password,role }); await user.save(); res.status(201).json({ message: "New user registered successfully" }); } catch (error) { res.status(500).json({ message: "Internal server error" }); } }); ``` 在登入路徑中,就像使用者名稱和密碼驗證一樣,我們也會驗證使用者的角色。 ``` // Updated Login route router.post("/login", async (req, res) => { const { username, password, role } = req.body; try { const user = await User.findOne({ username }); if (!user) { return res.status(401).json({ message: "Invalid username or password" }); } if (user.password !== password) { return res.status(401).json({ message: 'Invalid username or password' }); } if (user.role !== role) { return res.status(401).json({ message: 'Invalid role' }); } // Generate JWT token const token = jwt.sign( { id: user._id, username: user.username, role: user.role}, process.env.JWT_SECRET ); res.json({ token }); } catch (error) { res.status(500).json({ message: "Internal server error" }); } }); ``` #### 3. 建立管理驗證中間件: 現在,我們將建立一個中間件來驗證使用者是否是管理員。 ``` function verifyAdmin(req, res, next) { if (req.user.role !== "admin") { return res.status(401).json({ message: "Access denied. You need an Admin role to get access." }); } next(); } module.exports = verifyAdmin; ``` #### 4. 建立管理路由: 之後,我們將在主`index.js`中建立一個管理路由來驗證使用者是否具有管理員存取權限。 ``` // index.js const adminMiddleware = require("./middleware/admin"); app.get("/admin", userMiddleware, adminMiddleware, (req, res) => { const { username } = req.user; res.send(`This is an Admin Route. Welcome ${username}`); }); ``` #### 5. 測試端點: 在註冊路徑中,我們將建立一個具有管理員角色的新使用者。 為此,我們將使用以下正文向[`http://localhost:3000/auth/signup`](http://localhost:3000/auth/signup)發出 POST 請求: ``` {     "username": "Arindam Majumder",     "password": "071204",     "role": "admin" } ``` ![Postman 介面的螢幕截圖,顯示了「http://localhost:3000/auth/signup」的 POST 要求,其中包含包含使用者名稱、密碼和角色的 JSON 正文。回應正文顯示一則訊息:“新用戶註冊成功”,狀態為 201 Created。](https://lh7-us.googleusercontent.com/4AsIcyQYmEgP38jlExZ0JJk_nnzCLvbn6Vflg2w_fHMgnGv39JenYDBhd5W0OgOT516USD-RoPIVWqYPXBCmxMRfhUSOXcEjizs3ZELeAps6AqcB6PX7rM6Tpd1XJt2kgm0UVQ_xYmgNQTc2Cm1tKC4) 新用戶已註冊。我們更新後的註冊報價正常運作。 同樣,在登入路由中,我們將取得新使用者的令牌。 為此,我們將使用類似的正文向[`http://localhost:3000/auth/login`](http://localhost:3000/auth/login)發出 GET 請求: ``` { "username": "Arindam Majumder", "password": "071204", "role": "admin" } ``` 我們將得到一個像這樣的令牌: ![Postman 介面的螢幕截圖顯示了對「http://localhost:3000/auth/login」的 POST 要求。請求內文包含 JSON 資料,其中包含「使用者名稱」、「密碼」和「角色」欄位。回應正文顯示帶有「令牌」欄位的 JSON 物件。請求的狀態為 200 OK。](https://lh7-us.googleusercontent.com/H76nwPmFj-vCvnULTn0dmo2ABKjuHBx-aemMNYo9DCGTsSaKj_RpxrvdyQuENgGFN-TDefoN_-78fAenWQ3UjSeHkCpq1EIAceTWqTdbaKkvvbiTXYlrovVmYzmALcmYMakMyXw_xx7MYAm1NNWBoM8) 現在,我們將測試我們的管理路由。為此,我們將使用以下正文向[`http://localhost:3000/admin`](http://localhost:3000/admin)發出 GET 請求: ``` { "username": "Arindam Majumder", "password": "071204", "role": "admin" } ``` 這次我們還必須加入一個授權標頭並在其中加入令牌來驗證我們的用戶。 ``` Authorization = USERS_JWT_TOKEN ``` 我們將得到以下回應: ![Postman 介面的螢幕截圖,顯示了「http://localhost:3000/admin」的 GET 要求,其中包含 JSON 正文參數,包括「使用者名稱」、「密碼」和「角色」。回應部分顯示一條訊息:“這是一條管理路線。歡迎 Arindam Majumder。”狀態為 200 OK。](https://lh7-us.googleusercontent.com/hXtX9n0Bb0fJl50zJRbA50XGLPGwpKsgffdkQa_-w58p_Oo9fillBPy9f6k0jH2SOz2FOh5xwdKPLXqCcqerrrMgUpQkA2AKdqnZGN_tGjEYIiUJCqcCuibc-7Z-W-j7hlfXUOTtwf4oQQC5NvuetNA) 這意味著我們的端點正在按預期工作。 至此,我們已經在 NodeJs 應用程式中成功實現了授權。 **結論** ------ 總的來說,身份驗證和授權在現代 Web 應用程式中非常重要。 在本文中,我們介紹了身份驗證和授權的基礎知識以及如何將它們整合到 NodeJs 應用程式中。 希望您覺得這有幫助。不要忘記分享您對評論的回饋。 如需付費合作,請發送電子郵件至: <[email protected]> 在[Twitter](https://twitter.com/intent/follow?screen_name=Arindam_1729) 、 [LinkedIn](https://www.linkedin.com/in/arindam2004/) 、 [Youtube](https://www.youtube.com/channel/@Arindam_1729)和[GitHub](https://github.com/Arindam200)上與我聯絡。 快樂編碼! ![謝謝 :)](https://cdn.hashnode.com/res/hashnode/image/upload/v1713555130149/625f8664-4caa-4318-bfe7-97bec77085bb.png) --- 原文出處:https://dev.to/arindam_1729/how-to-implement-authorization-in-nodejs-31hk

同步引擎是 Web 應用程式的未來嗎?

請看下面的 GIF — 它顯示了一個即時[Todo-MVC 演示](https://todo-replicache-sveltekit.onrender.com/),跨視窗同步並平滑地進出離線模式。雖然它只是一個簡單的演示應用程式,但它展示了每個 Web 開發人員都應該了解的重要的前沿概念。這是一個[Replicache](https://replicache.dev/)演示應用程式,我將其從 Express 後端和 Web 元件前端移植到 SvelteKit,以了解背後的技術和概念。我想與您分享我的學習成果。原始碼可[在 Github 上](https://github.com/isaacHagoel/todo-replicache-sveltekit)取得。 ![sveltekit-replicache-演示](https://github.com/isaacHagoel/todo-replicache-sveltekit/assets/20507787/11b5ae10-049d-4cc7-82bf-45d8287701f0) 背景和動機 ----- Web 應用程式面臨一些根本性的難題,而大多數 Web 框架似乎都忽略了這些問題。這些問題非常困難,以至於只有很少的應用程式能夠真正很好地解決它們,並且這些應用程式在各自的領域中遙遙領先於其他應用程式。 以下是我在實際開發的商業應用程式中必須處理的一些此類問題: 1. 讓應用程式感覺敏捷,即使它與伺服器通信,即使在緩慢或不穩定的網路上。這不僅適用於初始載入時間,也適用於應用程式載入後的互動。 [SPA](https://developer.mozilla.org/en-US/docs/Glossary/SPA)是解決這個問題的早期嘗試,但最終還不夠。 2. 為使用者產生的內容(例如網站建立、電子商務、線上課程建構器)實施撤銷/重做和版本歷史記錄。 3. 當同一用戶在多個分頁/裝置上同時開啟應用程式時,請讓應用程式正常運作。 4. 處理執行舊版本前端的長期會話,使用者可能不想刷新以避免丟失工作。 5. 使協作功能/多人遊戲功能正確且近乎即時地工作,包括解決衝突。 我在開發完全正常的 Web 應用程式時遇到了這些問題,沒有什麼太瘋狂的,而且我相信大多數 Web 應用程式在獲得吸引力時都會遇到部分或全部問題。 我在開始開發新產品的開發團隊中註意到的一個模式是完全忽略這些問題,即使團隊已經意識到這些問題。推理通常是這樣的:“當我們真正開始遇到這些問題時,我們會處理它。”然後,團隊將繼續選擇一些完善的框架(選擇您最喜歡的),認為這些工具肯定能為可能出現的任何常見問題提供解決方案。幾個月後,當應用程式達到一萬名活躍用戶時,現實就浮出水面:團隊必須引入部分的、不完整的解決方案,這些解決方案會增加複雜性,使系統更加緩慢和錯誤,或者重寫核心部分(之後沒有人立即這樣做)發射)。哎喲。 我感受到了這種痛苦。痛苦是真實的。 輸入“同步引擎”。 同步引擎到底是什麼? ---------- 還記得我說過有些應用程式比其他應用程式更好地解決這些問題嗎?最近著名的例子是[Linear](https://linear.app/isaach)和[Figma](https://www.figma.com/) 。兩者都透過技術優勢擾亂了競爭異常激烈的市場。其他例子有[Super human](https://superhuman.com/)和十年前的[Trello](https://trello.com/) 。當您研究他們所做的事情時,您會發現它們都集中在非常相似的模式上,並且它們都在內部開發了各自的實現。您可以在以下連結中了解他們是如何做到的(強烈推薦): [Figma](https://www.figma.com/blog/how-figmas-multiplayer-technology-works/) 、 [Linear](https://www.youtube.com/live/WxK11RsLqp4?feature=share&t=2175) 、 [Super human](https://blog.superhuman.com/superhuman-is-built-for-speed/) 、 [Trello(系列)](https://www.atlassian.com/engineering/sync-architecture) 。 在系統的核心,始終有一個同步引擎,可作為前端和後端之間的持久緩衝區。從高層次來看,它是這樣運作的: - 客戶端始終讀取和寫入引擎提供的本地儲存。就應用程式程式碼而言,它在記憶體中本地執行。 - 該儲存負責樂觀地更新狀態,將資料本地保存在瀏覽器的儲存中,並與後端來回同步,包括處理潛在的複雜情況和邊緣情況。 - 後端實作引擎的另一半,以允許拉取和推播資料、在資料變更時通知客戶端、將資料保存在資料庫中等。 同步引擎的不同實作會做出不同的權衡,但基本概念始終是相同的。 這不是一個新想法,但... ------------- If you've been following trends in the web-dev world, you'd know that sync engines have been a centrepiece in several of them, namely: [progressive web apps](https://web.dev/articles/what-are-pwas) , [offline-first apps](https://offlinefirst.org/) , and the lately trending term: [local-first軟體](https://www.inkandswitch.com/local-first/).您甚至可能研究過一些提供內建同步引擎的資料庫,例如[PouchDb](https://pouchdb.com/)或具有相同功能的線上服務(例如[Firestore](https://firebase.google.com/docs/firestore) )。我也有,但過去幾年我的整體感覺是,這些都不是切中要害的。漸進式網頁應用程式是關於用戶在主螢幕上「安裝」網站的快捷方式,就好像它們是本機應用程式一樣,儘管不需要安裝可能是網路的「好處」。 「離線優先」聽起來離線模式比線上模式更重要,但對於 99% 的網路應用程式來說,情況並非如此。 「本地優先」無疑是迄今為止最好的名字,但官方的[本地優先宣言](https://www.inkandswitch.com/local-first/)談論了點對點通信和[CRDT](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type) (一個超級酷的想法,但除了協作文本編輯之外很少用於任何其他用途)。客戶端-伺服器Web 應用程式的世界正在嘗試解決像我上面描述的那樣的實際問題。諷刺的是,許多屬於當前「本地優先」浪潮一部分的工具都採用了這個名稱,但沒有採用所有原則。 最引起我注意和興趣的是「Replicache」。具體來說,我對它很感興趣,因為它不是一個自我複製的資料庫,也不是一個你必須圍繞它來建立整個應用程式的黑盒 SaaS 服務。相反,與我在這個領域遇到的任何現成解決方案相比,它提供了更多的控制、靈活性和關注點分離。 什麼是複製快取? -------- Replicache 是一個函式庫。在前端,它只需要很少的佈線,並且可以有效地充當普通的全局商店(想想 Zustand 或 Svelte 商店)。它有一個狀態區塊(在我們的範例中,每個清單都有自己的儲存)。它可以使用一組稱為“mutators”(認為是reducers)的用戶定義函數進行變異,例如“addItem”、“deleteItem”或任何您想要的東西,並公開一個訂閱函數(我[在這裡](https://doc.replicache.dev/api/classes/Replicache)簡化了完整的API)。 在這個熟悉的介面背後是一個強大且高效能的客戶端同步引擎,它可以處理: 1. 初步將相關資料完整下載到客戶端。 2. 從後端拉動和推送“突變”。突變是一個事件,指定應用哪個突變器以及哪些參數(加上一些元資料)。 ``` - When pushing, these changes are applied optimistically on the client, and rolled back if they fail on the server. Any other pending changes would be applied on top (rebase). ``` ``` - The sync mechanism also includes queuing changes if the connection is lost, retry mechanisms, applying changes in the right order, and de-duping. ``` 3. 將所有內容快取在記憶體中(效能)並將其保存到瀏覽器儲存(特別是 IndexedDB)以進行備份。 4. 由於可以從同一應用程式的所有選項卡存取相同的存儲,因此引擎會處理其中的所有含義,例如當架構發生更改但某些選項卡已刷新而某些選項卡尚未刷新且仍在使用時該怎麼辦舊模式。 5. 使用廣播通道立即保持所有選項卡同步(因為依賴共用儲存不夠快)。 6. 處理瀏覽器決定清除本地儲存的情況。 您可能已經注意到,這裡解決了我在本文頂部列出的大部分問題。基於突變也適合撤銷/重做等功能。 為了讓所有這些都能發揮作用,後端的工作就是實作 Replicache 定義的協定。具體來說: 1. 您需要實作[推送](https://doc.replicache.dev/reference/server-push)和[拉取](https://doc.replicache.dev/reference/server-pull)API。這些端點需要能夠像前端一樣啟動變異器(儘管它們不必執行相同的邏輯)。後端是權威的,衝突解決是由您的 mutator 實作中的程式碼完成的。 2. 您的資料庫需要支援快照隔離並在事務內執行操作。 3. Replicache 用戶端定期輪詢伺服器以檢查更改,但如果您希望用戶端之間接近即時同步,則需要實作「poke」機制,即通知客戶端某些內容已更改並且需要進行更改的方法。拉。這可以透過[伺服器發送的事件](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)或[websockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)來完成。這是一個有趣的 API 設計選擇——更改永遠不會推送到客戶端;客戶總是拉他們。我相信這樣做是為了簡單且易於對系統進行推理。有一點可以肯定:他們沒有強制使用Websocket,這是件好事,因為這會使協議與HTTP(伺服器透過正常HTTP 連接發送的事件流)不相容,這將需要額外的基礎設施並帶來額外的集成挑戰。 4. 根據[版本控制策略](https://doc.replicache.dev/strategies/overview),您可能需要實作其他操作(例如,createSpace)。 如果這對您來說並不平凡,那麼您是對的。我認為我還沒有完全理解它如何與資料庫一起操作的所有細節。我需要做一個後續專案,在其中完全重構資料庫結構和/或向範例加入有意義的功能(例如版本歷史記錄),以便更接近完全理解它。問題是,我知道在建立和維護實際生產應用程式時這種控制層級有多麼有價值。在我的書中,花一兩週的時間深入思考和設定應用程式的核心部分,如果它為建立和擴展奠定了堅實的基礎,那麼它就是一筆巨大的投資。 移植一個重要的範例 --------- 學習新事物的最好(也可以說是唯一)方法就是親自動手,親自體驗一些會影響真正應用程式的權衡和影響。當我查看[Replicache 網站上的範例](https://doc.replicache.dev/examples/todo)時,我注意到沒有 Sveltekit 的範例。自從 Svelte 3 發布以來,我一直是 Svelte 的忠實粉絲,但最近才開始使用 Sveltekit。我認為這將是一個透過實踐學習並同時建立有用的參考來實現的絕佳機會。 將現有程式碼庫移植到不同的技術具有教育意義,因為在翻譯程式碼時,您被迫理解並質疑它。在整個過程中,我經歷了多次靈光一現的時刻,因為一些起初看起來很奇怪的事情都發生了。 學習內容 ---- #### 斯維爾特基特 1. Sveltekit[本身並不支援 WebSockets](https://github.com/sveltejs/kit/issues/1491) ,即使它確實支援伺服器發送事件,但它的[方式也很笨拙](https://stackoverflow.com/questions/74879852/how-can-i-implement-server-sent-events-sse-in-sveltekit)。 Express 很好地支援兩者。因此,我使用[svelte-sse](https://github.com/razshare/sveltekit-sse)來處理伺服器發送的事件。我遇到的一個有點煩人的怪癖是,由於 svelte-sse 返回一個 Svelte 商店,而我的應用程式沒有訂閱該商店(應用程式不需要讀取該值,只需觸發如上所述的拉取),整件事情只是被編譯器優化掉了。起初我很困惑為什麼訊息沒有通過。我最終不得不針對這種行為實施解決方法。我不怪圖書館的作者;我只是怪罪圖書館的作者。他們假設一個有意義的值將發送給客戶端,但「poke」的情況並非如此。 2. 與原始 Express 後端相比,SvelteKit 基於檔案系統的路由、載入函數、佈局和其他功能可以實現更好組織的程式碼庫和更少的樣板程式碼。不用說,在前端,Svelte 遠遠領先於 Web 元件,導致前端程式碼庫更小、更易讀,儘管它具有更多功能(原始示例 TodoMVC 缺少諸如“將所有內容標記為完成”等功能) “刪除完成”)。 3. 總的來說,我喜歡 Sveltekit 並計劃在未來繼續使用它。如果您還沒有嘗試過,[官方教學](https://learn.svelte.dev/tutorial/introducing-sveltekit)是一個很棒的介紹。 ### 複製快取 總的來說,Replicache 給我留下了非常深刻的印象,並建議嘗試一下。在基本層面上(這是我目前要做的所有嘗試),它運作良好並兌現了所有承諾。話雖如此,以下是我的一些普遍擔憂(與待辦事項應用程式無關)以及與之相關的想法: - **性能相關:** ``` - **Initial load time** (first time, before any data was ever pulled to the client) might be long when there is a lot of data to download (think tens of MBs). Productivity apps in which the user spends a lot of time after the initial load are less sensitive to this, but it is still something to watch for. Potential mitigation: partial sync (e.g., Linear only sends open issues or ones that were closed over the last week instead of sending all issues). ``` ``` - **Chatty network (?)** - Initially, it seemed to me that there was a lot of chatter going back and forth between the client and the server with all the push, pull, and poke calls flying around. On deeper inspection, I realized my intuition was wrong. There is frequent communication, yes, but since the mutations are very compact and the poke calls are tiny (no payload), it amounts to much less than your normal REST/GraphQL app. Also, a browser full reload (refresh button or opening the page again in a new tab/window after it was closed) loads most of the data from the browser's storage and only needs to pull the diffs from the server, which leads me to the next point. ``` ``` - **Coming back after a long period of time offline**: I haven't tested this one, but it seems like a real concern. What happens if I was working offline for a few days making updates while my team was online and also making changes? When I come back online, I could have a huge amount of diffs to push and pull. Additionally, conflict resolution could become super difficult to get right. This is a problem for every collaborative app that has an offline mode and is not unique to Replicache. The Replicache docs [warn about this situation](https://doc.replicache.dev/concepts/offline) and propose implementing "the concept of history" as a potential mitigation. ``` ``` - What about **bundle size**? Replicache is [34kb gzipped](https://bundlephobia.com/package/[email protected]), and for what you get in return, it's easily worth it. ``` ``` - [This page](https://doc.replicache.dev/concepts/performance) on the Replicache website makes me think that, in the general case, performance should be very good. ``` - **功能相關:** ``` - Unlike native mobile or desktop apps, it is possible for users to **lose the local copy of their work** because the browser's storage doesn't provide the same guarantees as the device's file system. Browsers can just decide to delete all the app's data under certain conditions. If the user has been online and has work that didn't have a chance to get pushed to the server, that work would be lost in such a case. Again, this problem is not unique to Replicache and affects all web apps that support offline mode, and based on what I read, it is unlikely to affect most users. It's just something to keep in mind. ``` ``` - I was surprised to see that the **schema in the backend database** in the Todo example I ported doesn't have the "proper" relational definitions I would expect from a SQL database. There is no "items" table with fields for "id", "text", or "completed". The reason I would want that to exist is the same reason I want a relational database in the first place—to be able to easily slice and dice the data in my system (which I always missed down the line when I didn't have). I don't think it is a major concern since Replicache is supposed to be backend-agnostic as long as the protocol is implemented according to spec. I might try to refactor the database as a follow-up exercise to see what that means in terms of complexity and ergonomics. ``` ``` - I find **version history and undo/redo** super useful and desirable in apps with user-editable content. With regards to undo/redo there is an [official package](https://github.com/rocicorp/undo) but it seems to [lack support for the multiplayer usecase](https://github.com/rocicorp/replicache/issues/1008) (which is where the problems come from). As for version-history, the Replicache documentation mentions "the concept of history" but [suggests talking to them](https://doc.replicache.dev/concepts/offline) if the need arises. That makes me think it might not be straightforward to achieve. Another idea for a follow-up task. ``` ``` - **Collaborative text editing** - the existing conflict resolution approach won't work well for collaborative text editing, which requires [CRDTs](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type) or [OT](https://en.wikipedia.org/wiki/Operational_transformation). I wonder how easy it would be to integrate Replicache with something like [Yjs](https://yjs.dev/). There is an [official example repo](https://github.com/rocicorp/replicache-yjs), but I haven't looked into it yet. ``` - **縮放相關:** ``` - Since the server is stateful (holds open HTTP connections for server-sent events), I wonder how well it would scale. I've worked on production systems with >100k users that used WebSockets before, so I know it is not that big of a deal, but still something to think about. ``` - **其他:** ``` - - In theory, Replicache can be **added into existing apps** without rewriting the frontend (as long as the app already uses a similar store). The backend might be trickier. If your database doesn't support snapshot isolation, you are out of luck, and even if it does, the existing schema and your existing endpoints might need some serious rework. If you're going to use it, do it from day one (if you can). ``` ``` - Replicache is **not open source** (yet! see the point below) and is [free only as long as you're small or non-commercial](https://replicache.dev/#pricing). Given the amount of work (>2 years) that went into developing it and the quality of engineering on display, it seems fair. With that said, it makes adopting Replicache more of a commitment compared to picking up a free, open library. If you are a tier 2 and up paying customer, you get a [source license](https://doc.replicache.dev/howto/source-access) so that if Replicache shuts down for some reason, your app is safe. Another option is to roll out your own sync engine, like the big boys (Linear, Figma) have done, but getting to the quality and performance that Replicache offers would be anything but easy or quick. ``` ``` - **Crazy plot twist** (last minute edit): As I was about to publish this post I discovered that Replicache is going to be opened sourced in the near future and that its parent company is planning to launch a new sync-engine called "Zero". [Here is the official announcement](https://zerosync.dev/). It reads: "We will be open sourcing [Replicache](https://replicache.dev/) and [Reflect](https://reflect.net/). Once Zero is ready, we will encourage users to move." ``` ``` Ironically, Zero seems to be yet another solution that automagically syncs the backend database with the frontend database, which at least for me personally seems less attractive (because I want separation of concerns and control). With that said, these guys are experts in this domain and I am just a dude on the internet so we'll have to wait and see. In the meanwhile, I plan on playing with Replicache some more. ``` 同步引擎應該用於所有事情嗎? -------------- 不,同步引擎不應該用於所有事情。好訊息是,您可以讓應用程式的某些部分使用它,而其他部分仍然以傳統方式提交表單並等待伺服器的回應。 SvelteKit 和其他全端框架使這種整合變得容易。 使用同步引擎的明顯情況是一個壞主意: 1. 只有當客戶端更改很可能成功(回滾很少)並且客戶端擁有足夠的資訊來預測結果時,樂觀更新才有意義。例如,在線上測驗中,學生的答案必須傳送到伺服器進行評分,樂觀更新(因此同步引擎)是不可行的。這同樣適用於下訂單或交易股票等關鍵操作。一個好的經驗法則是,任何依賴伺服器且無法離線運作的操作都不應該依賴同步引擎。 2. 任何處理無法安裝在使用者電腦上的龐大資料集的應用程式。例如,建立本地優先版本的 Google 或處理千兆位元組資料以產生結果的分析工具是不切實際的。然而,在部分同步就足夠的情況下,同步引擎仍然是有益的。例如,Google地圖可以在客戶端裝置上下載和快取地圖以進行離線操作,而無需始終提供全球每個位置的高解析度地圖。 關於開發人員生產力和 DX 的一句話 ------------------ 我的印像是,擁有同步引擎可以讓 DX(開發人員體驗)變得更好。前端工程師只需與普通商店合作即可訂閱更新,並且 UI 始終保持最新狀態。無需考慮為同步引擎控制的應用程式部分取得任何內容、呼叫 API 或伺服器操作。至於後端,我還不能說太多。看起來它不會比傳統後端難,但我不能肯定。 ### 結束語 令人興奮的是,將網路應用程式的未來想像為全球範圍內的即時多人協作工具,無論網路條件如何,都可以可靠地工作,同時解決這些令人討厭的問題,我以過去的事情開始這篇文章。 我強烈建議網頁開發人員熟悉這些新概念,嘗試它們,甚至做出貢獻。 謝謝閱讀。如果您有任何問題或想法,請發表評論。和平。 。 **聚苯乙烯** 建立 Replicache 公司的創辦人 Aaron Boodman 的[訪談](https://youtu.be/cgTIsTWoNkM?si=Sssrbj09Z936QxEf)非常棒。觀看並稍後感謝我。 --- 原文出處:https://dev.to/isaachagoel/are-sync-engines-the-future-of-web-applications-1bbi

  近期留言