🔍 搜尋結果:ul

🔍 搜尋結果:ul

2024 年您需要了解的免費 API

[![給我買一杯咖啡](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://buymeacoffee.com/dk119819) 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)); ``` ### 防暴遊戲 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 -------- ### 不和諧 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)); ``` ### 鬆弛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)); ``` ### 叫喊 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://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://buymeacoffee.com/dk119819) --- 原文出處:https://dev.to/raajaryan/free-apis-you-need-to-know-about-in-2024-2ieg

我正在尋找 FullStack 軟體開發人員職位

嘿,大家,希望你們一直做得很好並且感覺很好!我叫 Cherry Ramatis,目前正在尋找成為 FullStack 軟體開發人員的機會。 我熱衷於學習新事物並成為社區中的積極人物以實現知識民主化,因為我發現這是成為更好的專業人士並同時認識很酷的人(雙贏)的關鍵。我透過參加聚會、發表演講、為初級和中級開發人員提供指導、撰寫友好而足智多謀的文章以及總體上成為一個對任何人都平易近人且樂於助人的人物來做到這一點。 就我個人而言,我有三隻漂亮的狗,我喜歡在海灘上散步,也喜歡和朋友一起去卡拉 OK 酒吧(這是享受涼爽快樂時光的好機會👀) 稍微了解一下我 ------- - **名稱:**櫻桃拉馬蒂斯 - **目前居住地:**巴西聖保羅 - **我在專業領域中積極使用的技術:** - 打字稿/Javascript - 反應 - 下一個 - 角 - 承載者 - 碼頭工人 - Github 操作 - PostgreSQL - MongoDB - **我願意使用的技術:** - 紅寶石 - 紅寶石 on Rails - 靈丹妙藥 - 鳳凰 - **時間編碼總計:**約10年 - **專業時間編碼:**目前我已工作 6 年 - **線上和現場進行的演講數量:** - 在[He4rt 開發者](https://discord.gg/he4rt)社群進行了 3 場線上演講 - 在[ElixirDays](https://x.com/elaine_nw/status/1795459111678570643)發表 1 場面對面演講 - **發表文章數量:**目前發表文章21篇,瀏覽量約6.7萬,接觸人數達1.1萬 我引以為傲的成就 -------- - **參與巴西播客「Elixir em Foco」:** https://www.youtube.com/watch?v=zYl6ec4G4k8 - **被 dev.to 評為 2023 年排名前 7 位的作者之一:** https://dev.to/devteam/top-7s-top-authors-of-the-year-120m - **對大型資料庫公司的開源貢獻:** https://cloud-getting-started.scylladb.com/stable/build-with-ruby 我最喜歡的專案 ------- - **Regexer - 從單行語言到正規表示式的編譯器:** https://github.com/cherryramatisdev/regexer - **使用 Ruby 進行依賴注入的 HTTP 伺服器模組化架構:** https://github.com/cherryramatisdev/api-with-dry-ruby - **rust 和 elixir 中從偽語言到有效字節碼 BEAM 檔案的編譯器:** https://github.com/cherryramatisdev/beam\_studies - **使用 ruby 將異常轉換為結果單子的實驗:** https://github.com/cherryramatisdev/monadic-exceptions 你如何聯絡我 ------ - **領英:** https://www.linkedin.com/in/cherryramatis/ - **推特:** https://x.com/cherryramatis - **開發者:** https://dev.to/cherryramatis --- 原文出處:https://dev.to/cherryramatis/im-looking-for-a-fullstack-software-developer-role-417m

🔧 進階 JavaScript 效能優化:技術與模式

隨著 JavaScript 應用程式變得越來越複雜,優化效能變得越來越重要。這篇文章深入探討了先進的技術和模式,以提高您的 JavaScript 效能並確保您的應用程式即使在重負載下也能順利執行。 🛠️記憶體管理 ------- 高效的記憶體管理是維持 JavaScript 應用程式效能的關鍵。糟糕的記憶體管理可能會導致洩漏和崩潰。 ### 提示:避免全域變數 盡量減少全域變數的使用,防止記憶體洩漏,確保更好的封裝。 ``` (function() { const localVariable = 'I am local'; console.log(localVariable); })(); ``` ### 提示:使用 WealMap 進行緩存 WeakMap 允許您快取物件而不阻止垃圾收集。 ``` const cache = new WeakMap(); function process(data) { if (!cache.has(data)) { const result = expensiveComputation(data); cache.set(data, result); } return cache.get(data); } function expensiveComputation(data) { // Simulate expensive computation return data * 2; } ``` 🌐 用於離線快取的 Service Worker ------------------------ Service Worker 可以透過快取資產和啟用離線功能來顯著提高效能。 ### 提示:實施基本 Service Worker 設定 Service Worker 來快取資產。 ``` // sw.js self.addEventListener('install', event => { event.waitUntil( caches.open('v1').then(cache => { return cache.addAll([ '/index.html', '/styles.css', '/script.js', '/image.png' ]); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request).then(response => { return response || fetch(event.request); }) ); }); // Register the Service Worker if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(() => console.log('Service Worker registered')) .catch(error => console.error('Service Worker registration failed', error)); } ``` 📊 用於效能密集型任務的 WebAssembly ------------------------ WebAssembly (Wasm) 是一種允許高效能程式碼執行的二進位指令格式。 ### 提示:使用 WebAssembly 進行繁重運算 將應用程式的效能關鍵部分編譯到 WebAssembly。 ``` // C code (example.c) #include <emscripten.h> EMSCRIPTEN_KEEPALIVE int add(int a, int b) { return a + b; } // Compile to WebAssembly // emcc example.c -o example.js -s EXPORTED_FUNCTIONS="['_add']" // JavaScript fetch('example.wasm').then(response => response.arrayBuffer() ).then(bytes => WebAssembly.instantiate(bytes, {}) ).then(results => { const add = results.instance.exports.add; console.log(add(2, 3)); // 5 }); ``` 🎛️ 用於多執行緒的 Web Worker --------------------- Web Workers 可讓您在背景執行緒中執行腳本,從而在 JavaScript 中啟用多執行緒。 ### 提示:將密集型任務分擔給 Web Worker 將繁重的計算移至 Web Worker 以保持主執行緒回應。 ``` // worker.js self.onmessage = (event) => { const result = performHeavyComputation(event.data); self.postMessage(result); }; function performHeavyComputation(data) { // Simulate heavy computation return data.split('').reverse().join(''); } // main.js const worker = new Worker('worker.js'); worker.postMessage('Hello, Web Worker!'); worker.onmessage = (event) => { console.log('Result from Worker:', event.data); }; ``` 🚀 優化 React 應用程式 --------------- React 很強大,但對於大型應用程式來說它可能會變得很慢。優化 React 效能對於無縫用戶體驗至關重要。 ### 提示:使用`React.memo`和`useMemo`進行記憶 使用`React.memo`來防止功能元件不必要的重新渲染。 ``` const ExpensiveComponent = React.memo(({ data }) => { // Expensive operations here return <div>{data}</div>; }); ``` 使用 useMemo 來記憶昂貴的計算。 ``` const MyComponent = ({ items }) => { const total = useMemo(() => { return items.reduce((sum, item) => sum + item.value, 0); }, [items]); return <div>Total: {total}</div>; }; ``` ### 提示:使用`React.lazy`和 Suspense 進行程式碼分割 拆分程式碼以僅在需要時載入元件。 ``` const LazyComponent = React.lazy(() => import('./LazyComponent')); const MyComponent = () => ( <React.Suspense fallback={<div>Loading...</div>}> <LazyComponent /> </React.Suspense> ); ``` ⚙️ 使用高效率的資料結構 ------------- 選擇正確的資料結構會對效能產生重大影響。 ### 提示:使用映射進行快速鍵值查找 與物件相比,映射為頻繁加入和查找提供了更好的效能。 ``` const map = new Map(); map.set('key1', 'value1'); console.log(map.get('key1')); // value1 ``` ### 提示:使用集合進行快速唯一值存儲 集合提供了一種儲存唯一值的高效能方法。 ``` const set = new Set([1, 2, 3, 4, 4]); console.log(set.has(4)); // true console.log(set.size); // 4 ``` 結論 -- 進階 JavaScript 效能優化需要深入了解該語言及其生態系統。透過有效管理記憶體、利用 Service Workers、使用 WebAssembly 執行運算任務、將工作卸載給 Web Workers、優化 React 應用程式以及選擇高效的資料結構,您可以建立提供卓越使用者體驗的高效能 JavaScript 應用程式。 不斷探索和試驗這些技術,以釋放 JavaScript 的全部潛力。快樂編碼! 🚀 --- 原文出處:https://dev.to/parthchovatiya/advanced-javascript-performance-optimization-techniques-and-patterns-26g0

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

探索 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

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

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

乾淨的程式碼是每個成功的軟體專案的基石。作為開發人員,編寫乾淨、可維護的程式碼的能力對於應用程式的效率和壽命至關重要。在本文中,我們將深入研究 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

如何在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

少寫,永不修復:高度可靠程式碼的藝術

![被燒壞的工程師](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aygtgwad96xzq2pr944q.gif) 如果您是開發人員,不知疲倦地推出新的更改,卻被過去工作中的錯誤拖了回來,那麼這篇文章對您來說非常重要。 在過去的十年裡,在軟體開發中,我犯過並且看到其他人反覆犯過的關鍵錯誤之一是專注於做更多的工作,而不是確保完成的工作(無論多小)是穩健的並且將繼續正常工作。這些重複出現的錯誤會嚴重影響生產力和積極性。 從我自己的錯誤中,我學到了寶貴的教訓。在這裡,我想分享一些策略,它們不僅可以幫助您**交付強大的軟體**,還可以**讓您擺脫過去工作的束縛**。 ![告訴我更多](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a85h4md8p9xwd1ooq7zc.gif) 我們將討論對我最有效的 5 個策略: 1. [計劃 10 倍](#1-plan-for-10x) 2. [附註:您的舊工作出現錯誤,正在召回您](#2-psst-your-old-work-got-a-bug-and-is-calling-you-back) 3. [讓系統為您服務,而不是相反](#3-make-the-systems-work-for-you-not-the-other-way-around) 4. [始終用連結回答](#4-always-answer-with-a-link) 5. [了解軟體建置是一項團隊運動](#5-understand-software-building-is-a-team-sport)。 1. 10 次計劃 --------- 恕我直言,工程師有兩種:為今天而奮鬥的工程師和為遙遠的未來而設計的工程師。這兩種方法本身都不可持續。 您的程式碼應該能夠應對您的業務即將經歷的成長。然而,針對未來挑戰的過度設計可能會導致不必要的複雜性。有一個專門的術語 -[自行車脫落](https://thedecisionlab.com/biases/bikeshedding) ![擴大](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/edi9uv0o8bxjg58qr0wm.gif) 這是我的實用經驗法則:規劃目前規模的 10 倍,或考慮您的業務在未來 2-3 年內預計會成長多少。確保您的計劃與您的業務目標保持一致。 例如,如果您是一家設計預訂模組的計程車公司,現在您的公司每天處理 10,000 次乘車,並預計在 2 年內達到每天 100,000 次乘車,請以此作為基準。當您只進行 10,000 次騎行時,設計一個每天可進行 1000 萬次騎行的系統可能會導致解決方案過於複雜和昂貴。 2. 噓:您的舊工作出現了錯誤,正在召回您 --------------------- ![系統損壞](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/csf7rulcx55smffdqyyi.gif) 「幾天甚至幾週的除錯可以節省你編寫測試的幾個小時」——明智的人。 在不測試所有邊緣情況的情況下發布程式碼就像噴霧和祈禱策略。確保程式碼按預期工作的最簡單方法是新增單元測試。這聽起來似乎是顯而易見的,但徹底測試的重要性怎麼強調也不為過。 單元測試不僅充當針對明顯錯誤的第一道防線,而且還可以作為程式碼的保險,防止可能違反業務需求的意外更改。因此,減少每個衝刺分配給您的臨時錯誤 😉 **懶人(像我)的一個技巧**:在寫程式之前: - 編寫涵蓋您能想到的每個極端情況的測試。 - 假裝你正試圖破壞別人的系統。 - 在所有測試中編寫斷言 False 並執行它們。 - 當然,所有測試都會失敗。 現在,只需努力讓每個測試通過即可。這種方法總體上花費的時間較少,每次都會產生健壯的程式碼! 3. 讓系統為你服務,而不是相反 ---------------- ![監控系統](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8teb74yr1dgfq2tpolxf.gif) 我的一位經理曾經給了我最有影響力的建議:“採取行動,不要做出反應。”當我不斷在不同的 Slack 頻道上因問題、客戶投訴和付款失敗而被標記時,我提出了這個建議。我只是對每個請求做出反應,不知道接下來會發生什麼。 從那時起,我開始對我建造的每個功能提出三個問題: - 我怎麼知道它正在工作? - 我怎麼知道它失敗了? - 我怎麼知道它成功了? 然後,我透過將指標傳送到我們的 APM 工具(例如 Datadog 或 NewRelic)來回答各個層級(功能、螢幕、應用程式)的這些問題。 ![APM樣本](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8werj18bl8p6zhwc61d.png) 設定完畢後,我配置了警報,以便在出現任何問題時通知我。 透過這樣做,我在錯誤升級為重大問題之前就意識到了它們,從而防止了反應性措施、糟糕的客戶體驗以及我自己對接下來可能發生的事情的不確定性。 每次建造一些東西時,就開始回答這三個基本問題,以確保您始終採取行動而不是做出反應。 4. 總是用連結來回答 ----------- ![回覆文件](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e8utxvlj2pt1ojjq7kk8.gif) 就像糟糕的工作會讓你在各種 Slack 頻道上進行修復一樣,出色的工作會讓你在你所從事的領域中被貼上上下文標籤。 這可能會在你最意想不到的時候耗盡你的精力,或者更糟的是,它可能會讓你成為執行相同任務的首選人選,因為你了解完整的情況。 **請保留這個秘密技巧:** 記錄一切。包括您在建立功能時所做的上下文、架構和特定於業務的決策。當有人詢問某個區域的上下文(功能、螢幕、應用程式)時,只需向他們發送更新文件的連結即可。這每次都會為您節省幾個小時。 此外,完整的文件使新團隊成員的入職變得更加容易,並確保您的工作隨著時間的推移仍然可以存取和理解。 5. 了解軟體建置是一項團隊運動。 ----------------- ![特德·拉索欣賞](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/witndxix4fs05xy3fjie.gif) 軟體工程通常強調個人貢獻者路徑。然而,單獨實現最終目標是不可能的——你只能與你的團隊一起實現它(反之亦然)。 理解並採用流程卓越的思維方式可以幫助您充分利用團隊的集體生產力。 ![使困惑](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iwk1ubf1tcuq8wio2v7x.gif) 對於這樣的措詞表示抱歉😄 簡而言之,確保審查、部署和任何涉及程式碼的協作活動不會有很長的等待時間,這可以大大提高您的工作效率! 辨識團隊中長時間等待或阻塞時間的最佳方法是衡量 DORA 指標。您可以使用像[Middleware](https://github.com/middlewarehq/middleware)這樣的開源工具,它提供開箱即用的[DORA 指標](https://www.middlewarehq.com/blog/what-are-dora-metrics-how-they-can-help-your-software-delivery-process)。 {% 嵌入 https://github.com/middlewarehq/middleware %} PS:我也是[Middleware](https://middlewarehq.com)的共同創辦人,我們的使命是讓工程師的工程變得順暢。如果您喜歡我們所建造的內容,請考慮給我們一顆星星! 像老闆一樣發布程式碼! ----------- ![老闆人](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2qrf8s8gmb9cx5f8b6f.gif) 透過採用這些建議,您可以大幅減少重新審視和修復過去工作所花費的時間。這不僅可以提高您的工作效率,還可以確保您始終專注於創新和提供新功能。 保持高效,而不是忙碌!祝一切順利😊 --- 原文出處:https://dev.to/middleware/write-less-fix-never-the-art-of-highly-reliable-code-5a0i

使用 Gemini API 和 ToolJet 在 10 分鐘內建立人工智慧商業提案編寫器 🚀

在本教學中,我們將引導您完成使用 ToolJet 和 Gemini API 建立 AI 商業提案編寫器的流程。我們將利用 ToolJet 的預先建置元件和簡單的整合流程來快速建立一個可以與 Gemini API 互動的應用程式。該應用程式將允許用戶輸入業務詳細資訊並產生專業的業務提案。 以下是最終應用程式的預覽: ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rghughfkz183bzjtqpou.png) ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ewcpalt0obyfkvdh68xr.png) --- 先決條件 ---- **Gemini API 金鑰**:Gemini API 是[Google AI Studio](https://aistudio.google.com/app/apikey)提供的進階 AI 服務。它使開發人員能夠將強大的內容生成功能整合到他們的應用程式中。 **ToolJet** (https://github.com/ToolJet/ToolJet):一個開源、低程式碼的商業應用程式建構器。[註冊](https://www.tooljet.com/signup)免費的 ToolJet 雲端帳號或使用 Docker[在本機上執行 ToolJet](https://docs.tooljet.com/docs/setup/try-tooljet/) 。 首先建立一個名為*Business Proposal Writer 的*應用程式。 --- 1. 建立一個新應用程式 ------------ - 打開 ToolJet 並點擊**“建立新應用程式”** 。 - 將您的應用程式命名為*Business Proposal Writer* 。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5faoqkb5ab9ydfpbjt0n.png) 建立新應用程式後,您將看到一個空白畫布,右側有一個元件庫,底部有一個查詢面板。 --- 2. 設計使用者介面 ---------- 將以下元件拖曳到畫布上: - **容器**:組織標題、輸入欄位和輸出部分。 - **文字和文字輸入**:用於公司名稱、服務描述、預算、截止日期和公司專業知識。 - **按鈕**:產生提案。 - **文字**:以 HTML 格式顯示產生的提案。 - **圖示**:用於徽標並使 UI 更具吸引力。 為了清楚起見,重新命名輸入欄位: - `companyNameInput` - `serviceDescriptionInput` - `budgetInput` - `deadlineInput` - `companyExpertiseInput` 將按鈕命名為`createButton` 。 命名將把產生的提案顯示為`output`的文字元件。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dki3r05jwejzr62mlbws.png) *ToolJet 的預先建置[元件](https://docs.tooljet.com/docs/tooljet-concepts/what-are-components)在功能和樣式自訂方面提供了完全的靈活性。* --- 3. 透過查詢與Gemini API集成 -------------------- - 建立一個[工作區常數](https://docs.tooljet.com/docs/tooljet-concepts/workspace-constants/)來保存您的 Gemini API 金鑰。將其命名為`GEMINI_API_KEY` 。 - 展開查詢面板,建立一個新查詢,並命名為`generateProposal` 。 - 將請求方法變更為`POST`並將以下 URL 貼到 URL 輸入下: `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent?key={{constants.GEMINI\_API\_KEY}} ` - 導航到`getContent`查詢的正文部分。切換到原始 JSON 並輸入以下程式碼: ``` { "contents": [ { "parts": [ { "text": " 1. **Client/Company Name:** {{components.companyNameInput.value}} 2. **Project/Service Description:** {{components.serviceDescriptionInput.value}} 3. **Budget Range (if applicable):** {{components.budgetInput.value}} 4. **Deadline:** {{components.deadlineInput.value}} 5. **Company Expertise:** {{components.companyExpertiseInput.value}} Based on these inputs, generate a well-structured and comprehensive business proposal document in HTML format. The generated proposal should include the following sections, each with ample padding and spacing: 1. **Executive Summary** 2. **Company Overview and Qualifications** 3. **Project Understanding and Approach** 4. **Proposed Solution and Methodology** 5. **Timeline and Deliverables** 6. **Team Structure and Bios** 7. **Cost Breakdown and Budget** (Include charts as needed) 8. **Terms and Conditions** 9. **Conclusion and Call to Action** Ensure that the HTML output is properly formatted and visually appealing." } ] } ] } ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71f02ensa53tr3g6ponl.png) *ToolJet 中的[查詢](https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries)提供了一種連接[資料庫、API 和雲端儲存服務的](https://docs.tooljet.com/docs/tooljet-concepts/what-are-datasources)簡單方法。* --- 4. 將 UI 元件與查詢連接 --------------- - 選擇`createButton`元件。 - 新增事件處理程序以在點擊按鈕時觸發`generateProposal`查詢。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cuayj8aq73tdg0zbhrc.png) *事件用於執行查詢、顯示警報以及基於觸發器(例如按鈕單擊或查詢完成)的其他功能。* - 選擇為顯示查詢輸出而建立的文字元件。 - 在其 Data 屬性下,輸入以下程式碼: `{{queries.generateProposal.data.candidates[0].content.parts[0].text}}` 現在,在輸入欄位中輸入所需的詳細訊息,然後按一下按鈕。您應該在輸出元件中看到產生的業務提案。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jjzuk15d30x9036nyhki.png) ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xyfbp9ltgyn1zqmsezsu.png) --- 結論 -- 您已在短短 10 分鐘內使用 Gemini API 和 ToolJet 成功建立了一個商業提案編寫器。該工具將簡化專業商業提案的建立,節省您的時間和精力。如有任何問題或支持,請加入[ToolJet Slack 社群](https://join.slack.com/t/tooljet/shared_invite/zt-2l2i9tuls-NNCZPBlPAi2flYIhrjBqHA)。您也可以查看[ToolJet 文件](https://docs.tooljet.com/docs/)以了解更多資訊。 --- 原文出處:https://dev.to/tooljet/build-an-ai-business-proposal-writer-using-gemini-api-and-tooljet-in-10-minutes-4j3j

只需 2GB 記憶體即可將後端擴展到 1M 請求 ⚡️

本部落格介紹了我如何解鎖效能,使我能夠在最少的資源(2 GB RAM 1v CPU 和最小網路頻寬 50-100 Mbps)上將後端從 50K 請求擴展到 1M 請求(~16K 請求/分鐘)。 ![迷因](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0m1kiuyq575f2qzyweu.png) 它將帶你踏上一段與過去的自己的旅程。這可能是一段漫長的旅程,所以請繫緊安全帶,享受這段旅程! 🎢 *它假設您熟悉後端和編寫 API。如果你了解一點 Go,這也是一個優勢。如果你不這樣做,也沒關係。您仍然可以按照我提供的資源來幫助您理解每個主題。 (如果您不知道 GO,這裡有一個*[*快速介紹*](https://www.youtube.com/watch?v=446E-r0rXHI)*)* 長話短說;博士, 首先,我們建立一個[可觀察性管道](https://www.observo.ai/post/what-is-an-observability-pipeline),幫助我們監控後端的所有面向。然後,我們開始對後端進行壓力測試,直到斷點測試(當一切最終崩潰時)。 →[連接輪詢以避免達到最大連接閾值](#optimization-1-connection-pooling-️) →[實施資源限制以避免非關鍵服務佔用資源](#optimization-2-unblocking-resources-from-alloy-open-telemetry-collector) →[新增索引](#optimization-3-adding-indexes-🏎️) →[禁用隱式事務](#optimization-4-ensure-while-testing-there-is-no-blocking-transaction) →[增加 Linux 的最大檔案描述符限制](#optimization-6-increasing-the-max-file-descriptor-limit) →[限制 Goroutines](#optimization-7-avoid-overloading-goroutines) →[未來計劃](#next-steps) 後端簡介🤝 ----- 讓我簡單介紹一下後端, - 它是一個用 Golang 寫的整體 RESTful API。 - 使用[GIN](https://github.com/gin-gonic/gin)框架編寫,並使用[GORM](https://gorm.io/)作為[ORM](https://www.theserverside.com/definition/object-relational-mapping-ORM) 。 - 使用 Aurora Postgres 作為託管在 AWS RDS 上的唯一主資料庫。 - 後端是[Docker 化的](https://dev.to/documatic/how-to-dockerize-your-application-536i#:~:text=Dockerizing%20an%20application%20is%20the,for%20developers%20and%20organizations%20alike.),我們在 AWS 上的`t2.small`實例中執行它。它具有 2GB RAM、50-100mb/s 網路頻寬、1 個 vCPU。 - 後端提供身份驗證、CRUD 操作、推播通知和即時更新。 - 對於即時更新,我們打開一個非常輕量級的[Web 套接字連接](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API),通知設備實體已更新。 我們的應用程式主要是讀取密集型,具有下降的寫入活動,如果我必須給它一個比率,它將是 65% 讀取/35% 寫入。 我可以寫一篇單獨的部落格來解釋我們為什麼選擇 - 整體架構、golang 或 postgress,但為了向您介紹[MsquareLabs 的](www.msquarelabs.com)tl;dr,我們相信「保持簡單,並建立允許我們以驚人的快節奏前進的程式碼。 資料資料資料🙊 ------- 在進行任何模擬負載生成之前,我首先將可觀察性建置到我們的後端中。其中包括追蹤、指標、分析和日誌。這使得找到問題並準確地找出造成疼痛的原因變得非常容易。當您對後端擁有如此強大的監控能力時,您也可以更輕鬆地更快地追蹤生產問題。 在我們繼續之前,讓我先簡單介紹一下指標、分析、日誌和追蹤: - 日誌:我們都知道日誌是什麼,它只是我們在事件發生時建立的大量文字訊息。 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/94b2970c-34fc-4135-bed0-bf763ef098c8) - 追蹤:這是高度可見性的結構化日誌,有助於我們以正確的順序和時間封裝事件。 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/9ee944e8-0637-4aa9-b076-5ff35990a8e2) - 指標:所有數字攪動資料,例如 CPU 使用率、活動請求和活動 goroutine。 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/ec9a493d-6344-4c10-80e6-0db8c5c1d219) - 分析:為我們提供程式碼的即時指標及其對機器的影響,幫助我們了解正在發生的情況。 (WIP,下一篇部落格會詳細講) 要了解有關我如何將可觀察性建置到後端的更多訊息,您可以研究下一個博客(WIP),我將此部分移至另一個博客,因為我想避免讀者不知所措並只關註一件事 -**優化**) 這就是追蹤、日誌和指標的視覺化的樣子, ![截圖 2024-05-30 下午 4.53.29.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/20883b44-6f0f-42a1-b4f0-ae6ac2c04642) 所以現在我們有一個強大的監控管道+一個像樣的儀表板作為開始🚀 嘲笑高級用戶 x 100,000 🤺 ------------------ 現在真正的樂趣開始了,我們開始嘲笑愛上該應用程式的用戶。 「只有當你把你的愛(後端)置於極大的壓力時,你才會發現它的真正本質✨」 - 某個偉大的人,哈哈,idk Grafana 還提供了一個負載測試工具,因此我決定使用它,因為它只需要幾行程式碼的最少設置,因此您已經準備好了模擬服務。 我沒有觸及所有 API 路線,而是專注於最關鍵的路線,這些路線負責我們 90% 的流量。 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/e42d706f-fc61-4cdd-8b0e-35113761f09c) 關於[k6](https://k6.io)的簡單介紹,它是一個基於 javascript 和 golang 的測試工具,您可以在其中快速定義要模擬的行為,它負責對其進行負載測試。無論您在主函數中定義什麼,都稱為*迭代*,k6 會啟動多個虛擬使用者單元(VU)來處理此迭代,直到達到給定的週期或迭代計數。 每次迭代構成4個請求,建立任務→更新任務→取得任務→刪除任務 ![iLoveIMG 下載 (1).jpg](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/32cb71fb-d549-48c9-88a0-ecaf48296593/c7dcc3cb-4128-44d4-b3ad-e736c96e377b) 慢慢開始,讓我們看看大約 10K 請求 → 100 VU 和 30 iter → 3000 iters x 4reqs → 12K 請求情況如何 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/84f31eec-79d5-49f9-915f-bb97b6d5f517) 這是輕而易舉的事情,沒有任何記憶體洩漏、CPU 過載或任何類型瓶頸的跡象,萬歲! 這是 k6 的摘要,發送了 13MB 資料,接收了 89MB,平均超過 52 req/s,平均延遲為 278ms,考慮到所有這些都在單台機器上執行,這還不錯。 ``` checks.........................: 100.00% ✓ 12001 ✗ 0 data_received..................: 89 MB 193 kB/s data_sent......................: 13 MB 27 kB/s http_req_blocked...............: avg=6.38ms min=0s med=6µs max=1.54s p(90)=11µs p(95)=14µs http_req_connecting............: avg=2.99ms min=0s med=0s max=536.44ms p(90)=0s p(95)=0s ✗ http_req_duration..............: avg=1.74s min=201.48ms med=278.15ms max=16.76s p(90)=9.05s p(95)=13.76s { expected_response:true }...: avg=1.74s min=201.48ms med=278.15ms max=16.76s p(90)=9.05s p(95)=13.76s ✓ http_req_failed................: 0.00% ✓ 0 ✗ 24001 http_req_receiving.............: avg=11.21ms min=10µs med=94µs max=2.18s p(90)=294µs p(95)=2.04ms http_req_sending...............: avg=43.3µs min=3µs med=32µs max=13.16ms p(90)=67µs p(95)=78µs http_req_tls_handshaking.......: avg=3.32ms min=0s med=0s max=678.69ms p(90)=0s p(95)=0s http_req_waiting...............: avg=1.73s min=201.36ms med=278.04ms max=15.74s p(90)=8.99s p(95)=13.7s http_reqs......................: 24001 52.095672/s iteration_duration.............: avg=14.48s min=1.77s med=16.04s max=21.39s p(90)=17.31s p(95)=18.88s iterations.....................: 3000 6.511688/s vus............................: 1 min=0 max=100 vus_max........................: 100 min=100 max=100 running (07m40.7s), 000/100 VUs, 3000 complete and 0 interrupted iterations _10k_v_hits ✓ [======================================] 100 VUs 07m38.9s/20m0s 3000/3000 iters, 30 per VU ``` 讓我們增加 12K → 100K 請求,發送 66MB,接收 462MB,CPU 使用率峰值達到 60%,記憶體使用率達到 50%,執行需要 40 分鐘(平均 2500 個請求/分鐘) ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/838e351e-ac9e-47a1-af51-4f69f75f5de0) 一切看起來都很好,直到我在日誌中看到一些奇怪的東西,“::gorm: 連接太多::”,快速檢查RDS 指標,確認打開的連接已達到410,即最大打開連接的限制。它是由 Aurora Postgres 本身[根據實例的可用記憶體](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Managing.html#AuroraPostgreSQL.Managing.MaxConnections)設定的。 您可以透過以下方法檢查, `select * from pg_settings where name='max_connections';` ⇒ 410 Postgres 為每個連接產生一個進程,考慮到它會在新請求到來時打開一個新連接並且之前的查詢仍在執行,因此這是極其昂貴的。因此 postgress 對可以開啟的並發連線數進行了限制。一旦達到限制,它會阻止任何進一步連接資料庫的嘗試,以避免實例崩潰(這可能會導致資料遺失) ### 優化一:連接池⚡️ 連接池是一種管理資料庫連接的技術,它重用打開的連接並確保它不會超過閾值,如果客戶端請求連接並且超過最大連接限制,它會等待直到連接被釋放或拒絕該請求。 這裡有兩個選項,要么執行客戶端池,要么使用單獨的服務,例如[pgBouncer](pgbouncer.org) (充當代理)。當我們規模較大且我們有連接到相同資料庫的分散式架構時,pgBouncer 確實是一個更好的選擇。因此,為了簡單性和我們的核心價值觀,我們選擇繼續進行客戶端池化。 幸運的是,我們使用的 ORM GORM 支援連接池,但[在幕後使用資料庫/SQL](https://gorm.io/docs/connecting_to_the_database.html#Connection-Pool) (golang 標準套件)來處理它。 有一些非常簡單的方法可以處理這個問題, ``` configSQLDriver, err := db.DB() if err != nil { log.Fatal(err) } configSQLDriver.SetMaxIdleConns(300) configSQLDriver.SetMaxOpenConns(380) // kept a few connections as buffer for developers configSQLDriver.SetConnMaxIdleTime(30 * time.Minute) configSQLDriver.SetConnMaxLifetime(time.Hour) ``` - `SetMaxIdleConns` → 保留在記憶體中的最大空閒連接,以便我們可以重複使用它(有助於減少開啟連接的延遲和成本) - `SetConnMaxIdleTime` → 我們應該在記憶體中保留空閒連接的最長時間。 - `SetMaxOpenConns` → 與資料庫的最大開啟連接,因為我們在同一個 RDS 實例上執行兩個環境 - `SetConnMaxLifetime` → 任何連線保持開啟的最長時間 現在更進一步,500K 請求(4000 個請求/分鐘)和 20 分鐘伺服器崩潰💥,最後讓我們調查一下🔎 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/39787835-b83d-441a-a3aa-a3b9fb03fc26) 快速查看指標,然後砰! CPU 和記憶體使用量激增。 Alloy(開放遙測收集器)佔用了所有 CPU 和內存,而不是我們的 API 容器。 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/e8e764e4-31ea-44fa-b930-1bd1746d131b) ### 優化二:合金資源解鎖(開放式遙測收集器) 我們在小型 t2 實例中執行三個容器, - API開發 - API 分期 - 合金 當我們將大量負載轉儲到 DEV 伺服器時,它開始以相同的速率產生日誌和跟踪,從而呈指數級增加 CPU 使用率和網路出口。 因此,確保合金容器不會超出資源限制並妨礙關鍵服務非常重要。 由於合金在 docker 容器內執行,因此更容易強制執行此約束, ``` resources: limits: cpus: '0.5' memory: 400M ``` 此外,這次日誌不為空,存在多個上下文取消錯誤 - 原因是請求逾時,並且連接突然關閉。 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/ace0ce7e-990e-43ea-a871-dc18888e3968) 然後我檢查了延遲,這太瘋狂了 😲 經過一段時間後,平均延遲為 30 - 40 秒。多虧了跟踪,我現在可以準確地找出是什麼導致瞭如此巨大的延遲。 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/04be9892-5791-4834-b418-e9f417c0781d) 我們在 GET 操作中的查詢非常慢,讓我們對查詢執行[`EXPLAIN ANALYZE`](https://www.postgresql.org/docs/current/sql-explain.html) , ![截圖 2024-06-11 9.55.10 PM.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/3cf82d23-53c5-4976-aacc-2fa0d6ab2353) LEFT JOIN 花了 14.6 秒,而 LIMIT 又花了 14.6 秒,我們如何優化它 - INDEXING ### 優化3:新增索引🏎️ 為`where`或`ordering`子句中常用的欄位新增索引可以將查詢效能提高五倍。在新增 LEFT JOIN 表和 ORDER 欄位的索引後,相同查詢花費了 50 毫秒。你能從**14.6 秒 ⇒ 50 毫秒**開始思考嗎? (但要注意盲目加入索引,會導致CREATE/UPDATE/DELETE慢死) 它還可以更快地釋放連接,並有助於提高處理巨大並發負載的整體能力。 ### 最佳化 4:確保測試時沒有阻塞 TRANSACTION 🤡 從技術上講不是優化而是修復,您應該記住這一點。當您進行壓力測試時,您的程式碼不會嘗試同時更新/刪除相同實體。 在檢查程式碼時,我發現了一個錯誤,該錯誤導致每次請求時都會對用戶實體進行更新,並且當在事務內執行每個更新呼叫時,這會建立一個鎖,幾乎所有更新呼叫都被以前的更新呼叫阻止。 僅此一項修復就將吞吐量提高至 2 倍。 ### 最佳化5:跳過 GORM 的隱式 TRANSACTION 🎭 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/ab40af5b-c0fd-4c18-9067-859df56c4ec0) 預設情況下,GORM 在事務中執行每個查詢,這會降低效能,因為我們擁有極其強大的事務機制,在關鍵區域丟失事務的機會幾乎是不可能的(除非他們是實習生🤣)。 我們有一個中間件可以在到達模型層之前建立事務,並且有一個集中函數來確保控制器層中該事務的提交/回滾。 透過停用此功能,我們可以獲得[至少約 30% 的效能提升](https://gorm.io/docs/transactions.html#Disable-Default-Transaction)。 “我們卡在每分鐘 4-5K 請求的原因是這個,我認為這是我的筆記型電腦網路頻寬的問題。” - 愚蠢的我 所有這些優化帶來了 5 倍的吞吐量增益 💪,現在光是我的筆記型電腦就可以每分鐘產生 12K-18K 請求的流量。 ![截圖 2024-06-12 7.20.27 PM.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/fd440164-255f-4a4d-8389-c14365472372) ### 百萬點次數🐉 最後,每分鐘 10k-13K 請求達到 100 萬次,大約需要 2 小時,本來應該早點完成,但隨著合金重新啟動(由於資源限制),所有指標都會隨之丟失。 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/6561ab09-1eb6-4b6f-92f2-92b5b2818590) 令我驚訝的是,該時間段內的最大 CPU 使用率為 60%,而記憶體使用量僅為 150MB。 Golang 的效能如此之高且處理負載的能力如此出色,這真是太瘋狂了。它具有最小的記憶體佔用。就是愛上了 golang 💖 每個查詢需要 200-400 毫秒才能完成,下一步是找出為什麼需要這麼多時間,我的猜測是連接池和 IO 阻塞減慢了查詢速度。 平均延遲降至約 2 秒,但仍有很大改進空間。 隱式優化🕊️ ------ ### 優化6:增加最大檔案描述子限制🔋 當我們在 Linux 作業系統中執行後端時,我們打開的每個網路連線都會建立一個檔案描述符,預設為 Linux 將每個進程限制為 1024 個,這阻礙了它達到峰值效能。 當我們開啟多個 Web 套接字連線時,如果有大量並發流量,我們很容易就會達到此限制。 Docker compose 提供了一個很好的抽象, ``` ulimits: core: soft: -1 hard: -1 ``` ### 優化 7:避免 goroutine 過載 🤹 作為一個 Go 開發者,我們經常認為 Goroutine 是理所當然的,只是盲目地在 Goroutine 中執行許多非關鍵任務,我們在函數之前加入`go` ,然後忘記它的執行,但在極端情況下它可能會成為瓶頸。 為了確保它永遠不會成為我的瓶頸,對於經常在 goroutine 中執行的服務,我使用帶有 n-worker 的記憶體佇列來執行任務。 ![圖片.png](https://res.craft.do/user/full/66854ea9-b711-5e28-ddbd-8d28e1defc9f/doc/355f2532-e0ec-485f-97e2-472751298750/b00e6636-6b3f-472e-99fc-f6c66ee87186) 後續步驟🏃‍♀️ -------- ### 改進:從 t2 移動到 t3 或 t3a t2是老一代的AWS通用機器,而t3和t3a、t4g是新一代。它們是可突發的實例,與 t2 相比,它們為長時間的 CPU 使用提供更好的網路頻寬和更好的效能 了解突發實例, [AWS 引入了可突發執行個體](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances.html)類型,主要針對大多數時間不需要 100% CPU 的工作負載。因此,這些實例以基準效能 (20% - 30%) 運作。當您的實例不需要 CPU 時,他們會維護一個積分系統,它會累積積分。當 CPU 峰值發生時,它會使用該積分。這可以降低您的 AWS 運算成本和浪費。 t3a 將是一個值得堅持的好系列,因為它們的成本/效率比在可突發實例係列中好得多。 這是一個比較[t2 和 t3 的](https://www.cloudzero.com/advisor/t2-vs-t3/)不錯的部落格。 ### 改進:查詢 我們可以對查詢/模式進行許多改進來提高速度,其中一些是: - 在插入重型表中批量插入。 - 透過非規範化避免 LEFT JOIN - 快取層 - 著色和分區,但這要晚得多。 ### 改進:分析 釋放效能的下一步是啟用分析並弄清楚執行時到底發生了什麼。 ### 改進:斷點測試 為了發現我的伺服器的限制和容量,下一步是斷點測試。 ### 尾註👋 如果你讀到最後,你已經破解了,恭喜你🍻 這是我的第一篇博客,如果有不清楚的地方,或者您想更深入地了解該主題,請告訴我。在我的下一篇部落格中,我將深入研究分析,敬請關注。 您可以在[X](x.com/_rikenshah)上關注我,以獲取最新資訊:) --- 原文出處:https://dev.to/rikenshah/scaling-backend-to-1m-requests-with-just-2gb-ram-4m0c

如何使用 Ollama 和打開 WebUI 在本地執行 Llama 3

https://youtu.be/GT-Fwg124-I 我是 Llama 的忠實粉絲。 Meta 發布其 LLM 開源程式碼對整個科技界來說是一項淨收益,其寬鬆的許可證允許大多數中小型企業在幾乎沒有任何限制的情況下使用其 LLM(當然,在法律範圍內)。他們的最新版本是備受期待的 Llama 3。 Llama 3 有兩種大小:80 億和 700 億參數。這種模型經過大量文字資料的訓練,可用於各種任務,包括生成文字、翻譯語言、編寫不同類型的創意內容以及以資訊豐富的方式回答您的問題。 Meta 宣稱 Llama 3 是最好的開放模型之一,但它仍在開發中。這是與 Mistral 和 Gemma 相比的 8B 模型基準(根據 Meta)。 ![基準測試](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ax9r9z2w2zghv81grbh7.png) 這就引出了一個問題:作為一個普通人,我如何在我的電腦上本地執行這些模型? 開始使用 Ollama ----------- 這就是[奧拉瑪](https://ollama.com/)登場的地方! Ollama 是一款免費的開源應用程式,可讓您在自己的電腦上執行各種大型語言模型,包括 Llama 3,即使資源有限。 Ollama 利用了 llama.cpp 的效能提升,llama.cpp 是一個開源程式庫,旨在允許您以相對較低的硬體要求在本地執行 LLM。它還包括一種套件管理器,使您只需一個命令即可快速有效地下載和使用 LLM。 第一步是[安裝 Ollama](https://ollama.com/download) 。它支援所有 3 個主要作業系統,其中[Windows 是「預覽版」](https://ollama.com/blog/windows-preview) (更好的說法是「測試版」)。 安裝完成後,打開您的終端。在所有平台上,命令都是相同的。 ``` ollama run llama3 ``` 等待幾分鐘,它會下載並載入模型,然後開始聊天!它應該會帶您進入與此類似的聊天提示。 ``` ollama run llama3 >>> Who was the second president of the united states? The second President of the United States was John Adams. He served from 1797 to 1801, succeeding George Washington and being succeeded by Thomas Jefferson. >>> Who was the 30th? The 30th President of the United States was Calvin Coolidge! He served from August 2, 1923, to March 4, 1929. >>> /bye ``` 您可以在這個終端聊天中整天聊天,但是如果您想要更像 ChatGPT 的東西怎麼辦? 打開網頁介面 ------ Open WebUI 是一個可擴充的、自架的 UI,完全在[Docker](https://docs.docker.com/desktop/)內部運作。它可以與 Ollama 或其他 OpenAI 相容的 LLM 一起使用,例如 LiteLLM 或我自己的[Cloudflare Workers OpenAI API](https://github.com/chand1012/openai-cf-workers-ai) 。 假設您的電腦上已經執行了[Docker](https://docs.docker.com/desktop/)和 Ollama,[安裝](https://docs.openwebui.com/getting-started/#quick-start-with-docker-)非常簡單。 ``` docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main ``` 只要造訪 http://localhost:3000,建立帳戶,然後開始聊天! ![OpenWebUI 範例](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rdi1d35zh09s78o8vqvb.png) 如果您之前沒有執行過 Llama 3,則必須先關閉一些模型才能開始聊天。最簡單的方法是點擊左下角您的名字後點擊設定圖示。 ![設定](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tqyetksyn0y4a0p12ylu.png) 然後點擊模式左側的“模型”,然後貼上[Ollama 註冊表](https://ollama.com/models)中的模型名稱。以下是我推薦用於一般用途的一些模型。 - `llama3` - `mistral` - `llama2` ![機型設定頁面](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txc581jf4w3xszymjfbg.png) 奧拉馬 API ------- 如果您想將 Ollama 整合到您自己的專案中,Ollama 提供自己的 API 以及 OpenAI 相容 API。 API 會自動將本機儲存的 LLM 載入到記憶體中,執行推理,然後在一定的逾時後卸載。您必須先拉取您想要使用的任何模型,然後才能透過 API 執行模型,這可以透過命令列輕鬆完成。 ``` ollama pull mistral ``` ### 奧拉馬 API Ollama 有自己的 API,其中還有[一些用於 Javascript 和 Python 的 SDK](https://github.com/ollama/ollama?tab=readme-ov-file#libraries) 。 以下是如何使用 API 進行簡單的文字產生推理。 ``` curl http://localhost:11434/api/generate -d '{ "model": "mistral", "prompt":"Why is the sky blue?" }' ``` 以下是如何使用 API 進行聊天產生推論。 ``` curl http://localhost:11434/api/chat -d '{ "model": "mistral", "messages": [ { "role": "user", "content": "why is the sky blue?" } ] }' ``` 將`model`參數替換為您要使用的任何模型。請參閱[官方 API 文件](https://github.com/ollama/ollama/blob/main/docs/api.md)以取得更多資訊。 ### OpenAI 相容 API 您也可以使用 Ollama 作為 OpenAI 庫的替代品(取決於用例)。這是[他們文件](https://github.com/ollama/ollama/blob/main/docs/openai.md)中的一個範例。 ``` # Python from openai import OpenAI client = OpenAI( base_url='http://localhost:11434/v1/', # required but ignored api_key='ollama', ) chat_completion = client.chat.completions.create( messages=[ { 'role': 'user', 'content': 'Say this is a test', } ], model='mistral', ) ``` 這也適用於 JavaScript。 ``` // Javascript import OpenAI from 'openai' const openai = new OpenAI({ baseURL: 'http://localhost:11434/v1/', // required but ignored apiKey: 'ollama', }) const chatCompletion = await openai.chat.completions.create({ messages: [{ role: 'user', content: 'Say this is a test' }], model: 'llama2', }) ``` 結論 -- Meta 的 Llama 3 的發布及其大型語言模型 (LLM) 技術的開源標誌著技術社群的一個重要里程碑。現在,透過 Ollama 和 Open WebUI 等本地工具可以存取這些先進的模型,普通個人可以挖掘其巨大潛力來生成文字、翻譯語言、創作創意寫作等。此外,API 的可用性使開發人員能夠將 LLM 無縫整合到新專案或增強現有專案。最終,LLM 技術透過 Llama 3 等開源專案實現民主化,釋放了廣泛的創新可能性,並激發了科技業的創造力。 --- 原文出處:https://dev.to/timesurgelabs/how-to-run-llama-3-locally-with-ollama-and-open-webui-297d

系統設計面試中 Docker、Kubernetes 和 Podman 有何不同?

*揭露:這篇文章包含附屬連結;如果您透過本文中提供的不同連結購買產品或服務,我可能會獲得補償。* ![Docker、Kubernetes 和 Podman 之間的差異?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7lmxnjetsoayumogkorw.png) 朋友們大家好,如果您正在準備技術面試,那麼您必須為 Docker 和 Kubernetes 等容器技術做好準備,因為容器現在用於部署大多數應用程式,包括微服務和單體應用。 如今,系統設計和軟體開發人員面試中最常見的問題之一是**Docker、Kubernetes 和 Podman 之間的差異?它們是什麼以及何時使用它們**。 過去我討論過[API網關與負載平衡器、](https://dev.to/somadevtoo/difference-between-api-gateway-and-load-balancer-in-system-design-54dd)[水平與垂直擴展](https://dev.to/somadevtoo/horizontal-scaling-vs-vertical-scaling-in-system-design-3n09)、 [正向代理與反向代理](https://dev.to/somadevtoo/difference-between-forward-proxy-and-reverse-proxy-in-system-design-54g5)等系統設計問題,今天我將回答Docker、Kubernetes和Podman之間的差異。 Docker、Kubernetes 和 Podman 都是受歡迎的容器化工具,讓開發人員和 DevOps 以一致且高效的方式打包和部署應用程式。 **Docker**是流行的容器化平台,允許開發人員在容器中建立、部署和執行應用程式。 Docker 提供了一組工具和 API,使開發人員能夠建置和管理容器化應用程式,包括 Docker Engine、Docker Hub 和 Docker Compose。 另一方面, **Kubernetes**是一個開源容器編排平台,可以自動化容器化應用程式的部署、擴展和管理。 Kubernetes 還提供了一組 API 和工具,使開發人員能夠在多個主機和環境中大規模部署和管理容器化應用程式。 而\*\*,Podman\*\*是一個相對較新的容器化工具,與Docker類似,但架構不同。 Podman 不需要守護程序來執行容器,並且它與 Docker 映像和註冊表相容。 Podman 提供了一個簡單的命令列介面來建立和管理容器,在許多情況下它可以用作 Docker 的直接替代品。 現在我們已經基本了解它們是什麼以及它們的作用,讓我們深入研究它們以了解它們是如何工作的。 順便說一句,如果您正在準備系統設計面試並想深入學習系統設計,那麼您還可以查看[**ByteByteGo**](https://bit.ly/3P3eqMN) 、 [**Design Guru**](https://bit.ly/3pMiO8g) 、 [**Exponent**](https://bit.ly/3cNF0vw) 、 [**Educative**](https://bit.ly/3Mnh6UR)和[**Udemy**](https://bit.ly/3vFNPid)等網站,它們有許多很棒的系統設計課程 [![如何回答系統設計問題](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxd9nfio7kl57gyevndql.jpg)](https://bit.ly/3pMiO8g) PS 繼續閱讀直到最後。我有一份免費獎金給你。 --- 什麼是 Docker?它是如何運作的? ------------------- 正如我所說,Docker 是一個開源平台,使開發人員能夠在容器內自動部署和管理應用程式。 它提供了*一種將應用程式及其相依性打包到稱為容器的標準化單元中的方法,*該單元可以在任何相容的系統上執行,而無需擔心作業系統或底層基礎設施的差異。 身為開發人員或 DevOps 工程師,您應該了解以下幾個重要的 Docker 概念: **1. 容器化** Docker 利用容器化技術建立隔離的環境(稱為容器)來執行應用程式。容器是輕量級的,封裝了執行應用程式所需的應用程式程式碼、執行時間、系統工具、程式庫和相依性。 這使得應用程式能夠在不同的環境中一致地執行,確保無論底層系統如何,它們的行為都是相同的。 **2. Docker 映像** Docker 映像可作為建立容器的範本。它是一個只讀快照,包含應用程式程式碼和所有必要的依賴項。 Docker 映像是使用`Docker file`建立的,該文件是一個文字文件,指定建置映像的步驟。 `Dockerfile`中的每個步驟代表映像中的一個層,從而實現映像的高效儲存和共用。 **3.Docker引擎** Docker Engine是Docker的核心元件。它負責建置和執行基於Docker映像的容器。 Docker 引擎包括管理容器的伺服器和允許使用者與 Docker 互動的命令列介面 (CLI)。 **4. Docker 註冊表** Docker 映像可以儲存在登錄中,例如 Docker Hub 或私有註冊表。註冊表是`Docker`映像的集中儲存庫,可輕鬆地在不同系統之間共用和分發映像。開發人員可以從登錄中提取預先建置的映像,或推送自己的自訂映像供其他人使用。 **5. 容器生命週期** 為了執行應用程式, [Docker](https://medium.com/javarevisited/5-best-docker-courses-for-java-and-spring-boot-developers-bbf01c5e6542)從映像建立容器。容器是隔離的,有自己的檔案系統、流程和網路介面。 它們可以根據需要啟動、停止、暫停和刪除。 Docker 提供了一組命令和 API 來管理容器的生命週期,從而可以輕鬆擴展、更新和監控。 **6. 容器編排** 雖然[Docker](https://medium.com/javarevisited/why-every-developer-should-learn-docker-in-2023-ac27fac5fd6f)本身提供了容器管理功能,但它還可以與 Kubernetes 等容器編排平台無縫協作。 這些平台支援管理大型容器集群,處理負載平衡、擴展和跨多個主機的自動部署等任務。 總體而言, **Docker 利用容器化技術簡化了應用程式的打包、分發和執行過程。**它幫助開發人員實現應用程式的一致性、可移植性和可擴展性,使其成為現代軟體開發和部署工作流程中的熱門選擇。 這也是[ByteByteGo](https://bit.ly/3P3eqMN)的一個很好的圖表,它突出顯示了 Docker 的關鍵元件及其工作原理: [ ![Docker 是如何運作的](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8jbisa4dxd0k9tju7va.jpg)](https://bit.ly/3P3eqMN) --- 什麼是 Kubernetes?它是如何運作的? ----------------------- Docker 和 Kubernetes 就像兄弟一樣,經常被一起提及,但它們卻有很大不同。 [Kubernetes](https://medium.com/javarevisited/10-best-kubernetes-courses-for-developers-and-devops-engineers-94c35cd3a2fd)是一個開源容器編排平台,可自動執行容器化應用程式的部署、擴充和管理。 它**提供了一個框架,用於跨機器叢集執行和協調多個容器**,從而更輕鬆地管理複雜的分散式系統。 以下是我認為每個開發人員或 DevOps 都應該學習和了解的重要 Kubernetes 或 K8 概念: **1. 集群架構** Kubernetes 以叢集架構執行,由一個主節點和多個工作節點組成。主節點管理叢集並協調整體操作,而工作節點負責執行容器。 **2. Pod** Kubernetes 中的基本部署單元是 Pod。 Pod 是一個或多個容器的邏輯群組,這些容器位於同一位置並共享相同的資源,例如網路命名空間和儲存。 Pod 內的容器可以使用 localhost 相互通訊。 Pod 被視為臨時單元,可輕鬆建立、更新或終止。 **3. 副本集和部署** 副本集定義了在任何給定時間執行的相同 Pod 副本的所需數量。 它們透過自動管理和維護所需數量的 Pod 執行個體來確保高可用性和可擴充性。 部署是一種更高層次的抽象,可讓您以聲明方式管理和更新副本集,從而實現應用程式版本的無縫滾動更新和回滾。 **4. 服務** Kubernetes 服務提供穩定的網路端點來連接到一組 Pod。它們支援負載平衡並將 Pod 內的容器公開給其他服務或外部用戶端。 服務抽象化了底層的 Pod 實例,允許應用程式與其他元件進行通信,而無需擔心它們的動態特性。 **5. 標籤和選擇器** Kubernetes 使用標籤和選擇器來實現靈活、動態的物件分組和選擇。標籤是附加到 Pod、部署、服務和其他 Kubernetes 物件的鍵值對。 選擇器用於根據物件的標籤過濾和匹配物件,從而可以進行有針對性的操作並對相關資源進行分組。 **6. 縮放和自動縮放** Kubernetes 可讓您透過調整 pod 副本的數量來擴展應用程式。 Pod 水平自動擴展 (HPA) 是一項根據資源利用率指標(例如 CPU 或記憶體使用情況)自動擴展 Pod 副本數量的功能。 **7. 容器網絡** Kubernetes 也管理 Pod 和節點之間的網路。每個 Pod 都有自己的 IP 位址,Pod 內的容器可以使用`localhost`相互通訊。 Kubernetes 提供了**網路插件**,可以促進容器網路並實現跨 Pod 和叢集的通訊。 **8. 集群管理** Kubernetes 還提供廣泛的叢集管理功能,包括捲動更新、機密管理、設定管理和執行狀況監控。 它提供了一種聲明式方法來定義系統的所需狀態,使 Kubernetes 能夠持續監控實際狀態並將其與所需狀態進行協調。 **9. 貨櫃存放** Kubernetes 支援各種儲存選項,包括持久磁碟區和儲存類別。持久卷提供了一種將儲存與 Pod 生命週期分離的方法,從而實現跨 Pod 和容器重新啟動的資料持久化和共享。 透過抽象化*大規模管理容器的複雜性,Kubernetes 使開發人員能夠專注於應用程式邏輯*而不是基礎架構管理。 它提供了一個強大且可擴展的平台,用於部署和管理容器化應用程式,使其成為建置現代雲端原生系統的流行選擇。 這是一個很好的圖表,顯示了 K8 或 Kubernetes 的不同元件以及它們如何協同工作: ![什麼是 Kubernetes](https://miro.medium.com/v2/resize:fit:609/0*pRm7KUB_3307GXS2.png) --- Podman 是什麼?它是如何運作的? --------------- 現在您已經知道什麼是 Docker 和 Kubernetes,是時候看看另一個流行的工具 Podman,它通常被視為 Docker 的替代品。 Podman 是一個開源容器執行時間和管理工具,提供用於管理容器的命令列介面 (CLI)。 它旨在成為 Docker 的兼容替代方案,提供與 Docker 相容的 API,並允許熟悉 Docker 的用戶輕鬆過渡\*。 Podman 設計提供安全且輕量的容器體驗。 以下概述了 Podman 的工作原理以及您應該了解的重要 Podman 概念: **1. 容器運作時** Podman 作為容器執行時,這意味著它可以建立和執行容器。它使用相容於開放容器計劃 (OCI) 的容器格式,確保與其他容器執行時的兼容性,並允許 Podman 執行符合 OCI 的容器。 **2. CLI 相容性** Podman 的 CLI 旨在讓 Docker 用戶熟悉。它提供類似於 Docker CLI 的命令,讓使用者可以輕鬆管理容器、映像、磁碟區和網路。 這種相容性使開發人員和系統管理員可以更輕鬆地從 Docker 過渡到 Podman,而無需對其工作流程進行重大更改。 **3.無根容器** Podman 的一項顯著功能是它對無根容器的支援。它允許非 root 用戶無需特權存取即可執行容器。 這透過將容器與主機系統隔離並降低容器逃逸的風險來增強安全性。 **4. 容器管理** Podman 提供一系列管理功能,例如建立、啟動、停止和刪除容器。它支援網路配置,允許容器之間以及主機系統之間進行通訊。 Podman 還提供了管理容器磁碟區、環境變數和資源限制的選項。 **5. 容器鏡像** 與 Docker 一樣,Podman 依賴容器映像作為建立容器的基礎。它可以從各種容器註冊表(包括 Docker Hub)中提取和推送容器映像。 Podman 也可以使用 Dockerfile 在本機建置映像或從其他容器執行時匯入映像。 **6. Pod 支持** Podman 超越了單一容器,支援 Pod 的概念,類似 Kubernetes。 Pod 是一組共享相同網路命名空間和資源的容器。 Podman 讓使用者可以建立和管理 Pod,從而實現容器之間更複雜的部署和通訊模式。 **7. 與編排平台集成** 雖然 Podman 可以用作獨立的容器執行時,但它也可以與 Kubernetes 等容器編排平台整合。它可以充當 Kubernetes Pod 的容器執行時,允許使用者在 Kubernetes 叢集中利用 Podman 的功能和相容性。 **8. 安全焦點** Podman 非常重視安全性。它支援使用者命名空間映射等功能,將容器使用者ID映射到主機上的非root使用者ID,從而增強容器隔離。 Podman 還整合了 SELinux 和 seccomp 設定檔等安全增強技術,以提供額外的保護層。 Podman 旨在為 Docker 用戶提供無縫過渡,同時強調安全性和輕量級容器管理。 它提供相容性、靈活性和用戶友好的 CLI,對於尋求替代容器執行時的人來說是一個引人注目的選擇。 ![什麼是 Podman](https://miro.medium.com/v2/resize:fit:609/1*bFTJH7TCRebunX4CXhr7Uw.png) --- Docker、Kubernetes 和 Podman 之間有什麼區別? ----------------------------------- 以下是 Docker、Kubernetes 和 Podman 之間的主要區別,我對它們的不同點進行了比較,主要是這些工具提供的功能和功能,例如容器化和容器管理等。 **1. 容器引擎** Docker 主要是用於建置、執行和分發容器的容器執行時和引擎。另一方面,Kubernetes 是一個編排平台,旨在管理跨機器叢集的容器化應用程式。 Podman 是一個容器執行時間和管理工具,提供與 Docker 相容的 CLI 和容器執行時間。 **2. 容器格式** Docker 使用自己的容器格式,稱為 Docker 容器。 [Kubernetes](https://medium.com/javarevisited/7-free-online-courses-to-learn-kubernetes-in-2020-3b8a68ec7abc)可以使用多種容器格式,但 Docker 容器是最常見的選擇。 另一方面,Podman 使用相容於開放容器計劃 (OCI) 的容器格式,並且可以執行符合 OCI 的容器。 **3. 編排** Docker 擁有內建的編排工具 Docker Swarm,它允許管理一組用於執行容器的 Docker 節點。 另一方面,Kubernetes 提供了用於管理容器化應用程式的高級編排功能,包括擴充功能、負載平衡、自動化部署和自我修復。 Podman 沒有像 Docker Swarm 或 Kubernetes 這樣的內建編排功能,但它可以與 Kubernetes 或其他編排平台一起工作。 **4. 集群管理** Docker 本身不支援管理容器叢集。另一方面,Kubernetes 是專門為管理容器叢集而設計的,並提供擴展、升級、監控和管理容器化應用程式的功能。 Podman 本身不支援管理容器集群,但可以與 Kubernetes 或其他容器編排框架等外部工具一起使用。 **5. 安全** 對於安全性比較,Docker 提供了基本的隔離和安全功能,但其主要重點是執行單一容器。 Kubernetes 提供進階安全功能,例如網路策略、秘密管理和 RBAC。 另一方面, **Podman**專注於安全性,並提供使用者命名空間映射、seccomp 設定檔和 SELinux 整合等功能,以增強容器安全性。 **6. 使用者介面** 相較於 UI, [Docker](https://medium.com/javarevisited/10-free-courses-to-learn-docker-and-devops-for-frontend-developers-691ac7652cee)提供了使用者友善的 CLI 和基於 Web 的圖形介面(Docker Desktop)來管理容器。 Kubernetes 有一個名為`"kubectl"`的 CLI 工具和一個基於 Web 的儀表板(Kubernetes Dashboard),用於管理容器和叢集。 同時,Podman 提供了類似 Docker CLI 的 CLI,可以與`Cockpit`等第三方工具一起使用,進行基於 Web 的管理。 而且,如果您喜歡表格,這裡有一個很好的表格,我以表格格式列出了*Docker、Kubernetes 和 Podman 之間的所有差異*: ![docker、kubernetes 和 podman 之間的區別](https://miro.medium.com/v2/resize:fit:609/1*Q4wN6VE6C_0LoWc1PqgTzg.png) 這些是*Docker、Kubernetes 和 Podman 之間的根本區別*,它們在容器化生態系統中服務於不同的目的。 --- ### 系統設計訪談資源: 而且,這裡列出了最佳系統設計書籍、線上課程和練習網站,您可以查看這些內容,以便更好地為系統設計面試做好準備。這些課程中的大多數也回答了我在這裡分享的問題。 1. [**DesignGuru 的 Grokking 系統設計課程**](https://bit.ly/3pMiO8g):一個互動式學習平台,提供實作練習和真實場景,以增強您的系統設計技能。 2. [**《系統設計面試》作者:Alex Xu**](https://amzn.to/3nU2Mbp) :這本書深入探討了系統設計概念、策略和麵試準備技巧。 3. Martin Kleppmann 的[**「設計資料密集型應用程式」**](https://amzn.to/3nXKaas) :綜合指南,涵蓋了設計可擴展且可靠的系統的原則和實踐。 4. [LeetCode 系統設計 標籤](https://leetcode.com/explore/learn/card/system-design):LeetCode 是一個受歡迎的技術面試準備平台。 LeetCode 上的系統設計標籤包含各種練習問題。 5. GitHub 上的[**「系統設計入門」**](https://bit.ly/3bSaBfC) :精選的資源列表,包括文章、書籍和影片,可幫助您準備系統設計面試。 6. [**Educative 的系統設計課程**](https://bit.ly/3Mnh6UR):一個互動式學習平台,提供實作練習和真實場景,以增強您的系統設計技能。 7. **高可擴展性部落格**:該部落格包含有關高流量網站和可擴展系統架構的文章和案例研究。 8. **[YouTube 頻道](https://medium.com/javarevisited/top-8-youtube-channels-for-system-design-interview-preparation-970d103ea18d)**:請參閱「Gaurav Sen」和「Tech Dummies」等頻道,以取得有關係統設計概念和麵試準備的富有洞察力的影片。 9. [**ByteByteGo**](https://bit.ly/3P3eqMN) :Alex Xu 的一本現場書籍和課程,用於系統設計面試準備。它包含《系統設計訪談》第一捲和第二卷的所有內容,並將隨即將推出的第三卷進行更新。 10. [**Exponent**](https://bit.ly/3cNF0vw) :一個專為面試準備的網站,特別是針對亞馬遜和谷歌等 FAANG 公司,他們還有很棒的系統設計課程和許多其他材料,可以幫助您破解 FAAN 面試。 [![如何為系統設計做準備](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqv3p46jmw5qc0newuiu.jpg)](https://bit.ly/3P3eqMN) image\_credit - [ByteByteGo](https://bit.ly/3P3eqMN) 這就是**Docker、Kubernetes 和 Podman 之間的差異。**總之,Docker 是一個用於建立和管理容器的流行容器化平台,Kubernetes 是一個用於大規模管理容器化應用程式的容器編排平台,而`Podman`是一個具有不同架構的容器化工具,可以用作Docker的直接替代品在很多情況下。 這些工具都有不同的用途,它們都可以一起使用,為開發人員提供全面的容器化解決方案,但更重要的是每個開發人員和 DevOps 都應該了解這些工具。 ### 獎金 正如承諾的,這是給你的獎金,一本免費的書。我剛剛找到一本新的免費書籍來學習分散式系統設計,您也可以在 Microsoft 上閱讀它 --- [https://info.microsoft.com/rs/157-GQE-382/images/EN-CNTNT -eBook-設計分散式系統.pdf](https://info.microsoft.com/rs/157-GQE-382/images/EN-CNTNT-eBook-DesigningDistributedSystems.pdf) [![學習分散式系統的免費書籍](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrc1jn751mzs4ru91zt3.png)](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrc1jn751mzs4ru91zt3.png) 謝謝 --- 原文出處:https://dev.to/somadevtoo/difference-between-docker-kubernetes-and-podman-for-system-design-interview-3an6

了解 API 和端點之間的區別

### 了解 API 和端點之間的區別 在軟體開發領域,特別是在 Web 服務和後端開發領域,經常出現兩個術語:API(應用程式介面)和端點。雖然它們具有內在聯繫,但它們代表不同的概念。本文旨在闡明 API 和端點之間的差異,闡明它們各自的角色以及它們如何相互關聯。 #### 什麼是 API? 應用程式介面 (API) 是一組用於建立軟體應用程式的協定、例程和工具。它定義了應用程式可以用來相互溝通的方法和資料格式。本質上,API 充當中介,允許不同的軟體系統無縫互動。 ##### API 的主要特徵: - **定義**:API 是一套全面的規則和定義,可促進軟體應用程式之間的通訊。 - **範圍**:它包含多個端點、函數或方法,提供廣泛的功能。 - **目的**:API 支援不同系統之間的集成,透過提供用於存取各種功能和資料的一致介面來確保它們可以協同工作。 - **範例**:常見範例包括 RESTful API、SOAP API 和 GraphQL API。 #### 什麼是端點? 另一方面,端點是 API 中代表離散資源或功能的特定 URL 或 URI。它是客戶端(例如 Web 瀏覽器、行動應用程式或其他伺服器)可以存取 API 的特定互動點。 ##### 端點的主要特徵: - **定義**:端點是 API 中的精確位置,通常對應於單一功能或服務。 - **範圍**:它是 API 的一部分,通常指特定功能,例如檢索資料、更新資源或執行操作。 - **用途**:端點是 API 請求所導向的特定 URL。它們定義存取特定資源或功能所需的路徑和參數。 - **範例**:典型範例包括: - `GET /api/users` – 檢索使用者列表 - `POST /api/users` – 建立一個新用戶 - `GET /api/users/{id}` – 透過 ID 檢索特定用戶 - `PUT /api/users/{id}` – 按 ID 更新特定用戶 - `DELETE /api/users/{id}` – 按 ID 刪除特定用戶 #### API和端點之間的關係 打個比方,可以將 API 視為一個函式庫,將端點視為該函式庫中的特定書籍。 API 提供了庫如何運作的結構和規則,而端點是您可以尋找和存取特定資訊的精確位置。 - **API 作為圖書館**:就像圖書館包含書籍集合一樣,API 包含端點集合,每個端點都有特定的用途。 - **端點作為書籍**:API 中的每個端點都類似於圖書館中的一本書,提供可以直接存取的特定資訊或功能。 #### 實際影響 了解 API 和端點之間的差異對於開發人員來說至關重要。在設計 API 或與 API 互動時,重要的是要了解: - **API**提供了互動的整體框架和規則。 - **端點**是存取資料和功能的特定交互點。 這種差異有助於設計更有效率、更有組織的系統。它還有助於故障排除,因為開發人員可以找出問題是在更廣泛的 API 結構中還是在特定端點中。 #### 結論 總之,雖然 API 和端點是相關概念,但它們在軟體開發生態系統中扮演著不同的角色。 API 是一套全面的協定和定義,使軟體系統能夠進行通信,而端點是 API 中發生這些交互的特定 URL。了解這些差異對於有效的軟體設計、開發和整合至關重要。 --- 原文出處:https://dev.to/msnmongare/understanding-the-difference-between-apis-and-endpoints-402a

  近期留言