🔍 搜尋結果:.

🔍 搜尋結果:.

初級開發人員會犯什麼錯誤

詢問高級開發人員 -------- ![問](https://i.imgur.com/ZRJAQRB.gif) 我們最近在[Reddit](https://www.reddit.com/r/webdev/comments/112im2m/senior_devs_what_are_the_most_damaging/)上的網頁開發社群向資深開發人員詢問了以下問題: *初級開發人員中最具破壞性的誤解是什麼?* 我們想知道初級開發人員一直犯的錯誤是什麼,以及他們可以做些什麼來改進。令人驚訝的是,我們詢問的高級開發人員給了我們大量的回應——準確地說超過 270 個! 由於這裡有很多有價值的訊息,我們決定在本文中總結回應。 所以,請閱讀一下,然後在評論中告訴我們您的想法:) 最常見的主題 ------ 回覆中有很多很棒的具體例子,但我們注意到其中有很多共同的主題: - **程式碼品質** - **管理時間和期望** - **有效的溝通和團隊合作** 這些似乎是高階開發人員最常談論的話題。這是有道理的——當你深入問題的核心時,這些事情幾乎可以成就或毀掉*任何*職業。 有趣的是,最受歡迎的回覆是涵蓋所有這些主題的問題。例如,以下是得票最高的回覆: ![稍後清理](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6rrl9weufsl2ch92myk.png) 先質量,後速度 ------- > *高程式碼品質只會間接影響使用者。主要目的是維持較高的開發速度,使所有利害關係人受益* > — **zoechi** \* r/webdev 在「品質」辯論中,實際上存在兩個陣營,其中一些認為品質程式碼是關於: 1. 編寫乾淨、可讀的程式碼,易於維護 2. 編寫按時交付且有效的程式碼。 滿足最後期限、發布功能和編寫最佳程式碼之間的平衡顯然是一個棘手的問題。 有些人認為,業務現實意味著團隊通常沒有時間進行乾淨的程式碼模式。最重要的一點是按時完成任務並讓客戶滿意。 另一方面,許多高級開發人員認為品質程式碼應該是**優先事項**,並且透過將其作為優先事項,您實際上可以提高長期速度,即使無法滿足短期期限。 ![您不必接觸所有程式碼](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3z5qolwgu1y09gut2sp9.png) 不過,這種討論可能會分散初級開發人員優先事項的注意力,這些優先事項是作為開發人員成長和改進,而不是帶領團隊取得成功。因此,**我們認為初級開發人員最好先專注於質量,然後再提高交付速度。** --- 順便說一句,我們正在建立[Wasp](https://wasp-lang.dev) ,一個具有超能力的全端 React + NodeJS 框架,成為提升全端 Web 開發人員技能的最佳方法之一。 透過[在 GitHub 上為我們的儲存庫加註星標,](https://www.github.com/wasp-lang/wasp)您將幫助我們繼續使 Web 開發變得更快、更輕鬆,並每週為您帶來這樣的內容。 ![https://media1.giphy.com/media/ZfK4cXKJTTay1Ava29/giphy.gif?cid=7941fdc6pmqo30ll0e4rzdiisbtagx97sx5t0znx4lk0auju&ep=v1_gifs_searchx97sx5t0znx4lk0auju&ep=v1_gifs_search}&ridgi.](https://media1.giphy.com/media/ZfK4cXKJTTay1Ava29/giphy.gif?cid=7941fdc6pmqo30ll0e4rzdiisbtagx97sx5t0znx4lk0auju&ep=v1_gifs_search&rid=giphy.gif&ct=g) <https://www.github.com/wasp-lang/wasp> ⭐️ 感謝您的支持🙏 --- 保持謙虛並管理期望 --------- 作為初級開發人員,您不會期望第一次就能把所有事情都做對。 人們假設您會隨著時間的推移學習最佳實踐,但在此過程中您可能會產生不一致的工作、犯錯,甚至可能會破壞一些東西。 ![愚蠢的](https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExYWZ3bHZ0NXZ1NzFtbTR4djc3dTJhZ2E0dGtyZHpod2FnNDVleDBrcCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/xT9Igi8GqJpYgC2vQs/giphy.gif) 但沒關係。 這是過程的一部分。這是預期的。重要的是要記住,這並不反映您作為工程師或個人的價值或價值。 在回覆中,也有許多開發者認識到另一個開發者希望“稍後修復問題”,以此來消除對其工作的批評。他們普遍認為這是一種壞習慣,因為即使開發人員獲得了更多經驗,這也常常困擾著他們。 例如,「程式碼審查不應該針對個人」是高階開發人員的共同觀點。 因此,**能夠優雅地接受批評是一項需要培養的重要技能。** 畢竟,前輩會根據他們自己的經驗指導你做出更好的決定。青少年也在那裡學習。 ![資深開發人員並不了解一切](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l3j4lng6hbhwc7hpopmc.png) 但是您應該多久尋求一位前輩的建議呢?你應該照他們所說的去做,還是按照某些人在 YouTube 或某些博文中告訴你的那樣*去做 x 的唯一方法*;)? 你是否應該在每次陷入困境時尋求幫助,還是應該犧牲自己的理智,獨自掙扎數日? 嗯,這取決於你問誰。但大多數回應都明確表示: 1. 你應該先自己嘗試一下。 2. 使用您可用的資源(ChatGPT、Stack Overflow、Google)嘗試找出答案。 3. 一旦你進展緩慢,就尋求幫助。 4. 如果你有一個可能的解決方案,而且它與高級開發人員的建議不同,這並不意味著它是錯誤的——有時可能有很多可能的方法來實現相同的目標! ![提問打擾前輩](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7yylsti2jhtcc81fv93.png) 保持靈活性並樂於改變 ---------- 沒有什麼比科技世界的變化更快。作為開發人員,您需要不斷學習和適應新技術和趨勢。如果您不喜歡改變,那麼軟體開發人員可能不適合您。 ![一切都比你想像的還要長](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rkvo1a6gavuj0d341h9y.png) 除了事物不斷變化之外,這種工作還會挑戰你的假設。例如,您認為可能是最佳的解決方案結果與您團隊的預期目標或最終產品不相容,您被迫使用「次優」解決方案。 為什麼?因為這可能是最好的方法 考慮到團隊的限制來完成工作。 ( *「抱歉,朋友,我們不能在這個框架上使用您最喜歡的框架。」* ) **保持靈活和開放思想的**開發人員通常在這方面具有優勢。 他們對特定技術或方法不太教條,更願意適應當前的情況。他們通常比同齡人進步得更快,並且能夠出色地完成工作。 --- 如果到目前為止您發現這很有用,**請[在 GitHub 上給我們一顆星](https://github.com/wasp-lang/wasp)以表示您的支持**!它將幫助我們繼續製造更多類似的東西。 ![https://res.cloudinary.com/practicaldev/image/fetch/s--OCpry2p9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads /文章/bky8z46ii7ayejprrqw3.gif](https://res.cloudinary.com/practicaldev/image/fetch/s--OCpry2p9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bky8z46ii7ayejprrqw3.gif) <https://www.github.com/wasp-lang/wasp> ⭐️ 感謝您的支持🙏 --- 所以你怎麼看? ------- 好的,這就是我們的總結。 ![開發商](https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExMjc2ZzRreTgzMm45ZjZudXMxYXl6ZWVvYmV4eG5sZDdvZXg1dGFjNyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l3q2zbskZp2j8wniE/giphy.gif) 對於這些意見,你有何看法?高階開發人員的評估是否正確,或者他們是否遺漏了某些內容? 您最近是否意識到一些您希望早點知道的事情?如果是的話,請在評論中與我們分享! --- 噓!我和我的同事也在下面的 YouTube 影片中更詳細地討論了結果並權衡了我們的意見。所以檢查一下,如果這是你的事情:) https://www.youtube.com/watch?v=eermNn9VhOA --- 原文出處:https://dev.to/wasp/what-junior-devs-get-wrong-an8

建立你的第一個 npm 包

這個週末我開始開發我的第一個 npm 包。我不敢相信我編寫程式碼已經有多久了,我從來沒有費心去建立自己的 npm 包,但我們來了。我使用 Gridsome 和 markdown 建立了我的最新網站,您可以[在此處](https://www.danvega.me/blog/hello-gridsome)閱讀所有相關內容。在 Markdown 文件中,我想要一個簡單的方法來插入 Twitter 狀態並嵌入推文。 我將在以後的部落格文章中告訴您有關 Gridsome 插件的更多訊息,但現在,我想向您展示如何建立您的第一個 npm 包。我在做這件事的過程中學到了一些東西,我想與你們分享。 先決條件 ---- 我假設你至少知道什麼是 Node 和 npm,並且之前寫過 JavaScript。如果您對其中任何一個都不了解,並希望我寫一些有關這些入門的內容,請告訴我。 在我們深入並開始編寫一些程式碼之前,您需要一些東西。 - [Visual Studio Code](https://code.visualstudio.com/)或您最喜歡的編輯器 - [節點和 NPM](https://nodejs.org/en/) - [NPM帳戶](https://www.npmjs.com/) 建立你的 npm 包 ---------- 您要做的第一件事是建立一個新資料夾來保存您的 npm 套件。對於此範例,我將建立一個名為**wrap-with-poo**的新目錄。是的,你沒看錯。 進入該資料夾並輸入以下內容: ``` npm init ``` 這會問你一堆問題,然後建立一個 package.json。如果您還不知道某些問題的答案,請不要擔心,您可以稍後再回來回答。 ``` This utility will walk you through creating a package.json file. It only covers the most common items and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg>` afterward to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. package name: (wrap-with-poop) version: (0.1.0) 0.1.0 description: This package will take any string you give it and wrap it with the poop emjoi entry point: (index.js) test command: git repository: keywords: node,npm author: Dan Vega license: (ISC) MIT About to write to /Users/vega/dev/npm/wrap-with-poop/package.json: { "name": "wrap-with-poop", "version": "0.1.0", "description": "This package will take any string you give it and wrap it with the poop emjoi", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "node", "npm" ], "author": "Dan Vega", "license": "MIT" } Is this OK? (yes) yes ``` 寫你的插件 ----- 接下來在 Visual Studio Code 中開啟專案並建立 index.js。您建立此文件的原因是您在 package.json 中說過這是您的入口點。在你的index.js中加入以下程式碼: ``` module.exports = (str) => { return `💩${str}💩`; } ``` module.exports 物件允許我們組織一些相關的程式碼,然後將其公開為模組。這意味著當我們完成後,我們可以將此模組匯入到另一個應用程式中。在本例中,我們指派一個箭頭函數,這表示我們公開一個函數,該函數接受一個名為 str 的參數,並傳回用 poo 表情符號包裹的字串。這就是您需要對這個專案做的全部事情。這是一個非常簡單的包,但它將有助於完成一些事情。 npm 本機開發 -------- 現在您已經準備好了我們的包,您需要在另一個專案中測試它。在現實世界中,您應該針對它編寫一些單元測試,但我想將其保存到另一篇文章和截圖中。 接下來,建立一個名為「wrap-with-poo-testing」的新目錄(在套件外部)。您將再次需要執行 npm init 但這次您可以加入 -y 參數來跳過所有問題,這次它們不太重要。 ``` npm init -y Wrote to /Users/vega/dev/npm/wrap-with-poo/package.json: { "name": "wrap-with-poop", "version": "0.1.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" } ``` ### NPM安裝 在此專案中建立一個名為 app.js 的新檔案。這是您將使用新的wrap-with-poo 套件的地方。通常,您可以透過執行以下命令來安裝所需的 npm 軟體包。 ``` npm install wrap-with-poo ``` 問題是你還沒有發布你的新插件,所以它不在 npm 中。您需要一種在開發時在本地引用該套件的方法。您可以使用套件的絕對路徑來執行 npm install。 ``` npm install /Users/vega/dev/npm/wrap-with-poo ``` 這會將您的 package.json 更新為如下所示 ``` { "name": "npm", "version": "0.1.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "wrap-with-poo": "file:../wrap-with-poo" } } ``` 如果您需要測試套件中的[安裝前/安裝後掛鉤,](https://docs.npmjs.com/misc/scripts)那麼您將需要使用此方法。如果您不關心本地開發 NPM 專案的最佳方法是使用[npm link](https://docs.npmjs.com/cli/link.html) 。 ### NPM連結 npm link 是一個允許您在專案和依賴項之間建立符號連結的過程。首先,您需要進入目錄wrapper-with-poo並執行以下命令。 ``` npm link ``` 這將獲取您的套件並在 npm 全域資料夾中建立符號連結。 **/Users/vega/.nvm/versions/node/v10.15.0/lib/node\_modules/wrap-with-poo -> /Users/vega/dev/npm/wrap-with-poo** 這意味著您的專案只需一個簡單的步驟即可在任何專案中使用。您需要做的下一件事是進入專案 wrap-with-poo-testing 並執行以下命令。 ``` npm link wrap-with-poo ``` 這將輸出以下內容: \_\_/Users/vega/dev/npm/wrap-with-poo-testing/node\_modules/wrap-with-poo -> /Users/vega/.nvm/versions/node/v10.15.0/lib /node\_modules/wra p-with-poo -> /Users/vega/dev/npm/wrap-with-poo\_\_ 這就是全部內容,無需安裝依賴項。您已準備好開始編寫一些程式碼來使用新插件。打開 app.js 並新增以下程式碼。 ``` const poo = require('wrap-with-poo'); const boring = 'This is a boring string'; const fun = poo(boring); console.log(fun); ``` 並從集成終端執行以下命令 ``` node app.js ``` 你會得到以下輸出 ``` 💩This is a boring string💩 ``` 發布原始碼 ----- 現在我們知道我們的專案正在發揮作用,是時候將其公開供所有人使用了。如果您還沒有這樣做,我會將您的專案加入到 Github 或您喜歡的任何原始程式碼託管位置。 ``` git init git add . git commit -m "Initial commit" git remote add origin https://github.com/cfaddict/wrap-with-poo.git git push -u origin master ``` 現在它位於 Github 上,返回並在 package.json 中加入一個條目,以便每個人都知道在哪裡可以使用主頁鍵找到原始程式碼。 ``` { "name": "wrap-with-poo", "version": "0.1.0", "description": "This package will wrap any string you give it with the poop emoji", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "node", "npm", "poop" ], "author": "Dan Vega", "license": "MIT", "homepage": "https://github.com/cfaddict/wrap-with-poo" } ``` 發布 NPM 包 -------- 現在是時候將我們的專案發佈到 npm 以便任何人都可以使用它了。如果這是您第一次發布包,請在wrap-with-poo 目錄中開啟終端,然後鍵入以下命令。 ``` npm adduser ``` 這將要求您提供 npm 帳戶訊息,例如使用者名稱、密碼和電子郵件。 ``` vega wrap-with-poo (master) $ npm adduser Username: therealdanvega Password: Email: (this IS public) [email protected] Logged in as therealdanvega on https://registry.npmjs.org/. ``` 現在您已準備好發布,但您需要記住一些事情。首先,每個 npm 套件必須有一個唯一的名稱。我會前往[npm](https://www.npmjs.com/)并快速搜尋你的包。我已經發布了套件wrapper-with-poo,所以你的套件需要一個新的唯一名稱。 接下來您需要知道的是您的版本號碼很重要。我從 0.0.1 開始,然後從那裡開始工作。發布特定版本後,您將無法再次發布相同版本。將許多功能建置到一個版本中然後發布是一個好主意。如果你跑 ``` npm version ``` 它會告訴您目前的版本是什麼。 ``` { 'wrap-with-poo': '0.1.0', npm: '6.7.0', ares: '1.15.0', cldr: '33.1', http_parser: '2.8.0', icu: '62.1', modules: '64', napi: '3', nghttp2: '1.34.0', node: '10.15.0', openssl: '1.1.0j', tz: '2018e', unicode: '11.0', uv: '1.23.2', v8: '6.8.275.32-node.45', zlib: '1.2.11' } ``` 如果一切看起來都不錯,您可以透過執行來發布您的新專案 ``` npm publish ``` 這可能需要幾秒鐘,但如果一切順利,你的包包現在應該[在 npm 上](https://www.npmjs.com/settings/therealdanvega/packages)。 恭喜你發布了你的第一個 npm 包!!! 現在您可以進入任何已有 package.json 的專案並輸入以下內容 ``` npm install wrap-with-poo ``` 就像我們在上面的測試範例中所做的那樣使用它。 文件 -- 我知道有些人說你應該從一開始就建立文件,但我並不總是確定我的程式碼最終會是什麼樣子,所以我通常會等待。在專案的根目錄中建立 README.md 並加入有關專案的一些資訊。 - 你的 npm 包是做什麼的? - 你為什麼創造它。 - 你如何安裝它? - 有任何配置選項嗎? 結論 -- 正如我在本文開頭所說,我不敢相信我這個週末發布了我的第一個 npm 包。直到現在我才真正需要這樣做,但我真的很高興知道它是多麼容易。如果這是您的第一個 npm 軟體包,請在您的軟體包上線後給我留下一些評論或推文! 快樂編碼! 和 *本文首先發佈在我的部落格:https://www.danvega.dev/blog 如果您覺得這篇文章有趣,請考慮[訂閱我的電子報](https://www.danvega.dev/signup/)或在[Twitter](http://twitter.com/therealdanvega)上關注我。* --- 原文出處:https://dev.to/therealdanvega/creating-your-first-npm-package-2ehf

我使用 Next.js、GPT4 和 CopilotKit 建立了 v0.dev 克隆

長話短說 ---- 在本文中,您將了解如何建立 Vercel 的 V0.dev 的克隆。這是一個很棒的專案,可以加入到您的投資組合中並磨練您的人工智慧能力。 我們將介紹使用: - 用於應用程式框架的 Next.js 🖥️ - 法學碩士 OpenAI 🧠 - v0 👾 的應用程式邏輯 - 使用 CopilotKit 將 AI 整合到您的應用程式中 🪁 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/shhjdu2k5s02gzoby3p0.gif) --- CopilotKit:應用內人工智慧的作業系統框架 ========================= CopilotKit 是[開源人工智慧副駕駛平台。](https://github.com/CopilotKit/CopilotKit)我們可以輕鬆地將強大的人工智慧整合到您的 React 應用程式中。 建造: - ChatBot:上下文感知的應用內聊天機器人,可以在應用程式內執行操作 💬 - CopilotTextArea:人工智慧驅動的文字字段,具有上下文感知自動完成和插入功能📝 - 聯合代理:應用程式內人工智慧代理,可以與您的應用程式和使用者互動🤖 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8gltoave8490fg234ro.gif) {% cta https://github.com/CopilotKit/CopilotKit %} Star CopilotKit ⭐️ {% endcta %} (原諒人工智慧的拼字錯誤並給一顆星:) 現在回到文章。 --- 先決條件 ---- 要開始學習本教程,您需要具備以下條件: - 文字編輯器(VS Code、遊標) - React、Next.js、Typescript 和 Tailwind CSS 的基本知識。 - Node.js 安裝在您的 PC/Mac 上 - 套件管理器 (npm) - [OpenAI](https://platform.openai.com/docs/overview) API 金鑰 - [CopilotKit](https://docs.copilotkit.ai/getting-started/quickstart-textarea)安裝在您的 React 專案中 v0是什麼? ------ **v0**是[Vercel 開發的](https://vercel.com/blog/announcing-v0-generative-ui)生成式使用者介面 (UI) 工具,允許使用者給予提示並描述他們的想法,然後將其轉換為用於建立 Web 介面的 UI 程式碼。它利用[生成式 AI](https://medium.com/data-science-at-microsoft/generative-ai-openai-and-chatgpt-what-are-they-3c80397062c4)以及[React](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started) 、 [Tailwind CSS](https://tailwindcss.com/)和[Shadcn UI](https://ui.shadcn.com/)等開源工具,根據使用者提供的描述產生程式碼。 *這是使用 v0 產生的 Web 應用程式 UI 的範例* https://v0.dev/t/nxGnMd1uVGc 了解專案要求 ------ 在本逐步教程結束時,克隆將具有以下專案要求: 1. **使用者輸入:**使用者輸入文字作為提示,描述他們想要產生的 UI。這將使用 CopilotKit 聊天機器人來完成,該聊天機器人由[CopilotSidebar](https://docs.copilotkit.ai/reference/CopilotSidebar)提供。 2. **CopilotKit 整合:** CopilotKit 將用於為 Web 應用程式提供 AI 功能以產生 UI。 3. **渲染 UI:**在 UI React/JSX 程式碼和渲染 UI 之間切換的切換開關。 使用 CopilotKit 建立 v0 克隆 ---------------------- **第 1 步:建立一個新的 Next.JS 應用程式** 在終端機中開啟工作區資料夾並執行以下命令建立新的 Next.js 應用程式: ``` npx create-next-app@latest copilotkit-v0-clone ``` 這將建立一個名為`copilotkit-v0-clone`新目錄,其中包含 Next.JS 專案結構,並安裝了所需的依賴項。它將在您的終端中顯示這一點,並對除最後一個之外的所有選項都選擇**“是”** ,因為建議使用預設`import alias` 。其他提示安裝我們將在專案中使用的 Typescript 和 TailwindCSS。 ![終端](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o6l07dxihdi8hw68kv4e.png) 使用`cd`指令導航到專案目錄,如下所示: ``` cd copilotkit-v0-clone ``` **步驟 2:設定 CopilotKit 後端端點。閱讀[文件](https://docs.copilotkit.ai/getting-started/quickstart-backend)以了解更多資訊。** 執行以下命令來安裝 CopilotKit 後端軟體包: ``` npm i @copilotkit/backend ``` 然後造訪 https://platform.openai.com/api-keys 以取得您的**GPT 4** OpenAI API 金鑰。 ![開放伊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ise7y3qnb3cyg4j0mjr6.png) 取得 API 金鑰後,在根目錄中建立一個`.env.local`檔案。 `.env.local`檔案應該是這樣的: ``` OPENAI_API_KEY=Your OpenAI API key ``` 在**app**目錄下建立該目錄; `api/copilot/openai`並建立一個名為`route.ts`的檔案。該檔案用作 CopilotKit 請求和 OpenAI 互動的**後端**端點。它處理傳入的請求,使用 CopilotKit 處理它們,並傳回適當的回應。 我們將在`route.ts`檔案中建立一個POST請求函數,在post請求內部建立一個`CopilotBackend`類別的新實例,該類別提供了處理CopilotKit請求的方法。 然後,我們呼叫`CopilotBackend`實例的`response`方法,並傳遞請求物件 ( `req` ) 和`OpenAIAdapter`類別的新實例作為參數。此方法使用 CopilotKit 和 OpenAI API 處理請求並回傳回應。 如下面的程式碼所示,我們從`@copilotkit/backend`套件導入`CopilotBackend`和`OpenAIAdapter`類別。這些類別對於與 CopilotKit 和 OpenAI API 互動是必需的。 ``` import { CopilotBackend, OpenAIAdapter } from "@copilotkit/backend"; export const runtime = "edge"; export async function POST(req: Request): Promise<Response> { const copilotKit = new CopilotBackend(); return copilotKit.response(req, new OpenAIAdapter()); } ``` **步驟 3:為 v0 克隆建立元件** 我們將使用 Shadcn UI 庫中的元件。要處理這個問題,讓我們透過執行`shadcn-ui init`命令來設定 Shadcn UI 庫來設定您的專案 ``` npx shadcn-ui@latest init ``` 然後我們將用這個問題來配置components.json ``` Which style would you like to use? › Default Which color would you like to use as base color? › Slate Do you want to use CSS variables for colors? › no / yes ``` 我們在 Shadcn UI 中使用的元件是**按鈕**和**對話框**。那麼讓我們來安裝它們吧! 對於[按鈕](https://ui.shadcn.com/docs/components/button),執行此命令 ``` npx shadcn-ui@latest add button ``` 若要安裝[對話](https://ui.shadcn.com/docs/components/dialog)方塊元件,請執行以下命令 ``` npx shadcn-ui@latest add dialog ``` **第 4 步:設定 CopilotKit 前端。閱讀[文件](https://docs.copilotkit.ai/getting-started/quickstart-textarea)以了解更多資訊。** 若要安裝 CopilotKit 前端軟體包,請執行以下命令: ``` npm i @copilotkit/react-core @copilotkit/react-ui ``` 根據[CopilotKit 文件](https://docs.copilotkit.ai/getting-started/quickstart-textarea),要使用 CopilotKit,我們必須設定前端包裝器以透過 Copilot 傳遞任何 React 應用程式。當提示傳遞到 CopilotKit 時,它會透過 URL 將其傳送到 OpenAI,後者會回傳回應。 在**應用程式**目錄中,讓我們更新`layout.tsx`檔案。該文件將定義我們應用程式的佈局結構並將 CopilotKit 整合到前端。 輸入以下程式碼: ``` "use client"; import { CopilotKit } from "@copilotkit/react-core"; import "@copilotkit/react-textarea/styles.css"; // also import this if you want to use the CopilotTextarea component import "@copilotkit/react-ui/styles.css"; import { Inter } from "next/font/google"; import "./globals.css"; import { CopilotSidebar, } from "@copilotkit/react-ui"; const inter = Inter({ subsets: ["latin"] }); export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="en"> <body className={inter.className}> <CopilotKit url="/api/copilotkit/openai/"> <CopilotSidebar defaultOpen>{children}</CopilotSidebar> </CopilotKit> </body> </html> ); } ``` 該元件代表我們應用程式的根佈局。它使用 CopilotKit 包裝整個應用程式,根據我們在**步驟 2**中為後端建立的內容指定 CopilotKit 後端端點的 URL ( `/api/copilotkit/openai/` )。此外,它還包括一個 CopilotSidebar 元件,可作為 CopilotKit 的側邊欄,並將 Children 屬性作為其內容傳遞。 **第 5 步:設定主應用程式** 讓我們建立應用程式的結構。它將有一個標題、側邊欄和預覽畫面。 對於**Header** ,導航到**元件**目錄,如下所示, `src/components`然後建立一個`header.tsx`檔案並輸入以下程式碼: ``` import { CodeXmlIcon } from "lucide-react"; import { Button } from "./ui/button"; const Header = (props: { openCode: () => void }) => { return ( <div className="w-full h-20 bg-white flex justify-between items-center px-4"> <h1 className="text-xl font-bold">Copilot Kit</h1> <div className="flex gap-x-2"> <Button className=" px-6 py-1 rounded-md space-x-1" variant={"default"} onClick={props.openCode} > <span>Code</span> <CodeXmlIcon size={20} /> </Button> </div> </div> ); }; export default Header; ``` 對於**側欄,**建立一個`sidebar.tsx`檔案並輸入以下程式碼: ``` import { ReactNode } from "react"; const Sidebar = ({ children }: { children: ReactNode }) => { return ( <div className="w-[12%] min-h-full bg-white rounded-md p-4"> <h1 className="text-sm mb-1">History</h1> {children} </div> ); }; export default Sidebar; ``` 然後對於**預覽**螢幕,建立一個`preview-screen.tsx`檔案並輸入程式碼: ``` const PreviewScreen = ({ html_code }: { html_code: string }) => { return ( <div className="w-full h-full bg-white rounded-lg shadow-lg p-2 border"> <div dangerouslySetInnerHTML={{ __html: html_code }} /> </div> ); }; export default PreviewScreen; ``` 現在讓我們將它們放在一起,打開`page.tsx`檔案並貼上以下程式碼: ``` "use client"; import { useState } from "react"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import Header from "@/components/header"; import Sidebar from "@/components/sidebar"; import PreviewScreen from "@/components/preview-screen"; import { Input } from "@/components/ui/input"; export default function Home() { const [code, setCode] = useState<string[]>([ `<h1 class="text-red-500">Hello World</h1>`, ]); const [codeToDisplay, setCodeToDisplay] = useState<string>(code[0] || ""); const [showDialog, setShowDialog] = useState<boolean>(false); const [codeCommand, setCodeCommand] = useState<string>(""); return ( <> <main className="bg-white min-h-screen px-4"> <Header openCode={() => setShowDialog(true)} /> <div className="w-full h-full min-h-[70vh] flex justify-between gap-x-1 "> <Sidebar> <div className="space-y-2"> {code.map((c, i) => ( <div key={i} className="w-full h-20 p-1 rounded-md bg-white border border-blue-600" onClick={() => setCodeToDisplay(c)} > v{i} </div> ))} </div> </Sidebar> <div className="w-10/12"> <PreviewScreen html_code={readableCode || ""} /> </div> </div> <div className="w-8/12 mx-auto p-1 rounded-full bg-primary flex my-4 outline-0"> <Input type="text" placeholder="Enter your code command" className="w-10/12 p-6 rounded-l-full outline-0 bg-primary text-white" value={codeCommand} onChange={(e) => setCodeCommand(e.target.value)} /> <button className="w-2/12 bg-white text-primary rounded-r-full" onClick={() => generateCode.run(context)} > Generate </button> </div> </main> <Dialog open={showDialog} onOpenChange={setShowDialog}> <DialogContent> <DialogHeader> <DialogTitle>View Code.</DialogTitle> <DialogDescription> You can use the following code to start integrating into your application. </DialogDescription> <div className="p-4 rounded bg-primary text-white my-2"> {readableCode} </div> </DialogHeader> </DialogContent> </Dialog> </> ); } ``` 我們來分解一下上面的程式碼: `const [code, setCode] = useState<string[]>([]);`將用於保存生成的程式碼 `const [codeToDisplay, setCodeToDisplay] = useState<string>(code[0] || "");`將用於保存預覽畫面上顯示的程式碼。 `const [showDialog, setShowDialog] = useState<boolean>(false);`這將保持對話框的狀態,該對話框顯示您可以複製的生成程式碼。 在下面的程式碼中,我們循環產生的程式碼(一串陣列)將其顯示在側邊欄上,這樣當我們選擇一個程式碼時,它就會顯示在預覽畫面上。 ``` <Sidebar> <div className="space-y-2"> {code.map((c, i) => ( <div key={i} className="w-full h-20 p-1 rounded-md bg-white border border-blue-600" onClick={() => setCodeToDisplay(c)} > v{i} </div> ))} </div> </Sidebar> ``` `<PreviewScreen html_code={codeToDisplay} />`在這裡,我們發送要在預覽畫面上顯示的程式碼。預覽畫面元件採用 CopilotKit 產生的程式碼字串,並使用`dangerouslySetInnerHTML`來呈現產生的程式碼。 下面我們有一個`Dialog`元件,它將顯示 CoplilotKit 產生的程式碼,可以將其複製並加入到您的程式碼中。 ``` <Dialog open={showDialog} onOpenChange={setShowDialog}> <DialogContent> <DialogHeader> <DialogTitle>View Code.</DialogTitle> <DialogDescription> You can use the following code to start integrating into your application. </DialogDescription> <div className="p-4 rounded bg-primary text-white my-2"> {readableCode} </div> </DialogHeader> </DialogContent> </Dialog> ``` **步驟6:實作主要應用程式邏輯** 在這一步驟中,我們將 CopilotKit 整合到我們的 v0 克隆應用程式中,以促進人工智慧驅動的 UI 生成。我們將使用 CopilotKit 的 React hook 來管理狀態,使元件可供 Copilot 讀取和操作,並與 OpenAI API 互動。 在您的`page.tsx`檔案中,匯入以下內容: ``` import { CopilotTask, useCopilotContext, useMakeCopilotReadable, } from "@copilotkit/react-core"; ``` 然後我們在`Home`元件中使用`CopilotTask`定義一個`generateCode`任務: ``` const readableCode = useMakeCopilotReadable(codeToDisplay); const generateCode = new CopilotTask({ instructions: codeCommand, actions: [ { name: "generateCode", description: "Create Code Snippet with React.js, tailwindcss.", parameters: [ { name: "code", type: "string", description: "Code to be generated", required: true, }, ], handler: async ({ code }) => { setCode((prev) => [...prev, code]); setCodeToDisplay(code); }, }, ], }); const context = useCopilotContext(); ``` 我們使用`useMakeCopilotReadable`來傳遞現有程式碼並確保可讀性。然後我們使用`CopilotTask`產生UI,並將`generateCode`任務綁定到**生成**按鈕,這樣就可以透過與按鈕元件互動來產生程式碼片段。 此操作由使用者互動觸發,並在呼叫時執行非同步`handler`函數。 `handler`將產生的程式碼新增至程式碼陣列中,更新應用程式狀態以包含新產生的程式碼片段,並將產生的程式碼傳送到預覽畫面上顯示和呈現,預覽畫面也可以複製。 此外, `instructions`屬性指定提供給 Copilot 的命令,該命令儲存在`codeCommand`狀態變數中。 有關`CopilotTask`運作方式的完整說明,請查看此處的文件:https://docs.copilotkit.ai/reference/CopilotTask **第 6 步:執行 v0 克隆應用程式** 至此,我們已經完成了 v0 克隆設置,然後可以透過執行來啟動開發伺服器 ``` npm run dev ``` ![終端](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6wm5oddqlzewca34ko0g.png) 可以使用此 URL 在瀏覽器中存取該 Web 應用程式 [http://本地主機:3000](http://localhost:3000/) 然後您可以輸入提示並點擊**“生成”。**這裡有些例子: - **定價頁面:**如下所示,這是產生的UI,有一個切換按鈕可以在UI和React程式碼之間切換: ![在](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cm3gyodvbl0x9i0uvxp9.png) 如果點擊右上角的**Code** &lt;/&gt; 按鈕,它會切換到產生的 UI 的 React 程式碼,如下所示: ![在](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1b5sruonnxl7x42ad8y1.png) - 註冊頁面 UI 範例: ![報名](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/350l7o66l6lq5d4kxiav.png) - 還有一個結帳頁面 ![查看](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dpj6j338fp2gavsvgtti.png) 要克隆專案並在本地執行它,請打開終端並執行以下命令: ``` git clone https://github.com/Tabintel/v0-copilot-next ``` 然後執行`npm install`以安裝專案所需的所有依賴項,並`npm run dev`來執行 Web 應用程式。 結論 -- 總而言之,您可以使用[CopilotKit](https://github.com/CopilotKit/CopilotKit)建立 v0 克隆,為您的設計提供 UI 提示。 CopilotKit 不僅適用於 UI 提示,它還可以用於建立[AI 驅動的 PowerPoint 生成器](https://dev.to/copilotkit/how-to-build-ai-powered-powerpoint-app-nextjs-openai-copilotkit-ji2)、 [AI 簡歷產生器](https://dev.to/copilotkit/how-to-build-the-with-nextjs-openai-1mhb)等應用程式。 可能性是無限的,立即查看 CopilotKit,將您的 AI 想法變為現實。 在[GitHub](https://github.com/Tabintel/v0-copilot-next)上取得完整原始碼。 從[文件](https://docs.copilotkit.ai/getting-started/quickstart-textarea)中了解有關如何使用 CopilotKit 的更多資訊。 另外,別忘了[Star CopilotKit!](https://github.com/CopilotKit/CopilotKit) ⭐ --- 原文出處:https://dev.to/copilotkit/i-created-a-v0-clone-with-nextjs-gpt4-copilotkit-3cmb

由於錯誤,我賣掉了我的新創公司:我希望我有這個無伺服器儲存庫!

2021 年,我創辦了一家名為 Linvo 的新創公司,這是一款 LinkedIn 自動化工具。它產生了很多錢,但燒錢率也很高。 我可以告訴你,作為一個年輕的企業家(完全自力更生),我損失了大部分錢😆 我的系統的問題是它不斷故障;我不是世界上最好的程式設計師,但讓我詳細說明一下。 ![收入](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4l95m758p7m9fg4914dc.png) --- 傀儡師會吸走你的記憶 ---------- Linvo 在其生命週期中進行了幾次迭代。我使用了我所知道的技術:React 和 NestJS。 基本上,任何自動化的雲端抓取都會涉及建立任務然後解決它們。 它看起來像這樣: ![工人和刮削](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9n4d78oe0cz6vxl1y34n.png) - Cron 每 10 分鐘執行一次,尋找新的事情要做,並將其發送到佇列。 - 工作人員從佇列中取出任務並處理它們。 - 將所有內容儲存到資料庫。 這是一個非常簡單的解決方案,在多個 EC2 (AWS) 和 Redis 上運作。 理論上,它應該有效 - 是的,您需要水平擴展工作人員,但這不是我的問題。 我開始經歷其他事情——**記憶體洩漏。** 您可能知道, [Puppeteer](https://pptr.dev/) - 一種 chromium 自動瀏覽器,很重(與您電腦上的 Chrome 相同),而且我執行了很多它們 - 它們耗盡了我的記憶體 - 導致伺服器停止工作並佔用網路頻寬。 ![糟透了](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5fsl47a1yzumo3qexa8h.gif) --- 需要一個解決方案 -------- 重構聽起來就像 - 是的,讓我們這樣做,但我的 Intercom 支援充滿了支援票(我已經有很多用戶),而且我知道我必須建立一些瘋狂的重構。 我有一個解決方案的想法 - 讓我們使用 AWS lambda。 - 拉姆達啟動 - 做任務 - 死亡(大部分時間) 它不會影響你的網路。 它會死掉並且不會導致記憶體洩漏。 它有點貴,因為 Lambda 並不意味著無限期地執行——這會消除整個概念,但我很絕望。 (嗯,好處是你不需要考慮規模。) 這是新的基礎設施: ![新基礎設施](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sr304vf0z81f0bqfxnup.png) - 事件橋 cron 每 1 分鐘執行一次(這是最小值) - 為佇列建立六個事件的 Lambda(使其像 cron 每 10 秒執行一次) - SQS隊列(再見,Redis) - Lambda 以自動縮放功能脫穎而出(是嗎?) --- 供應商鎖定 ----- 正如您可能從上下文中了解到的那樣 - 現在我完全使用 AWS,但我不介意 - 只介意如何在我的計算機上測試它。 以前,我使用[Sam](https://github.com/aws/aws-sam-cli) 。和[Serverless](https://www.serverless.com/)幾乎一樣快速地創造整個環境。 是的,他們確實帶來了一些本地測試。他們可以獲得您的 lambda 並將其轉變為端點!耶! 但我使用的是 Event Bridge、SQS 和 Lambda。那是不可能的。 我遇過[localstack](https://github.com/localstack/localstack) 。它本來應該幫助我在我的電腦上建立整個 AWS 堆疊,但當時很多東西都不受支持,例如 Lambda 層。我在使用它時不知所措。 因此,我開始建立我的「自己的」基礎設施,在 AWS 上部署了一個「測試」SQS,並用它執行本地程式碼(一個呼叫函數的函數),但結果很糟糕。 我在生產方面做得不好;我感覺這個詞當時就壓在我身上。 我只是想擺脫這家新創公司;我甚至免費向人們提供它,吸引了顧客並擺脫了這個問題。 長話短說,我設法以低價出售了該系統,但最近,我發現了一些有趣的事情。 --- Winglang - 類似 Typescript 的雲方言 ----------------------------- 我想我的痛苦是真實的,儘管我會很高興在當天找到它 - 我很高興它今天還活著。 [Winglang](https://github.com/winglang/wing)幫助您建立與我使用的相同的雲端基礎設施,但好處是: - 它不需要您使用任何設定檔。您基本上用程式碼定義了整個基礎設施(您可以檢查他們的整個預檢和飛行中文件) - 你可以在本地執行它 - 謝謝你,上帝,🙏🏻🙏🏻🙏🏻🙏🏻,包括所有基礎設施。 - 您可以將其部署到任何雲端供應商,並且不必使用 AWS。他們實際上可以產生任何 Terraform 或雲端結構,以便於部署。 我和Winglang的創始人Elad(著名的CDK的建置者)進行了交談,他說了一些讓我抽搐的話。 > 當您在飛機上時,您實際上可以處理您的專案並為其編寫測試🤯 我自己無法給他們足夠的星星 - 但請幫我一個忙,給他們的存儲庫加星標,當然,將其用於您的下一個專案。 https://github.com/winglang/wing ![謝謝](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/giofk3zupgxjgnc57zw5.gif) --- 最後的話 ---- 我對翼朗很生氣。我希望他們早點這麼做。現在他們出現了。什麼時候一切都與人工智慧有關? 我建立了一個新的 YouTube 頻道,主要涉及技術、開源和行銷:) 如果您對此感興趣,請隨時在這裡訂閱: https://www.youtube.com/@nevo-david?sub\_confirmation=1 --- 原文出處:https://dev.to/github20k/i-sold-my-startup-because-of-bugs-i-wish-i-had-this-serverless-repository-4l3a

50 多個核心 Java 面試問題及程式設計師答案

--- 標題:針對程式設計師的 50 多個核心 Java 面試問題及其答案 發表:真實 描述:核心 Java 面試常見問題及其答案,幫助初學者和初級開發人員獲得第一份 Java 開發工作。 標籤: java、程式設計、職業 封面圖:https://thepracticaldev.s3.amazonaws.com/i/k63545lbbjmh582tiosr.png --- *揭露:這篇文章包含附屬連結;如果您透過本文中提供的不同連結購買產品或服務,我可能會獲得補償。* Java程式設計師大家好!在過去的幾年裡,我一直在分享許多[Java 面試問題](http://javarevisited.blogspot.sg/2015/10/133-java-interview-questions-answers-from-last-5-years.html)、答案和單獨討論。我的許多讀者要求我將他們聚集在一起,以便他們可以在同一個地方進行面試準備。 這篇文章就是這個結果。 本文包含**50 多個 Java 面試問題和答案**,涵蓋所有重要主題,如核心 Java 基礎知識、 [Java 集合框架](https://javarevisited.blogspot.com/2011/11/collection-interview-questions-answers.html)、 [Java 多執行緒和並發](https://javarevisited.blogspot.com/2014/07/top-50-java-multithreading-interview-questions-answers.html)、 [Java IO](https://javarevisited.blogspot.com/2014/08/socket-programming-networking-interview-questions-answers-Java.html) 、 [JDBC](https://javarevisited.blogspot.com/2012/12/top-10-jdbc-interview-questions-answers.html) 、 [JVM 內部原理](http://www.java67.com/2016/08/10-jvm-options-for-java-production-application.html)、 [編碼問題](http://www.java67.com/2018/06/data-structure-and-algorithm-interview-questions-programmers.html)、 [物件導向程式設計](http://www.java67.com/2015/12/top-30-oops-concept-interview-questions-answers-java.html)等。 這些問題是從我做過的各種 Java 訪談中挑選出來的,我的朋友、讀者和其他人根據自己的經驗分享了一些問題。它們絕不是非常困難。您可能已經在電話或面對面的面試中見過它們。 這些問題對於複習重要的 Java 主題(例如核心 Java 概念、多執行緒、lambda、流和集合)也非常有用。 我還分享了一些*用於進一步學習和提高的有用資源*,例如 Udemy 上的[**完整 Java 大師**](https://click.linksynergy.com/fs-bin/click?id=JVFxdTr9V80&subid=0&offerid=323058.1&type=10&tmpid=14538&RD_PARM1=https%3A%2F%2Fwww.udemy.com%2Fjava-the-complete-java-developer-course%2F)課程,您可以加入課程來提高和填補 Java 技能方面的空白。 我還寫過有關 Java 面試準備的書籍,例如[《Grokking the Java Interview》](https://gumroad.com/l/QqjGH)和[《Grokking the Spring Boot Interviews》](https://gumroad.com/l/hrUXKY) ,其中我為 Java 開發人員分享了很多問題。 如果你今年正在準備 Java 面試,你也可以**[在 Gumroad 上取得我的 Java + Spring Interview + SQL Bundle](https://javinpaul.gumroad.com/l/sowpfg)** ,使用程式碼**Friends20**還可獲得 20% 的折扣 [![Java 和 Spring 面試書籍](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xj0hpl0w5lyvdrnwlsoe.png)](https://javinpaul.gumroad.com/l/sowpfg) 那我們還在等什麼?以下是針對初學者和經驗豐富的 Java 開發人員的面試中最常見的一些 Java 問題的清單。 2 至 3 年經驗豐富的程式設計師的 50 個 Java 面試問題 --------------------------------- 因此,為了不浪費您的時間,這裡列出了一些針對初學者程式設計師的常見[核心 Java 面試問題](http://www.java67.com/2018/03/top-50-core-java-interview-questions.html)。此清單主要針對初學者和經驗不足的開發人員,例如具有 2 到 3 年 Java 經驗的人。 1) **Java如何實現平台無關性?** ([回答](http://www.java67.com/2012/08/how-java-achieves-platform-independence.html)) 提示:字節碼和Java虛擬機 答案 - Java 透過產生字節碼然後在 Java 虛擬機器上執行來實現平台獨立性,該虛擬機將這些字節碼轉換為依賴計劃的機器程式碼。由於不同平台的 JVM 不同,我的意思是,對於 Windows,您有單獨的 JRE(其中包括 JVM),對於 Linux,您將有單獨的 JRE。由於 Java 程式碼不會編譯為本機機器碼,而是編譯為字節碼,這使得它們獨立於平台。 2) **Java中的**`**ClassLoader**`**是什麼**? ([回答](http://javarevisited.blogspot.sg/2012/12/how-classloader-works-in-java.html#axzz59AWpr6cb)) 提示:JVM 的一部分,用於載入類別的字節碼。你可以自己寫。 答:在Java中,程式碼被封裝在類別中,因為Java是物件導向的程式設計。你的程式是在類別中寫的,為了執行它們,JVM 會載入這些包含你的程式碼的類別。負責載入類別的 JVM 元件稱為類別載入器。它們是存在的三個主要類別載入器:引導類別載入器、擴充類別載入器和應用程式類別載入器。 這是一個很好的圖表,顯示了每個 Java 類別載入器的功能: [![Java 中的類別載入器](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2brxfmzd67dv2k7rwmv.PNG)](https://javarevisited.blogspot.com/2021/05/java-classloader-interview.html) 3)**寫一個Java程式來檢查一個數字是偶數還是奇數?** ([回答](http://javarevisited.blogspot.sg/2013/04/how-to-check-if-number-is-even-or-odd.htm)) 提示:您可以使用位元運算符,例如位元與,記住,二進位格式中偶數末尾為 0,奇數末尾為 1。 4) **Java中**`**ArrayList**`**和**`**HashSet**`**的差別**? ([回答](http://www.java67.com/2012/07/difference-between-arraylist-hashset-in-java.html)) 提示: `List`和`Set`之間的所有差異都適用於此,例如排序、重複、隨機搜尋等。請參閱 Richard Warburton 的[**《Java 基礎知識:集合》**](https://pluralsight.pxf.io/c/1193463/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fjava-fundamentals-collections)以了解有關Java 中的ArrayList、HashSet 和其他重要集合的更多資訊。 [![](https://miro.medium.com/max/875/1*hd861fcwDe86tY-1Y0VNRQ.png)](https://pluralsight.pxf.io/c/1193463/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fjava-fundamentals-collections) 5)**什麼是單例中的雙重檢查鎖定?** ([回答](http://www.java67.com/2016/04/why-double-checked-locking-was-broken-before-java5.html)) 提示:兩次檢查實例是否已初始化,第一次不加鎖,第二次加鎖。 **6)如何在Java中建立線程安全的Singleton? (** [**回答**](http://javarevisited.blogspot.sg/2012/12/how-to-create-thread-safe-singleton-in-java-example.html)**)** 提示:有很多方法,例如使用 Enum 或使用雙重檢查鎖定模式或使用巢狀靜態類別。 **7) Java中Serialized和Externalized的差別? (** [**回答**](http://www.java67.com/2012/10/difference-between-serializable-vs-externalizable-interface.html)**)** 提示:Externalized 讓您可以更好地控制序列化過程。 **8) Java中何時使用瞬態變數? (**[**回答**](http://www.java67.com/2012/08/what-is-transient-variable-in-java.html)**)** 提示:當您想要在實作 Serialized 介面的類別中使變數不可序列化時。換句話說,您可以將其用於不想保存其值的變數。請參閱[**完整的 Java MasterClass**](https://click.linksynergy.com/fs-bin/click?id=JVFxdTr9V80&subid=0&offerid=323058.1&type=10&tmpid=14538&RD_PARM1=https%3A%2F%2Fwww.udemy.com%2Fjava-the-complete-java-developer-course%2F)以了解 Java 中的瞬態變數。 **9) Java中transient變數和volatile變數的差別? (** [**回答**](http://www.java67.com/2012/11/difference-between-transient-vs-volatile-modifier-variable-java.html)**)** 提示:完全不同,一個用於序列化上下文,另一個用於並發。 **10) Java中什麼時候使用易失性變數? (**[**回答**](http://www.java67.com/2012/08/what-is-volatile-variable-in-java-when.html)**)** 提示:當你需要指示JVM一個變數可以被多個執行緒修改並提示JVM不緩存其值。 **11)我們可以重寫Java中的私有方法嗎? (** [**回答**](http://www.java67.com/2013/08/can-we-override-private-method-in-java-inner-class.html)**)** 提示:不,因為它在子類別中不可見,這是在 Java 中重寫方法的主要要求。 12) **Java中**`**Hashtable**`**和**`**HashMap**`**的差別**? **(** [**回答**](http://javarevisited.blogspot.sg/2010/10/difference-between-hashmap-and.html#axzz53B6SD769)\*\*) \*\*提示:有幾個但最重要的是`Hashtable` ,它是同步的,而`HashMap`不是。與`HashMap`相比,它也是遺留的且緩慢的。 13) **Java中**`**List**`**和**`**Set**`**的差別**? **(** [**回答**](http://javarevisited.blogspot.sg/2012/04/difference-between-list-and-set-in-java.html#axzz53n9YK0Mb)**)** 提示: `List`是有序的並且允許重複。 `Set`是無序的,不允許有重複的元素。 14) **Java中**`**ArrayList**`**和**`**Vector**`**的區別**([**答案**](http://www.java67.com/2012/09/arraylist-vs-vector-in-java-interview.html)**)** 提示:很多,但最重要的是, `ArrayList`是非同步的,速度很快,而`Vector`是同步的,速度很慢。它也是像`Hashtable`這樣的遺留類別。 **15)** **Java 中**`**Hashtable**`**和**`**ConcurrentHashMap**`的差異? **(** [**回答**](http://javarevisited.blogspot.sg/2011/04/difference-between-concurrenthashmap.html#axzz4qw7RoNvw)**)** 提示:更具可擴展性。請參閱 Richard Warburton 的[**《Java 基礎知識:集合》**](https://pluralsight.pxf.io/c/1193463/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fjava-fundamentals-collections)以了解更多資訊。 16) `**ConcurrentHashMap**`**如何實現可擴充性? (** [**回答**](http://javarevisited.blogspot.sg/2017/08/top-10-java-concurrenthashmap-interview.html#axzz50U9xyqbo)**)** 提示:透過將映射分為段並僅在寫入操作期間鎖定。 **17) 您將重寫哪兩個方法來將**`**Object**`**用作**`**HashMap**`**中的**`**Key**` **? (** [**回答**](http://www.java67.com/2013/06/how-get-method-of-hashmap-or-hashtable-works-internally.html)**)** 提示:等於和哈希碼 **18) Java中wait和sleep的差別? (**[**回答**](http://www.java67.com/2012/08/what-are-difference-between-wait-and.html)**)** \\ 提示: `wait()`方法釋放鎖定或監視器,而 sleep 則不會。 19\) **Java中**`**notify**`**和**`**notifyAll**`**的差別**? **(** [**回答**](http://www.java67.com/2013/03/difference-between-wait-vs-notify-vs-notifyAll-java-thread.html)**)** 提示: `notify`通知一個隨機執行緒正在等待該鎖,而`notifyAll`通知所有等待監視器的執行緒。如果你確定只有一個執行緒在等待,那麼使用`notify` ,否則`notifyAll`會更好。請參閱 Java Champion Heinz Kabutz 的[**線程基礎迷你課程,**](https://javaspecialists.teachable.com/p/threading-essentials/?product_id=539197&coupon_code=SLACK100?affcode=92815_johrd7r8)以了解有關線程基礎知識的更多資訊。 20\) 為什麼要**在 Java 中重寫 hashcode 以及**`**equals()**` ? **(** [**回答**](http://javarevisited.blogspot.sg/2015/01/why-override-equals-hashcode-or-tostring-java.html#axzz55oDxm8vv)**)** 提示:遵守 equals 和 hashcode 約定,如果您打算將物件儲存到集合類別(例如`HashMap`或`ArrayList`中,則需要遵守這一點。 21) `**HashMap**`**的負載因子是什麼意思? (**[**回答**](http://www.java67.com/2017/08/top-10-java-hashmap-interview-questions.html)**)** 提示:觸發`HashMap`調整大小的閾值一般為 0.75,這表示如果 HashMap 已滿 75%,則`HashMap`會自行調整大小。 **22)** **Java 中**`**ArrayList**`**和**`**LinkedList**`之間的差異? **(** [**回答**](http://www.java67.com/2012/12/difference-between-arraylist-vs-LinkedList-java.html)**)** 提示:與陣列和鍊錶相同,其中一個允許隨機搜尋,而另一種則不允許。在鍊錶上插入和刪除很容易,但在陣列上搜尋很容易。請參閱[**《Java 基礎知識:集合》**](https://pluralsight.pxf.io/c/1193463/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fjava-fundamentals-collections) **(** Richard Warburton 在 Pluralsight 上的課程),以了解更多關於 Java 中基本集合資料結構的資訊。 **23)** **Java 中**`**CountDownLatch**`**和**`**CyclicBarrier**`之間的差異? **(** [**回答**](http://www.java67.com/2012/08/difference-between-countdownlatch-and-cyclicbarrier-java.html)**)** 提示:屏障被打破後,您可以重複使用`CyclicBarrier` ,但計數為零後,您無法重複使用`CountDownLatch` 。 24)**在 Java 中什麼時候使用**`**Runnable**`**和**`**Thread**` ? **(** [**回答**](http://www.java67.com/2016/01/7-differences-between-extends-thread-vs-implements-Runnable-java.html)**)** 提示:總是 **25) Java 中 Enum 類型安全的意義是什麼? (** [**回答**](http://www.java67.com/2014/04/what-java-developer-should-know-about-Enumeration-type-in-Java.html)**)** 提示:這表示您不能將不同 Enum 類型的實例指派給 Enum 變數。例如,如果您有一個像`DayOfWeek` day 這樣的變數,那麼您無法從`DayOfMonth`枚舉中為其指派值。 **26) Java 中整數的自動裝箱如何運作? (** [**回答**](http://javarevisited.blogspot.sg/2012/07/auto-boxing-and-unboxing-in-java-be.html#axzz59AWpr6cb)**)** 提示:透過使用Java中的`valueOf()`方法。 **27)** **Java 中**`**PATH**`**和**`**Classpath**`之間的差異? **(** [**回答**](http://www.java67.com/2012/08/what-is-path-and-classpath-in-java-difference.html)**)** 提示:作業系統使用`PATH` ,而JVM 使用`Classpath`來定位Java 二進位文件,例如JAR 檔案或Class 檔案。請參閱[**Java 基礎知識:核心平台**](https://pluralsight.pxf.io/c/1193463/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fjava-fundamentals-core-platform),以了解有關`PATH` 、 `Classpath`和其他 Java 環境變數的更多資訊。 [![](https://miro.medium.com/max/478/1*PBuMgGmVXwBguv-SPw7YJw.jpeg)](https://pluralsight.pxf.io/c/1193463/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fjava-fundamentals-core-platform) **28) Java中方法重載和重寫的差別? (** [**回答**](http://www.java67.com/2015/08/top-10-method-overloading-overriding-interview-questions-answers-java.html)**)** 提示:重寫發生在子類別中,而重載發生在同一個類別中。此外,覆蓋是執行時活動,而重載是在編譯時解決的。 **29) 如何防止 Java 中的類別被子類化? (**[**回答**](http://www.java67.com/2017/06/10-points-about-final-modifier-in-java.html)**)** \\ 提示:只需將其建構函數設為私有即可 **30) 你如何限制你的類別被你的客戶使用? (** [**回答**](http://javarevisited.blogspot.sg/2016/01/why-jpa-entity-or-hibernate-persistence-should-not-be-final-in-java.html)**)** \\ 提示:使建構子私有或從建構子拋出異常 **31)** **Java 中**`**StringBuilder**`**和**`**StringBuffer**`之間的差異? **(**[**回答**](http://www.java67.com/2016/10/5-difference-between-stringbuffer.html)**)** 提示: `StringBuilder`不同步,而`StringBuffer`同步。 **32) Java 中多態性與繼承的差別? (** [**回答**](http://www.java67.com/2014/04/difference-between-polymorphism-and-Inheritance-java-oops.html)**)** 提示:繼承允許程式碼重複使用並建構類別之間的關係,這是多態性所需要的,多態性提供動態行為。請參閱\[**物件導向的 Java 程式設計:資料結構及超越專業化**\]( https://coursera.pxf.io/c/3294490/1164545/14726?u=https%3A%2F%2Fwww.coursera.org%2Fspecializations%2Fjava-object-orientation)在Coursera 上,了解有關OOP 功能的更多資訊。適合初學者的最深入的課程之一。 \[![](https://thepracticaldev.s3.amazonaws.com/i/vuohxotp8qeh638lzjpr.png) \]( https://coursera.pxf.io/c/3294490/1164545/14726?u=https%3A%2F%2Fwww.coursera.org%2Fspecializations%2Fjava-物件導向) 順便說一句,如果您發現 Coursera 課程很有用,因為它們是由世界各地的知名公司和大學建立的,我建議您加入[**Coursera Plus**](https://coursera.pxf.io/c/3294490/1164545/14726?u=https%3A%2F%2Fwww.coursera.org%2Fcourseraplus) ,這是Coursera 的訂閱計劃,可以讓您無限制地存取他們最受歡迎的課程、專業、專業憑證和指導專案。它的費用約為 399 美元/年,但它完全物有所值,因為您可以獲得無限的憑證。 **33)我們可以在Java中重寫靜態方法嗎? (**[**回答**](http://www.java67.com/2012/08/can-we-override-static-method-in-java.html)**)** \\ 提示:否,因為重寫在執行時間解析,而靜態方法呼叫在編譯時解析。 **34) 我們可以存取Java中的私有方法嗎? (**[**回答**](http://www.java67.com/2012/08/can-we-override-private-method-in-java.html)**)** \\ 提示:可以,在同一個班級內,但不能在班級外 **35) Java中介面和抽象類別的區別? (** [**回答**](http://www.java67.com/2017/08/difference-between-abstract-class-and-interface-in-java8.html)**)** 提示:從[Java 8](https://dzone.com/articles/5-courses-to-crack-java-certification-ocajp-1z0-80)開始,差異變得模糊。然而,一個Java類別仍然可以實作多個接口,但只能擴展一個類別。 **36) Java 中 DOM 和 SAX 解析器的差別? (**[**回答**](http://www.java67.com/2012/09/dom-vs-sax-parser-in-java-xml-parsing.html)**)** \\ 提示:DOM 將整個 XML 檔案載入到記憶體中,而 SAX 則不會。它是一個基於事件的解析器,可用於解析大文件,但 DOM 速度很快,對於小文件應該是首選。 **37) Java 中 throw 和 throws 關鍵字的差異? (**[**回答**](http://www.java67.com/2012/10/difference-between-throw-vs-throws-in.html)**)** \\ 提示: throws 聲明方法在發生錯誤時可以拋出什麼異常,但 throw 關鍵字實際上會拋出異常。請參閱[**Java 基礎知識:異常處理**](https://pluralsight.pxf.io/c/1193463/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fjava-fundamentals-exception-handling)以了解有關 Java 中異常處理的更多資訊。 [![](https://miro.medium.com/max/875/1*O5DEoN9mOy3D0HxFKWwfKQ.png)](https://pluralsight.pxf.io/c/1193463/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fjava-fundamentals-exception-handling) **38) Java 中的故障安全迭代器和故障快速迭代器的差異? (** [**回答**](http://www.java67.com/2015/06/what-is-fail-safe-and-fail-fast-iterator-in-java.html)**)** 提示:故障安全性不會拋出`ConcurrentModificationException` ,而`fail-fast`則在迭代時檢測到底層集合的外部變更時拋出 ConcurrentModificationException。 **39) Java 中迭代器和枚舉的差別? (** [**回答**](http://javarevisited.blogspot.sg/2010/10/what-is-difference-between-enumeration.html#axzz59AWpr6cb)**)** 提示:迭代器還使您能夠在迭代時刪除元素,而枚舉不允許這樣做。 **40)** **Java 中的**`**IdentityHashMap**`是什麼? **(** [**回答**](http://www.java67.com/2016/09/difference-between-identityhashmap-weakhashmap-enummap-in-java.html)**)** 提示:一個`Map` ,它使用`==`相等運算子來檢查相等性,而不是`equals()`方法。 **41)** **Java 中的**`**String**`池是什麼? **(** [**回答**](http://javarevisited.blogspot.sg/2016/07/difference-in-string-pool-between-java6-java7.html#axzz4pGGwsyna)**)** 提示: `String`文字池。請記住,它已從 JDK 7 中的永久代空間移至堆疊。 **42)** Java 中`**Serializable**`**類別可以包含不可序列化欄位嗎? (** [**回答**](http://javarevisited.blogspot.sg/2016/09/how-to-serialize-object-in-java-serialization-example.html)\*\*) \*\*提示:是的,但您需要將其設定為靜態或瞬態。 **43) Java 中 this 和 super 的差別? (**[**回答**](http://www.java67.com/2013/06/difference-between-this-and-super-keyword-java.html)**)** 提示:this 指的是目前實例,而 super 指的是超類別的實例。 **44)** **Java 中**`**Comparator**`**和**`**Comparable**`之間的差異? **(** [**回答**](http://www.java67.com/2013/08/difference-between-comparator-and-comparable-in-java-interface-sorting.html)**)** \\ 提示: `Comparator`定義自訂排序,而`Comparable`定義物件的自然順序,例如`String`字母順序。請參閱[**完整的 Java 大師課程**](https://click.linksynergy.com/fs-bin/click?id=JVFxdTr9V80&subid=0&offerid=323058.1&type=10&tmpid=14538&RD_PARM1=https%3A%2F%2Fwww.udemy.com%2Fjava-the-complete-java-developer-course%2F)以了解有關 Java 排序的更多資訊。 [![](https://miro.medium.com/max/875/1*MTR8OytpiIMidLndBnsJ5g.png)](https://click.linksynergy.com/fs-bin/click?id=JVFxdTr9V80&subid=0&offerid=323058.1&type=10&tmpid=14538&RD_PARM1=https%3A%2F%2Fwww.udemy.com%2Fjava-the-complete-java-developer-course%2F) **45)** **Java 中**`**java.util.Date**`**和**`**java.sql.Date**`之間的差異? **(**[**回答**](http://javarevisited.blogspot.sg/2012/04/difference-between-javautildate-and.html)**)** 提示:前者包含日期和時間,後者僅包含日期部分。 46)為什麼**Java中的**`**Object**`類別**中宣告了wait和notify方法**? **(**[**回答**](http://javarevisited.blogspot.sg/2012/02/why-wait-notify-and-notifyall-is.html)**)** 提示:因為它們需要僅對物件可用的鎖。 **47)為什麼Java不支援多重繼承? (** [**回答**](http://javarevisited.blogspot.sg/2011/07/why-multiple-inheritances-are-not.html)**)** 提示:它不支持,因為 C++ 的體驗不好,但對於 Java 8,它在某種意義上是支援的 --- 現在 Java 中不支援`Type`的多重繼承。 **48) Java 中檢查異常和非檢查異常的差異? (** [**回答**](http://javarevisited.blogspot.sg/2011/12/checked-vs-unchecked-exception-in-java.html)**)** 提示:如果是選取的,則必須使用 catch 區塊處理異常,而如果是未選取的,則由您決定;編譯不會打擾你。 **49) Java 中錯誤和異常的區別? (**[**回答**](http://www.java67.com/2012/12/difference-between-error-vs-exception.html)**)** 提示:我厭倦了打字,請檢查答案 **50) Java 中的競爭條件和死鎖的差異? (** [**回答**](http://javarevisited.blogspot.sg/2012/02/what-is-race-condition-in.html#axzz59AbkWuk9)**)** 提示:這兩種錯誤都是並發應用程式中發生的錯誤,一種是由於執行緒調度而發生的,另一種是由於編碼不良而發生的。請參閱[Java 中的多執行緒和平行計算](https://click.linksynergy.com/fs-bin/click?id=JVFxdTr9V80&subid=0&offerid=323058.1&type=10&tmpid=14538&RD_PARM1=https%3A%2F%2Fwww.udemy.com%2Fmultithreading-and-parallel-computing-in-java%2F),以了解有關死鎖、競爭條件和其他多執行緒問題的更多資訊。 其他資源 --- - [Java 面試指南:200+ 面試題目及答案](https://click.linksynergy.com/fs-bin/click?id=JVFxdTr9V80&subid=0&offerid=323058.1&type=10&tmpid=14538&RD_PARM1=https%3A%2F%2Fwww.udemy.com%2Fjava-interview-questions-and-answers%2F) - [Spring框架面談指南---200+問答](https://click.linksynergy.com/fs-bin/click?id=JVFxdTr9V80&subid=0&offerid=323058.1&type=10&tmpid=14538&RD_PARM1=https%3A%2F%2Fwww.udemy.com%2Fspring-interview-questions-and-answers%2F) - [準備工作面試 作者:John Sonmez](https://pluralsight.pxf.io/c/1193463/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fdeveloper-job-interviews) - [Markham 曝光的 Java 程式設計面試](http://www.amazon.com/Java-Programming-Interviews-Exposed-Markham/dp/1118722868?tag=javamysqlanta-20) - [破解編碼面試 --- 189 個問題和答案](http://www.amazon.com/Cracking-Coding-Interview-6th-Edition/dp/0984782850/?tag=javamysqlanta-20) - [求職面試的資料結構與演算法分析](https://click.linksynergy.com/fs-bin/click?id=JVFxdTr9V80&subid=0&offerid=323058.1&type=10&tmpid=14538&RD_PARM1=https%3A%2F%2Fwww.udemy.com%2Fdata-structure-and-algorithms-analysis%2F) - [過去 5 年 130 多道 Java 面試題](http://javarevisited.blogspot.sg/2015/10/133-java-interview-questions-answers-from-last-5-years.html) - [Grokking the Java Interview - 免費範例 PDF](https://javinpaul.gumroad.com/l/HMOAv) - [深入了解 Spring Boot 面試 - 免費 PDF 範本](https://javinpaul.gumroad.com/l/grokking-springboot-interview-sample) ### 結束語 謝謝,您已經讀到了文章的結尾...祝您程式設計面試順利!這當然不會很容易,但這些問題肯定會對您有所幫助。它還會鼓勵您了解更多。 如果您喜歡這篇文章,請與您的朋友和同事分享,並且不要忘記在 Twitter 上關注[javinpaul](https://twitter.com/javinpaul) ! > **PS ---**如果您需要一些免費資源來學習 Java,您可以查看[**我最喜歡的免費 Java 課程**](https://medium.com/javarevisited/10-free-courses-to-learn-java-in-2019-22d1f33a3915)清單來開始您的準備。 &gt; > **PSS ---**我沒有提供圖片中分享的面試問題的答案“程式碼中建立了多少個 String 物件?”你能猜出並解釋一下嗎? 而且,如果你今年正在準備 Java 面試,你還可以**[在 Gumroad 上取得我的 Java + Spring Interview + SQL Bundle](https://javinpaul.gumroad.com/l/sowpfg)** ,使用程式碼**friends20**也可以獲得 20% 的折扣 --- 原文出處:https://dev.to/javinpaul/50-core-java-interview-questions-with-answers-for-programmers-3bc

在 JavaScript 中建立 CLI 工具的指南

歡迎來到使用 JavaScript 的命令列介面 (CLI) 工具世界的令人興奮的旅程。 在本指南中,我將引導您建立 CLI 工具,該工具設定基本的專案結構,解釋每個步驟和程式碼片段,以確保您可以遵循。 設定您的開發環境 -------- 在我們深入 CLI 工具的世界之前,讓我們先設定我們的環境: 1. **安裝 Node.js 和 npm:**前往[Node.js 的官方網站](https://nodejs.org/en/)並下載建議的版本。安裝 Node.js 也會安裝 npm,這是您將用來處理 JavaScript 套件的套件管理器。 2. **驗證您的安裝:**開啟終端機並執行以下命令,確保所有內容均已正確安裝: ``` node --version npm --version ``` 查看版本號碼即可確認您已全部設定完畢! 建立您的 CLI 工具:專案設定自動化 ------------------- 我們的目標是建立一個能夠自動產生基本專案結構的 CLI 工具,從而省去您每次啟動新專案時手動建立資料夾和檔案的麻煩。 ### 第 1 步:啟動您的專案 1. **建立專案目錄:**這是 CLI 工具程式碼所在的位置。 ``` mkdir my-project-setup cd my-project-setup ``` 2. **初始化您的 npm 套件:**此步驟產生`package.json`文件,這對於管理專案的依賴項和配置至關重要。 ``` npm init -y ``` ### 第 2 步:建立 CLI 應用程式 1. **建立主檔案:**將此檔案命名為`index.js` 。它將包含 CLI 工具的邏輯。 2. **合併 Shebang 行:**在`index.js`的開頭新增: ``` #!/usr/bin/env node ``` ``` This line tells your system to use Node.js to execute this script. ``` 3. **實作邏輯:**下面的程式碼建立一個包含目錄和檔案的預定義專案結構: ``` const fs = require('fs'); // File System module to handle file operations // Define the project structure: directories and their respective files const projectStructure = { 'src': ['index.js'], 'public': ['index.html', 'styles.css'], }; // Iterate over the structure, creating directories and files Object.entries(projectStructure).forEach(([dir, files]) => { fs.mkdirSync(dir, { recursive: true }); // Create directories files.forEach(file => fs.writeFileSync(`${dir}/${file}`, '')); // Create files }); console.log("Project structure created successfully!"); ``` ``` Here's what each part of the code does: ``` - **需要 fs 模組:**這是 Node.js 的檔案系統模組,您將使用它來建立目錄和檔案。 - **定義專案結構:**我們指定要建立哪些目錄以及它們應包含哪些檔案。 - **建立目錄和檔案:**使用`fs.mkdirSync`和`fs.writeFileSync` ,腳本根據定義的結建置立每個目錄和檔案。 **4. 讓您的腳本可執行:**修改`package.json`以包含`"bin"`部分。這告訴 npm 哪個指令應該執行你的腳本: ``` `"bin": { ``` ``` "setup-project": "./index.js" ``` ``` }` ``` ### 第 3 步:在本地測試和連結您的工具 在分享您的工具之前,請先對其進行測試: 1. **連結您的工具:**在專案目錄中執行`npm link` 。此命令建立一個符號連結,允許您從終端中的任何位置執行 CLI 工具。 2. **執行您的工具:**只需在終端機的專案目錄中輸入`setup-project`即可。如果一切設定正確,您將看到“專案結構已成功建立!”訊息,以及提到的專案結構。 > 是的,就這樣! ### 第 4 步:增強功能 您的工具現在可以自動執行專案設置,但仍有改進的空間。考慮新增更多功能或處理使用者輸入來自訂專案結構。探索像`yargs`這樣的套件來解析命令列參數。您可以透過[此處的官方文件了解有關 yargs 的更多資訊。](https://yargs.js.org/) ### 第 5 步:在 npm 上分享您的工具 準備好與世界分享您的 CLI 工具了嗎?就是這樣: 1. **在 npm 上註冊:**如果您沒有帳戶,請在<https://www.npmjs.com/signup>建立帳戶。 2. **透過終端登入:**執行`npm login`並輸入您的 npm 憑證。 3. **發佈您的套件:**在您的專案目錄中,執行`npm publish` 。 恭喜!您的 CLI 工具現已在 npm 上提供,供所有人使用。 > 如果您已經關注我到這裡,請查看我用 Javascript 製作並發佈在 npm 上的第一個 CLI 工具:Naturalshell。 Naturalshell在您的終端中提供AI,現在無需記住shell命令! > 您可以[在此處查看 npm 套件](https://www.npmjs.com/package/naturalshell),[在此處查看 github 儲存庫](https://github.com/shreshthgoyal/naturalshell)。 > 請打 ⭐,並隨時加入新功能並與我一起在 naturalshell 上建置! > 該工具利用人工智慧來解析自然語言,並根據使用者的需求向使用者提供 shell 命令。除了提供命令之外,它還提供簡潔的解釋,確保使用者不僅知道要做什麼,而且了解其工作原理。憑藉直接在工具內編輯命令的便利性以及立即執行命令的能力,NaturalShell 提供了用戶友好、直觀的體驗 包起來 --- 您已經向使用 JavaScript 進行 CLI 工具開發的領域邁出了重要的第一步。透過建立一個簡單但實用的工具,您已經了解了建立、測試和發布 CLI 應用程式的基本知識。不斷嘗試、學習和建構。命令列是一個強大的盟友,現在,由您來指揮。快樂編碼! > 如果您發現本指南很有幫助並建立了您自己的出色 CLI 工具,我很樂意看到它!請在下面的評論部分分享您的 GitHub 儲存庫。讓我們一起建造吧! --- 原文出處:https://dev.to/shreshthgoyal/a-guide-to-building-cli-tools-in-javascript-28nn

加入我們參加 Cloudflare AI 挑戰:獎品為 3,000 美元!

我們很高興能與 Cloudflare 合作舉辦第二屆 DEV 挑戰賽 - 提供現金獎勵以及建立和認證您的 AI 技能的機會。這是一個在網路最重要和創新的平台之一之上進行建置的機會。感謝 Cloudflare 為我們的社區提供這個學習和建構的機會。 💗 **[Cloudflare AI 挑戰賽](https://dev.to/challenges/cloudflare)**將持續到 4 月 14 日,您將有機會嘗試 AI(或實際上是整隻腳,甚至一條腿)。這項挑戰有一個提示,但獲勝的方法有很多。 提示 -- 對於此挑戰,您將在[Cloudflare 工作執行緒](https://developers.cloudflare.com/workers-ai/)上部署無伺服器 AI 應用程式。您的任務是**建立一個 Workers AI 應用程式,該應用程式利用 Cloudflare 不斷增長的[開放模型](https://developers.cloudflare.com/workers-ai/models/)目錄中的 AI 任務類型。** Cloudflare 的開發平台提供了大量開放模型以及完成與文字、圖像和音訊相關的許多任務的能力。以下只是您可以執行的操作的一小部分: - 文本生成*(10+ 開放模型可供選擇!)* - 物體偵測 - 語音辨識 - 翻譯 - 和更多! ### 評審標準 所有提交的作品將根據以下標準進行評判: - 創新 - 創造力 - 底層技術展示 ### 附加獎品類別 除了能夠贏得總提示之外,您還可以爭取另外兩個獎品類別: - **多個模型:**授予每個任務利用多個模型的提交。 - **三重任務類型:**授予使用三種或更多任務類型的提交。 顯然,這些額外的獎品類別有一個主題:越多越好! 獎品 -- 我們的三位獲獎者將獲得以下獎品: **總提示獲勝者 (1)** - $1,500 禮品卡或同等金額 - 專屬開發者徽章 - 來自[DEV 商店](https://shop.forem.com)的禮物 **其他獎項類別得獎者 (2)** - $750 禮品卡或同等金額 - 專屬開發者徽章 - 來自[DEV 商店](https://shop.forem.com)的禮物 **所有提交有效提交的參與者都**將在其 DEV 個人資料中收到完成徽章。 如何參與 ---- 為了參與,您需要使用下面提供的提交範本發布貼文。作為提交的一部分,您需要在[Cloudflare Workers](https://developers.cloudflare.com/workers-ai/)或[Cloudflare Pages](https://pages.cloudflare.com/)上提供已部署的解決方案,並包含指向公共程式碼儲存庫的連結,其中包含包含安裝說明的工作自述文件。 Cloudflare 提供免費試用,無需信用卡,可讓您立即啟動並執行。 以下是任何想要直接參與的人使用的提交範本: {% cta https://dev.to/new?prefill=---%0Atitle%3A%20%0Apublished%3A%20%0Atags%3A%20cloudflarechallenge%2C%20devchallenge%2C%20ai%0A---% 0A%0A*這個%20是%20a%20submission%20for%20the%20%5BCloudflare%20AI%20Challenge%5D(https%3A%2F%2Fdev.to%2Fdevteam%2Fjoin-us-for-the-cloudflare-ai- challenge -3000 獎品-5f99)。* %0A%0A%23%23%20什麼%20I%20建置%0A%0A%3C!--%20告訴%20us%20%20你的%20app%20做了什麼!%20--%3E %0A%0A%23%23 %20Demo%0A%0A%3C!--%20Share%20a%20link%20to%20your%20deployed%20solution%20on%20Workers%20or%20Pages%2C%20and%20on%20a%20addadd%2C%20and% 20screenshot%20or%20video%20embed% 20%20您的%20app%20在這裡。%20--%3E%0A%0A%23%23%20My%20Code%0A%0A%3C!--%20顯示%20us%20the%20程式碼!%20Share%20a%20public %20link%20to%20your%20repo%20and%20be%20sure%20to%20include%20a%20README%20file%20和%20%安裝20%20%20README%20file%20和%20%20。我們%20also%20鼓勵%20you%20to%20add%20a%20license%20for% 20你的%20程式碼。%20%20--%3E%20%0A%0A%23%23%20旅程%0A% 0A%3C!--%20告訴%20us%20關於%20你的%20進程%2C%20%20任務% 20types%20and%20models%20you%20used%2C%20what%20you%20learned%2C%20anything %20you%20are%20尤其%20proud%20of%2C%20what%20you%20hope%20to%20do%20next%2C%20等。%20--%3E%0A%0A **Multiple%20Models%20and%2For%20Triple %20Task%20Types** %0A%0A%3C!--%20讓%20us%20know%20if%20your%20project%20utilized%20multiple%20models %20per%20task%20和%2Forouredifproject% 20third%20or%20more%20task%20types。%20If%20so%2C%20you%20may%20qualify%20for%20our%20additional%20prize%20 類別!%20如果%20不是%2C%200%這個%20部分。%20--%3E%0A%0A%3C!--%20團隊%20提交%3A%20請%20挑選%20one%20member%20到%20發布%20the % 20submission%20and%20credit%20隊友%20by%20listing%20他們的%20DEV%20用戶名%20直接%20in%20the%20body%20of%20the%20post。%20--%3E%0A%0A%3Cpost !--%20Don %27t%20忘記%20to%20add%20a%20cover%20image%20or%20an%20additional%20tag%20to%20this%20post%20(如果%20you%20想要)。%20-- %3E%0A%0A%3C !--%20感謝%20%20參與!%20--%3E %} Cloudflare 挑戰提交模板 {% 結束%} 請在提交之前查看我們的完整[規則、指南和常見問題解答頁面,](https://dev.to/challenges/cloudflare)以便您了解我們的參與指南和官方競賽規則(例如資格要求)。 需要技術幫助? ------- 我們鼓勵所有對挑戰有興趣的人加入[Cloudflare 開發者社群 Discord](https://discord.cloudflare.com)並進入他們的[\#devto-ai-challenge 頻道](https://discord.com/channels/595317990191398933/1224810884354936982)。這將是尋求技術協助並與使用 Cloudflare 建構的社群成員會面的地方。 重要的日子 ----- - 4 月 3 日:Cloudflare 挑戰賽開始! - 4 月 14 日:提交截止時間為太平洋夏令時間晚上 11:59 - 4 月 16 日:得獎者公佈 - 4 月 17 日:請關注下一次 DEV 挑戰 我們迫不及待想看看您建造了什麼!對挑戰有疑問嗎?請在下面詢問他們。 祝你好運,編碼愉快! --- 原文出處:https://dev.to/devteam/join-us-for-the-cloudflare-ai-challenge-3000-in-prizes-5f99

恭喜我們的前端挑戰賽獲勝者!

--- title:恭喜我們的前端挑戰賽獲勝者! 發表:真實 簡介: 感謝大家的參與!我們希望您玩得開心,感受到挑戰,並可能為您的職業檔案加入一兩件事。 標籤: frontendchallenge、devchallenge、css、javascript 封面圖片:https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yld68v14yeqhrbtttthm.png --- 不到兩週前,我們宣布了首個開發挑戰賽:[前端挑戰賽](https://dev.to/devteam/join-our-first-community-challenge-the-frontend-challenge-8be)。 我們歡迎大家參與一項或全部三項提示: - **CSS Art:**把你最喜歡的零食變成 CSS Art - **Glam Up My Markup:**採用我們提供的 HTML 並使其具有互動性 - **一位元組解釋器:**用 256 個或更少的字元解釋瀏覽器 API 或功能 我們對結果感到震驚。每個提示實際上都會產生數十個可能獲勝的提交內容。當然,每個提示只能有一名獲勝者,如下所示。 我們真的非常希望每個提交的人都能回來參加下一個前端挑戰,因為這個組中肯定有很多未來的獲勝者。 恭喜… --- @floscode 憑藉其精美的互動式 CSS 香蕉在**CSS 藝術**類別中名列前茅。哇! {% codepen https://codepen.io/flos-code/pen/VwNWYON %} 這絕對是徹頭徹尾的創意。它擴展了挑戰的概念,同時也真正切入人心。對一些靈感來自何處的精彩解釋會加分。 {% 連結 https://dev.to/floscode/the-frontend-challenge-bananas-are-the-superior-fruit-42n3 %} --- @rafajrg21 透過使我們的營地活動具有應有的互動性,贏得了**Glam Up My Markup**類別。 {% codepen https://codepen.io/Rafa-romero-dev/pen/GRLMdMd %} 該提交提供了一種易於存取、簡潔、互動的設計,在各種視窗尺寸下都很有用。 {% 嵌入 https://dev.to/rafajrg21/the-frontend-challenge-glammed-up-camp-activities-3j6j %} --- @highflyer910 以對`Intersection Observer API`的有用且簡潔的解釋贏得了**One Byte Expander**的勝利。 > `Intersection Observer API`追蹤元素何時在螢幕上可見。避免昂貴的事件處理程序。優化並保持對視口變化的反應。 > 與傳統的滾動/調整大小事件處理程序相比,它更有效率,同時更易於實現。試一試! 本提交內容將所描述的 API 與該 API 所取代的流行替代方案進行了比較和對比。充分利用分配的空間。 {% 嵌入 https://dev.to/highflyer910/intersection-observer-api-one-byte-explainer-3f5i %} 除了吹牛的權利之外,我們的獲勝者還將在其 DEV 個人資料中獲得專屬獲勝者徽章,以及他們想要從 DEV 商店的[DEV 挑戰](https://shop.forem.com/collections/dev-challenges)系列中獲得的任何禮物。 所有參與者將於本週收到參與徽章。 下一步是什麼? ------- 我們很快就會舉辦另一場前端挑戰賽!請務必關注我們的挑戰標籤,這樣您就不會錯過公告。請記住,您始終可以在以前專案的工作(尤其是學到的知識)的基礎上進行建置,因此並非一切都會丟失! {% 標籤前端挑戰 %} {% 標籤 devchallenge %} 感謝所有參與的人。 ❤️ 我們希望您玩得開心,感受到挑戰,並可能為您的職業檔案加入一兩件事。 下次見! --- 原文出處:https://dev.to/devteam/congrats-to-our-frontend-challenge-winners-2h5f

從頭開始寫簡單的程式語言 - 第 1 部分

如果您是開發人員,您就使用過程式語言。它們是讓電腦做你想做的事的好方法。也許您甚至已經深入研究過彙編或機器碼程式設計。許多人再也不想回來。但有些人想知道,我怎麼能透過做更多的低階程式來更折磨自己呢?我想更多地了解程式語言是如何製作的!開個玩笑,寫一門新語言並不像聽起來那麼糟糕,所以如果你有一點好奇心,我建議你留下來看看它是關於什麼的。 這篇文章的目的是簡單地介紹如何建立程式語言,以及如何建立自己的特殊語言。甚至可以用自己的名字命名。誰知道。 我還敢打賭,這似乎是一項令人難以置信的艱鉅任務。別擔心,因為我已經考慮過這一點。我盡力相對簡單地解釋了一切,沒有講*太多*離題的話。在這篇文章結束時,您將能夠建立自己的程式語言(將有幾個部分),但還有更多。了解幕後發生的事情會讓你更好地進行除錯。您將更能理解新的程式語言以及為何它們做出這樣的決定。如果我之前沒有提到的話,你可以擁有一種以你自己的名字命名的程式語言。而且,這真的很有趣。至少對我來說。 編譯器和解釋器 ------- 程式語言通常是高階的。也就是說,你看的不是0和1,也不是暫存器和組合程式碼。但是,您的電腦只能辨識 0 和 1,因此它需要一種方法來從您輕鬆讀取的內容轉變為機器可以輕鬆讀取的內容。該翻譯可以透過編譯或解釋來完成。 編譯是將原始語言的整個原始檔轉換為目標語言的過程。出於我們的目的,我們將考慮從全新的、最先進的語言一直編譯到可執行的機器碼。 ![簡單編譯圖](https://thepracticaldev.s3.amazonaws.com/i/c5difsv2s2rvk1iwzcih.png) 我的目標是讓「魔法」消失 解釋是或多或少直接執行原始檔中的程式碼的過程。我會讓你覺得這很神奇。 那麼,如何從易於閱讀的原始語言變成難以理解的目標語言呢? 編譯器的階段 ------ 編譯器可以透過多種方式分為多個階段,但有一種方法是最常見的。當你第一次看到它時,它的意義不大,但它是這樣的: ![編譯器的虛假階段](https://thepracticaldev.s3.amazonaws.com/i/cq1uo0x1gp7k73jldp7o.png) 哎呀,我選錯了圖,但這樣就可以了。基本上,您獲取原始文件,將其設置為計算機想要的格式(刪除空格之類的內容),將其更改為計算機可以很好地移動的格式,然後從中生成程式碼。還有更多。那是下次,或者如果你的好奇心快要殺死你的話,也可以供你自己研究。 詞法分析 ---- ### 又名“讓原始碼變得漂亮” 考慮以下完全虛構的語言,它基本上只是一個帶有分號的計算器: ``` // source.ect 3 + 3.2; 5.0 / 1.9; 6 * 2; ``` 計算機不需要所有這些。空間只適合我們狹隘的頭腦。還有新線?沒有人需要那些。電腦將您看到的程式碼轉換為可以使用的標記流,而不是原始檔案。基本上,它知道`3`是整數, `3.2`是浮點數, `+`是對這兩個值進行運算的東西。這就是計算機*真正*需要完成的全部工作。**詞法分析器**的工作是提供這些標記而不是原始程式。 它的實現方式非常簡單:給詞法分析器(詞法分析器的一種聽起來不那麼自命不凡的說法)一些期望的東西,然後告訴它當它看到這些東西時要做什麼。這些稱為*規則*。這是一個例子: ``` int cout << "I see an integer!" << endl; ``` 當 int 通過詞法分析器並執行此規則時,您將看到一個非常明顯的“我看到一個整數!”感嘆。這不是我們使用詞法分析器的方式,但看到程式碼執行是任意的很有用:沒有規則要求您必須建立某個物件並傳回它,它只是常規的舊程式碼。甚至可以用大括號括起來來使用多條線。 順便說一句,我們將使用稱為[FLEX 的](https://github.com/westes/flex)東西來進行詞法分析。它使事情變得非常簡單,但是沒有什麼可以阻止您自己編寫一個程式來執行此操作。 為了了解我們如何使用 flex,請看這個例子: ``` // scanner.lex /* Definitions */ %{ #include <iostream> using namespace std; extern "C" int yylex(); %} /* Rules next */ %% [0-9]+.[0-9]+ cout << "FLOAT: (" << yytext << ")" << endl; [0-9]+ cout << "INT: (" << yytext << ")" << endl; "+" cout << "PLUS" << endl; "-" cout << "MINUS" << endl; "*" cout << "TIMES" << endl; "/" cout << "DIVIDED BY" << endl; ";" cout << "SEMICOLON" << endl; [\t\r\n\f] ; /* ignore whitespace */ %% /* Code */ int main() { yylex(); } ``` 這引入了一些新概念,讓我們回顧一下它們: `%%`用於分隔 .lex 檔案的各個部分。第一部分是聲明 - 基本上是使詞法分析器更具可讀性的變數。這也是您導入的位置,由`%{`和`%}`包圍。 第二部分是規則,我們之前已經看過。這些基本上是一個大的`if` `else if`塊。它將執行*最長的匹配*行。因此,即使您更改 float 和 int 的順序,float 仍然會匹配,因為匹配`3.2`的 3 個字元比`3`的 1 個字元多。請注意,如果這些規則均不匹配,則會採用預設規則,只需將字元列印到標準輸出即可。然後,您可以使用`yytext`來引用它看到的與該規則相符的內容。 第三部分是程式碼,它只是在執行時執行的 C 或 C++ 原始碼。 `yylex();`是執行詞法分析器的函數呼叫。您也可以讓它從檔案中讀取輸入,但預設情況下它從標準輸入中讀取。 假設您將這兩個檔案建立為`source.ect`和`scanner.lex` 。我們可以使用`flex`命令建立一個 C++ 程式(假設您已經安裝了`flex` ),然後編譯它並輸入我們的原始程式碼以達到我們很棒的列印語句。讓我們將其付諸行動吧! ``` evan:ectlang/ $ flex scanner.lex evan:ectlang/ $ g++ lex.yy.c -lfl evan:ectlang/ $ ./a.out < source.ect INT: (3) PLUS FLOAT: (3.2) SEMICOLON FLOAT: (5.0) DIVIDED BY FLOAT: (1.9) SEMICOLON INT: (6) TIMES INT: (2) SEMICOLON evan:ectlang/ $ ``` 嘿,酷!您只需編寫將輸入與規則相符的 C++ 程式碼,以便執行某些操作。 現在,編譯器如何使用它?一般來說,每個規則都會返回一些東西,而不是打印一些東西——一個令牌!這些標記可以在編譯器的下一部分中定義... 語法分析器 ----- ### 又名“使漂亮的源程式碼可用” 是時候玩得開心了!一旦我們到達這裡,我們就開始定義程式的結構。解析器只是獲得一個標記流,它必須匹配該流中的元素,以使原始程式碼具有可用的結構。為了做到這一點,它使用了[語法](https://en.wikipedia.org/wiki/Formal_grammar),你可能在理論課上看到或聽到你奇怪的朋友閒聊的東西。它們非常強大,並且有很多東西需要了解,但我只會提供您需要了解的關於我們有點愚蠢的解析器的資訊。 基本上,語法將非終結符與終結符和非終結符的某種組合相匹配。終端是樹的葉子;非終端有孩子。如果這沒有意義,請不要擔心,程式碼可能會更容易理解。 我們將使用一個名為[Bison 的](https://www.gnu.org/software/bison/)解析器產生器。這次,為了解釋目的,我將把文件分成幾個部分。首先,聲明: ``` // parser.y %{ #include <iostream> using namespace std; extern "C" void yyerror(char *s); extern "C" int yyparse(); %} %union{ int intVal; float floatVal; } %start program %token <intVal> INTEGER_LITERAL %token <floatVal> FLOAT_LITERAL %token SEMI %type <floatVal> exp %type <floatVal> statement %left PLUS MINUS %left MULT DIV ``` 第一部分應該看起來很熟悉:我們正在導入我們想要使用的東西。之後就變得有點棘手了。 聯合是「真正的」C++ 類型到我們將在整個程式中呼叫它的類型的映射。因此,當我們看到`intVal`時,您可以將頭腦中的值替換為`int` ,而當我們看到`floatVal`時,您可以將頭腦中的值替換為`float` 。稍後你就會明白為什麼。 接下來我們來看看符號。您可以在腦海中將它們分為終結符和非終結符,就像我們之前討論的語法一樣。大寫字母表示終端,因此它們不會繼續擴展。小寫意味著非終結符,因此它們繼續擴展。這只是慣例。 每個聲明(以`%`開頭)聲明一些符號。首先,我們看到我們從一個非終端`program`開始。然後,我們定義一些標記。 `<>`括號定義回傳類型:因此`INTEGER_LITERAL`終端機回傳`intVal` 。 `SEMI`終端不會回傳任何內容。使用`type`可以對非終結符完成類似的操作,如將`exp`定義為傳回`floatVal`的非終結符時所見。 最後我們取得了優先權。我們知道 PEMDAS,或者您可能已經學過的任何其他縮寫詞,它告訴您一些簡單的優先規則:乘法在加法之前,等等。現在,我們以一種奇怪的方式在這裡聲明這一點。首先,清單中的位置越低意味著優先順序越高。其次,您可能想知道`left`是什麼意思。這就是關聯性:差不多,如果我們有`a op b op c` , `a`和`b`會在一起,還是`b`和`c`會在一起?我們的大多數運算子都執行前者,即`a`和`b`首先結合在一起:這稱為左結合性。某些運算子(例如求冪)會執行相反的操作: `a^b^c`期望您先提高`b^c`然後再提高`a^(b^c)` 。不過,我們不會處理這個問題。如果您想了解更多詳細訊息,請查看 Bison 頁面。 好吧,我可能已經厭倦了聲明,這是語法規則: ``` // parser.y %% program: /* empty */ | program statement { cout << "Result: " << $2 << endl; } ; statement: exp SEMI exp: INTEGER_LITERAL { $$ = $1; } | FLOAT_LITERAL { $$ = $1; } | exp PLUS exp { $$ = $1 + $3; } | exp MINUS exp { $$ = $1 - $3; } | exp MULT exp { $$ = $1 * $3; } | exp DIV exp { $$ = $1 / $3; } ; ``` 這就是我們之前講的文法。如果您不熟悉語法,這非常簡單:左側可以變成右側的任何內容,並用`|`分隔。 (邏輯`or` )。如果它可以走多條路徑,那就是不行的,我們稱之為*歧義語法*。由於我們的優先聲明,這並不含糊 - 如果我們更改它,使 plus 不再保持關聯,而是聲明為像`SEMI`這樣的`token` ,我們會看到發生移位/歸約衝突。想知道更多?看看Bison是如何運作的,提示,它使用LR解析演算法。 好的,所以`exp`可以是以下情況之一: `INTEGER_LITERAL` 、 `FLOAT_LITERAL`等。請注意,它也是遞歸的,因此`exp`可以變成兩個`exp` 。這允許我們使用複雜的表達式,例如`1 + 2 / 3 * 5` 。請記住,每個`exp`都會傳回一個 float 類型。 括號內的內容與我們在詞法分析器中看到的相同:任意 C++ 程式碼,但帶有更奇怪的語法糖。在這種情況下,我們有一些以`$`開頭的特殊變數。變數`$$`基本上就是回傳的內容。 `$1`是第一個參數傳回的內容, `$2`第二個參數傳回的內容,等等。我所說的「參數」是指語法規則的一部分:因此規則`exp PLUS exp`有參數 1 `exp` 、參數 2 `PLUS`和參數 3 `exp` 。因此,在程式碼執行中,我們將第一個表達式的結果加到第三個表達式中。 最後,一旦它回到`program`非終端,它將列印語句的結果。在這種情況下,程式是一堆語句,其中語句是一個表達式,後面跟著一個分號。 現在我們來編寫程式碼部分。這是當我們通過解析器時實際執行的內容: ``` // parser.y %% int main(int argc, char **argv) { if (argc < 2) { cout << "Provide a filename to parse!" << endl; exit(1); } FILE *sourceFile = fopen(argv[1], "r"); if (!sourceFile) { cout << "Could not open source file " << argv[1] << endl; exit(1); } // Sets input for flex to the file instead of standard in yyin = sourceFile; // Now let's parse it! yyparse(); } // Called on error with message s void yyerror(char *s) { cerr << s << endl; } ``` 好吧,這開始變得有趣了。我們的主函數現在從第一個參數提供的檔案而不是標準輸入中讀取,並且我們加入了一些錯誤程式碼。這是非常不言自明的,並且註釋很好地解釋了正在發生的事情,所以我將把它作為練習留給讀者來弄清楚這一點。您需要知道的是現在我們回到詞法分析器以向解析器提供標記!這是我們的新詞法分析器: ``` // scanner.lex %{ extern "C" int yylex(); #include "parser.tab.c" // Defines the tokens %} %% [0-9]+ { yylval.intVal = atoi(yytext); return INTEGER_LITERAL; } [0-9]+.[0-9]+ { yylval.floatVal = atof(yytext); return FLOAT_LITERAL; } "+" { return PLUS; } "-" { return MINUS; } "*" { return MULT; } "/" { return DIV; } ";" { return SEMI; } [ \t\r\n\f] ; /* ignore whitespace */ ``` 嘿嘿,現在確實變小了!我們看到的是,我們回傳的是終端符號,而不是列印。其中一些,例如整數和浮點數,我們首先在繼續之前設定值( `yylval`是終端符號的回傳值)。除此之外,它只是為解析器提供了一個終端標記流以供其自行決定使用。 酷,那麼讓我們執行吧! ``` evan:ectlang/ $ bison parser.y evan:ectlang/ $ flex scanner.lex evan:ectlang/ $ g++ lex.yy.c -lfl evan:ectlang/ $ ./a.out source.ect Result: 6.2 Result: 2.63158 Result: 12 ``` 我們開始了 - 我們的解析器列印出正確的值!但這並不是真正的編譯器,它只是執行 C++ 程式碼來執行我們想要的內容。為了製作編譯器,我們希望將其轉換為機器碼。為此,我們需要加入一點... 直到下次... ------- 我現在意識到這篇文章會比我想像的要長很多,所以我想我應該在這裡結束這篇文章。我們基本上有一個可用的詞法分析器和解析器,所以這是一個很好的停止點。 如果您對最終產品感到好奇,我已將原始程式碼放在[我的 Github](https://github.com/evantypanski/ectlang)上。隨著更多帖子的發布,該存儲庫將出現更多活動。 有了我們的詞法分析器和解析器,我們現在可以產生程式碼的中間表示,該中間表示最終可以轉換為真實的機器碼,我將向您展示具體的操作方法。 [第 2 部分來了!](https://dev.to/evantypanski/writing-a-simple-programming-language-from-scratch-part-2-2522) ### 其他資源 如果您想了解有關此處介紹的任何內容的更多訊息,我已經連結了一些內容以供您開始使用。我已經講了很多,所以這是我向您展示如何深入研究這些主題的機會。 - Flex 程式碼庫: <https://github.com/westes/flex> - 我們使用的詞法分析工具。 - Bison 文件: <https://www.gnu.org/software/bison/> - 我們使用的解析器產生器。這裡有很棒的文件。 - LALR 解析: <https://web.cs.dal.ca/~sjackson/lalr1.html> - 關於 LALR(1) 解析器(如 Bison 產生的解析器!)如何運作的精心解釋。 - 解決解析衝突: <http://www.cs.ecu.edu/karl/5220/spr16/Notes/Bottom-up/conflict.html> - 如何解決shift/reduce或reduce/reduce衝突,就像我們之前看到的那樣。 - Chomsky 層次結構: [https://en.wikipedia.org/wiki/Chomsky\_hierarchy](https://en.wikipedia.org/wiki/Chomsky_hierarchy) - 對此沒有詳細介紹,但我們使用了上下文無關語法,以便 Bison 可以編譯它。如果您需要上下文敏感性,那是為了後面的階段。 - 符號表: [https://www.tutorialspoint.com/compiler\_design/compiler\_design\_symbol\_table.htm](https://www.tutorialspoint.com/compiler_design/compiler_design_symbol_table.htm) - 使用符號表,編譯器如何處理變數。 哦,順便說一句,如果您不喜歡我的編譯器階段,這裡有一個實際的圖表。我仍然保留了符號表和錯誤處理程序。另請注意,許多圖表與此不同,但這最好地說明了我們所關心的內容。 ![編譯器的實際階段](https://thepracticaldev.s3.amazonaws.com/i/4bgv9blwleizrmcfw2fq.png) --- 原文出處:https://dev.to/evantypanski/writing-a-simple-programming-language-from-scratch-part-1-54a2

如果我可以重新開始,我會這樣學習 DevOps 🐳

你好,我是拉拉。我是 EngioTech 的高級 DevOps 和雲端工程師和架構師。如果您想成為 DevOps 和雲端工程師,請按照以下步驟操作。他們肯定會受益匪淺。 如果我有機會重新開始我的 DevOps 和雲端之旅,我會這樣做 😻 ![我們走吧 GIF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jw6easshgt9niiucxrda.gif) --- 1. 透過免費的 Microsoft 課程學習並獲得認證 ---------------------------- ![微軟學習](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hlbedpirx5qvf6zgbf0f.jpeg) 我首先要採取的步驟之一是透過獲得**雲端和 DevOps**認證來**鞏固我的知識**和技能。 Microsoft Learn 等平台提供了大量量身訂製的資源和課程,可協助您掌握這些技術。透過註冊此類課程,您可以獲得對 DevOps 和雲端世界的堅實基礎和實用見解。查看這些[有關 DevOps 和雲端的免費 Microsoft Learn 課程](https://learn.microsoft.com/training?wt.mc_id=studentamb_366508)。 --- 2. 實際專案實踐 --------- 通過認證建立了堅實的理論基礎後,我將深入實踐。從事現實世界的專案,無論是個人還是透過實習,對於應用所學和獲得實務經驗至關重要。這種實踐方法不僅可以加深您的理解,還可以幫助您培養 DevOps 和雲端領域中必不可少的解決問題的技能。 4. 一切自動化 -------- 自動化是 DevOps 的核心。我會盡可能專注於流程自動化,以簡化工作流程、提高效率並減少錯誤。 Ansible、Puppet 和 Jenkins 等工具對於自動化任務和部署、騰出時間進行更具策略性的工作來說非常寶貴。 --- 概括 -- 就是這個。我們傾向於把事情複雜化。透過實踐學習。參加[這些課程](https://learn.microsoft.com/training?wt.mc_id=studentamb_366508),您就已經做好了 10 倍的準備,成為工程師。 ![再見表情符號](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w1vhhdpw0nk4babg7r6r.gif) --- 原文出處:https://dev.to/larastewart_engdev/how-i-would-learn-devops-if-i-could-start-over-5amp

從開發者的角度看 Kubernetes

我們透過與事物互動和理解事物的方式來感知事物。對於基礎架構團隊來說,Kubernetes 是一種擴展和管理應用程式的好方法,但對於前端/後端開發人員來說,它可能看起來很複雜且壓力很大。 Kubernetes 引入了許多概念和術語(部署、服務、pod…),這些概念和術語需要時間來掌握,甚至需要更多時間來掌握。但開發人員有時必須每週(甚至每天)與他們互動。 透過我們的經驗和研究,我們確定了開發人員使用 Kubernetes 的三種最常見的方式。 那麼,開發人員眼中的 Kubernetes 是什麼樣子的呢? ### 支持我們🙏 ![Github 星星](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qqstf3s31okn4kzghqit.gif) 在我們開始之前,如果您為我們的[開源儲存庫](https://github.com/cyclops-ui/cyclops)加註星標並幫助我們獲得我們的產品,我們將非常高興 在其他開發者面前的工具 ⭐ 接觸點 --- 根據公司的結構和開發工作流程,開發人員要么根本不與 Kubernetes 交互,因為自動化流程和腳本正在執行此操作,要么通過三個接觸點與 Kubernetes 交互: 1. 他們的應用程式的配置文件 2. 在 K8s 叢集中部署應用程式 3. 監控他們的應用程式 ### 設定檔 ![YAML](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ugislkg1jjc9wgfiby5.png) 設定檔告訴 Kubernetes 如何處理應用程式。它們是聲明性的,這意味著您編寫您想要看到的結果,而不是實現該結果的步驟。 這些文件通常用[YAML](https://yaml.org/)編寫,它們很大且難以閱讀和理解。用 YAML 寫作會帶來挑戰(和[怪癖](https://noyaml.com/)),因為它是開發人員需要學習的額外程式語言。 配置錯誤很難發現和修正,但卻是**一件大事**。即使您對應用程式進行了完美編碼,沒有任何錯誤(假設😅),配置中的錯誤也可能意味著您的應用程式將無法執行。 ### 部署 部署應用程式是在 Kubernetes 叢集中啟動應用程式的過程。執行此操作的本機方法是使用`kubectl` 。 [`kubectl`](https://kubernetes.io/docs/reference/kubectl/)是 Kubernetes 的**命令列工具**。作為命令列工具/介面是我們應該考慮的。高級開發人員應該習慣 CLI,但初級開發人員可能仍然很膽怯。習慣`kubectl`為學習曲線增加了新的一層。 然而,部署需要的不僅僅是了解`kubectl`的可用命令;它還需要了解上下文以及它如何操作 Kubernetes 物件。 ### 監控 現在我們的開發人員已經配置並部署了他們的應用程式,他們就完成了,對吧?嗯,不。 該應用程式可能存在相當多的錯誤和問題,並且他們應該能夠監視它們並在需要時修復它們。 找出 Kubernetes 叢集內的應用程式出了什麼問題**並不簡單**。開發人員需要了解叢集中的物件以及它們如何相互互動。 例如,要取得應用程式的日誌,您需要知道它在 Pod 中執行。該 Pod 位於副本集中,副本集本身位於 Deployment 內。在使用`kubectl`翻閱 K8s 資源時,您必須了解這些關係。 開發者平台 ----- 這只是 Kubernetes 的冰山一角。它的複雜性大大延長了新開發人員的入職時間,並且引入的所有額外步驟都會減慢開發週期。 公司通常有專門的團隊來處理基礎設施和 Kubernetes。當開發人員遇到問題或需要協助時,他們會向這些團隊尋求協助。但你可以想像,在處理像 Kubernetes 這樣複雜的事情時,需要幫助是很常見的事情。 這就是為什麼我們看到開發者平台興起,它減少了開發者和基礎設施團隊之間的摩擦。一個好的平台可以使建立、更新和部署的開發週期盡可能順利和直接。 ### Cyclops - 為開發人員打造的 Kubernetes 平台 [Cyclops](https://github.com/cyclops-ui/cyclops)是一款出色的開源開發工具,它將 Kubernetes 的複雜性抽象化為簡單的圖形使用者介面。我們將其稱為平台,因為您的基礎架構團隊可以自訂 UI 以滿足您的特定需求和願望。 那麼,Cyclops是如何解決上述問題的呢? 1. 使用 Cyclops,您的開發人員永遠不會直接與設定檔互動。您建立一個模板,然後將其作為表單呈現給開發人員。這避免了學習 YAML 等語言的需要,並且還有一個額外的好處,即允許您向其輸入加入驗證,從而使開發人員更難犯錯。 2. 一旦開發人員在 Cyclops 的幫助下指定了他們的需求,部署他們的應用程式就像單擊按鈕一樣簡單。 3. 現在他們已經部署了應用程式,Cyclops 可以透過其用戶介面輕鬆監控其狀態。應用程式的詳細資訊很容易存取,包括它使用的所有資源(和日誌)。 讓我們看看它的實際效果! 安裝過程只需兩步,但有一些[先決條件](https://cyclops-ui.com/docs/installation/prerequisites),最主要的是 Kubernetes 叢集。 因此,一旦叢集啟動並執行,您就可以使用以下命令安裝 Cyclops: ``` kubectl apply -f https://raw.githubusercontent.com/cyclops-ui/cyclops/blogs-demo/install/cyclops-install.yaml ``` 一旦成功安裝(可能需要一兩分鐘),您可以透過以下方式存取它: ``` kubectl port-forward svc/cyclops-ui 3000:3000 -n cyclops ``` Cyclops 現在應該可以在瀏覽器中存取[http://localhost:3000](http://localhost:3000/) 。 現在,透過點擊`Add Module`按鈕,您將進入以下畫面: ![獨眼巨人中的新模組](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebfwzkonciqvlodmyyq2.png) 我們為您建立了一個預設模板,但此畫面是高度可自訂的(您可以嘗試[自己的 Helm 圖表](https://cyclops-ui.com/docs/installation/demo/new_module)!)。現在,開發人員無需讀取和編寫 YAML,而是可以透過點擊「儲存」按鈕填寫這些字段,然後他們的應用程式將部署! ![Cyclops 中的應用程式概述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2o1j6ous1lo06auj6gh.png) 下一個畫面顯示了新部署的應用程式的詳細視圖。在這裡,您可以查看所有指定的資源(並輕鬆存取日誌😉)。如果出現任何問題,都可以在這裡看到! 如果您希望更改配置中的某些內容(例如新增應用程式的更多副本),請按一下`Edit`按鈕。您將被帶到與第一個螢幕類似的螢幕,您可以在其中進行這些更改,甚至不知道您正在下面處理 YAML。 包起來 --- 我們希望本文能很好地展示了開發人員在 Kubernetes 中遇到的一些問題,以及您或您的開發人員下次使用它時可以考慮的潛在解決方案。 如果您遇到 Kubernetes 問題或開發人員用 K8s 相關問題糾纏您,請考慮在我們的 GitHub[儲存庫](https://github.com/cyclops-ui/cyclops)上給我們一個星星來支援我們 ⭐ 您是否遇過 Kubernetes 的這些接觸點?在下面的評論中分享您的經驗! --- 原文出處:https://dev.to/cyclops-ui/kubernetes-through-the-developers-perspective-38lf

我要告別科技業了

我試過。 我*真的*嘗試過。 2016 年,我畢業並獲得了網頁設計和開發學位,了解 Angular 和一些用戶體驗原則,認為也許我可以在技術領域有所斬獲。 我錯了。 直到兩年後我才得到第一個職位,即便如此,它是 Facebook 的合同,我必須*彌補我的職位頭銜*,我的團隊只是順其自然。不幸的是,我沒有考上合適的大學,也沒有走上實習後直接被全職僱用的正確道路。我聯繫過的任何使用者體驗專家或產品設計師都對我不屑一顧。 (你們都是守門人,不是嗎?) 疫情期間,我參加了一個編碼訓練營,天真地想:“如果我學會如何更好地編碼,我肯定會被認為更有價值!” 我完成了課程,學到了很多。建立了我的投資組合。在 Xitter 上瘋狂地交流。甚至因為在 Twitch 上直播我的想法/編碼過程而讓自己感到尷尬。 我獲得了幾個承包商的職位,這還不錯。但我想要健康保險。我更加努力了。 所有這一切都是在與過動症和重度憂鬱症作鬥爭的同時進行的。 2022 年,我終於獲得了第一份全職工作,擔任開發者關係工程師。在我的前三個月內,我為他們獲得了一份大牌公司的合約。 然而,我也試著解決我的心理健康問題。我被開了 Lexapro 和 Abilify。副作用包括嗜睡,這意味著如果我不工作,我就會睡覺。但如果我不覺得自己想要公里,那麼它就有效,對吧?讓我們在上面撒上 Adderall XR 來解決討厭的過動症。十月,我不得不停止服藥,因為我和我的配偶決定要生孩子。 我想:“我對自己的工作感覺很好!我們很穩定!讓我們開始吧!” 2023年5月,我發現自己懷孕了。我覺得我經歷了懷孕帶來的一些最嚴重的副作用:腦霧、疲憊、噁心——TL;DR:我無法工作。我立即告訴我的經理和人力資源部,認為完全誠實並「掩蓋我的基地」是謹慎的做法,以防我的生產力下降。 嗯,當然是這樣。將一個 10 磅重的米袋綁在腹部,在小辦公椅上旋轉 20 次,並嘗試召開一個小時的會議。 起初,我的同事們(據說)為我感到高興,並表示「支持」。然而,事情慢慢開始改變。我的經理一天比一天變得越來越挑剔。我很難控制自己的症狀並保持板著臉。 您是否曾經歷過有人告訴您他們會在您身邊,但當您需要他們時卻沒有真正出現?這就是發生在我身上的事。 九月,我接受了 PIP。同時,血液檢查結果顯示我或我的孩子身上有腫瘤。或者他有脊椎先天缺陷。我必須立即進行廣泛的測試才能找到問題。 那,我必須努力保住我的工作嗎? 我真誠地盡力了。最後,我只是把事情結束了,就像一篇我從未發表過的文章,很可能被同事偷走了。 經理可以說:“如果你感覺不舒服,那就休息一天!使用你的 PTO!”任何時候都只是為了掩飾他們的屁股。 現在我告訴你:人力資源和管理階層永遠不會支持你。 ------------------------ 不要被他們的廢話所迷惑。 不要告訴你的同事任何事。 科技環境中沒有什麼是穩定的。在工作場所的任何地方,*沒有人*是你可以與之分享個人生活的人。它瘋了,閉嘴。 零同理心。 科技領域不存在股權。 ---------- ### 需要徹底改革對有需要的人的支持,特別是那些神經分歧的人。尤其是那些選擇成為父母並且是親生父母的人。 但是,為了實現這一目標,這種改變需要是*巨大的*、*漸進的*,並由受社區尊重的人來領導。 那個人顯然不是我。 ### 所以這是我對科技的告別。 ### 我再也不想回答任何男人了。 我不會去不受歡迎的地方。 祝福您在職涯中一切安全、心智健全。 --- 原文出處:https://dev.to/cat/a-goodbye-to-tech-41gh

令人難以置信的 JavaScript 動畫庫

概述 -- JavaScript 動畫庫已成為開發人員的必備工具,旨在透過迷人的互動式視覺元素來豐富 Web 應用程式。這些庫的發展極大地簡化了動畫過程,使其更易於存取。透過利用適當的函式庫,開發人員能夠製作令人印象深刻的動畫,從而增強網站和應用程式的參與度和使用者體驗。 動畫有可能大幅改變網站的美感和氛圍。當明智地利用它們來增強用戶體驗時,它們就會成為寶貴的資產。動畫在吸引註意力和增加網站停留時間方面特別有效,從而增加流量。 GSAP ------ ![總體規劃計劃](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p88xykg0uhg90oj4xckg.png) [GSAP(GreenSock 動畫平台)](https://greensock.com/gsap/)作為領先且強大的 JavaScript 動畫庫脫穎而出,專為速度和效率而設計。它擁有一系列功能,包括基於時間軸的動畫、SVG 支援和緩動功能。 GSAP 提供了各種預先設計的工具和功能,即使是網頁動畫新手也能快速有效地建立複雜的動畫。 GSAP 有助於跨 jQuery、Canvas 和 SVG 建立精美的高效能動畫。它與其他軟體和函式庫相容,例如[PixiPlugin](https://greensock.com/docs/v2/Plugins/PixiPlugin) 、 [WebGL](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API) 、 [EaseJS](https://createjs.com/easeljs)等。 ### 好處 - 輕便快捷 - 廣泛的功能 - 可透過插件擴展 - 適應各種螢幕尺寸 - 支援所有主流瀏覽器 Anime.js ----- ![動漫.js](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9suyvmlz3kzt9tooinls.png) [Anime.js](https://animejs.com/)以其簡單、速度和多功能性而聞名。這個緊湊的庫簡化了動畫過程,使開發人員能夠以最少的努力製作出視覺上引人注目的動畫。 Anime.js 支援多種效果,例如縮放、變形和旋轉,為開發人員提供了輕鬆建立複雜時間軸和動畫的工具。 ### 好處 - 直覺的API - 結構緊湊、適應性強 - 豐富的功能集 - 插件就緒架構 - 支援所有主流瀏覽器 Three.js ---- ![三.js](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uqy0o2cm5obswsc9kp3y.png) [Three.js](https://threejs.org/)致力於產生 3D 視覺效果,提供一套強大的功能和工具。它建立在[WebGL](https://get.webgl.org/)之上,優化 GPU 使用以實現快速渲染,確保跨裝置(包括資源有限的裝置)的流暢效能。 Three.js 的多功能性允許建立廣泛的 3D 圖形和動畫,從簡單的形狀到複雜的模型。 Popmotion.io ------------ ![popmotion.io](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9u79jz8iilrbp65zx4h5.png) [Popmotion](https://popmotion.io/)在設計中優先考慮簡單性和易用性。它用[TypeScript](https://www.typescriptlang.org/)編寫,與任何接受數位輸入的 API 相容,提供簡單的 API 並支援主要瀏覽器。 Popmotion 的架構為[Framer Motion](https://www.framer.com/motion/)中的動畫提供支持,並且可以透過外掛程式進行擴充。 ### 好處 - 使用者友善的介面 - 可擴充的插件框架 - 響應式設計 - 支援所有主流瀏覽器 反應彈簧 ---- ![反應彈簧](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ny6fonq8dw3udlcejqfn.png) [React-spring](https://www.react-spring.dev/)專為 React 應用程式量身定制,透過其簡單的 API 提供跨所有主要瀏覽器的無縫動畫體驗。它不僅迎合 Web 環境,還支援 React-Native、React-Three-Fiber、React-Konva 和 React-ZDog。它的 TypeScript 基礎有助於輕鬆整合到現有專案中。 ### 好處 - 簡單易懂 - 啟用插件以增加功能 - 跨裝置回應 - 支援所有主流瀏覽器 Vivus - ![活](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t4zdqw3xeq1vxrrlgx1u.png) [Vivus](https://maxwellito.github.io/vivus/)專注於 SVG 動畫,具有易於使用的 API,確保跨所有主要瀏覽器的兼容性。它支援各種動畫樣式,例如延遲、同步或 OneByOne,並允許為每個 SVG 路徑自訂動畫腳本。 ### 好處 - 毫不費力地實施 - 插件擴充性 - 專用的 SVG 動畫功能 - 支援所有主流瀏覽器 Mo.js ----- ![Mo.js](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v3rhzp2ggqfy8t61fvkd.png) [Mo.js](https://mojs.github.io/)是一個強大且適應性強的 JavaScript 動畫庫,具有簡單的 API 和瀏覽器支援。它以其高性能動畫和與密度無關的效果而著稱,確保在任何設備上都有出色的視覺品質。 Mo.js 提供了廣泛的動畫建立工具,包括用於動畫控制的播放器、曲線編輯器和用於自訂緩動和編輯的時間軸編輯器。 ### 好處 - 強大而靈活 - 直覺的API - 插件相容 - 專為響應式環境設計 - 支援所有主流瀏覽器 結論 -- 為您的專案選擇正確的動畫庫可能是一項艱鉅的任務。還有許多其他 JavaScript 動畫庫可用,每個庫都具有獨特的特性和功能。 您是否有此處未提及的最喜歡的圖書館?請在下面的評論中分享。我總是渴望探索新工具並擴展我的工具包! 如果您發現這有幫助並願意給我的專案一顆星以支持,我將不勝感激! [黏土主題🚀](https://github.com/lilxyzz/clay-theme) --- 原文出處:https://dev.to/lilxyzz/incredible-javascript-animation-libraries-30on

⚛️ 解釋 React 的類型

React 的類型系統與 TypeScript 一起使用時,為開發人員提供了建構類型安全應用程式的強大框架。了解各種 React 類型之間的細微差別對於就其使用做出明智的決策至關重要。讓我們深入詳細比較這些類型,以了解它們的差異和適當的用例。 1️⃣ React.FC 與 React.ElementType -------------------------------- ### React.FC(React.FunctionComponent) `React.FC`是React中專門用來定義函數元件的類型。當 React Hooks 被引入並廣泛採用時,它開始變得更加流行。 在 React 18 之前,它曾經包含一個隱式的`children`屬性,使其適合預期有孩子的元件。但很長一段時間以來,隱式的`children` prop類型已經根據[React 18的類型變化](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210)被刪除了。 這是一個使用範例: ``` interface SomeComponentProps { title: string; children?: React.ReactNode; } export const SomeComponent: React.FC<SomeComponentProps> = ({ title, children }) => { return ( <article> <h2>{title}</h2> {children} </article> ); }; ``` 然而,由於刪除了隱`children` prop 類型,現在使用`React.FC`的人少了很多,因為與直接將介面分配給 props 物件相比,它很笨重並且沒有提供任何真正的好處: ``` interface SomeComponentProps { title: string; children?: React.ReactNode; } export const SomeComponent = ({ title, children }: SomeComponentProps) => { return ( <article> <h2>{title}</h2> {children} </article> ); }; ``` ### React.ElementType 另一方面, `React.ElementType`是一種更廣泛的類型,表示可以由 React 呈現的任何元件類型。這不僅包括 React 函數和類別元件,還包括 HTML 元素的字串標籤(例如「div」、「span」)。當您想要接受元件作為 prop 並渲染它時, `React.ElementType`特別有用,允許動態元件使用。 ``` const DynamicComponent: React.ElementType = 'div'; export const Container = () => ( <DynamicComponent className="container">Hello, world!</DynamicComponent> ); ``` 在這裡, `DynamicComponent`的類型為`React.ElementType` ,允許它動態分配給不同類型的元件或 HTML 元素。 ### 比較筆記 - `React.FC`主要用於定義功能元件。從 React 18 開始,它不再那麼有用了。 - `React.ElementType`在接受各種可渲染實體方面提供了更大的靈活性。當您需要可以動態接受不同類型的 React 元件或 HTML 元素的東西時,請使用`React.ElementType` 2️⃣ React.ReactNode vs React.ReactElement vs JSX.Element -------------------------------------------------------- ### React.ReactElement `React.ReactElement`是一個具有`type` 、 `props`和`key`屬性的物件,由`React.createElement()`函數建立。與`React.ReactNode`相比,它是一種更具體的類型,表示可以由 React 直接渲染的元素。 ``` const elementContent: React.ReactElement = <div>Hello, React.ReactElement!</div>; export const Container = () => <>{elementContent}</>; ``` ### React.ReactNode `React.ReactNode`是最具包容性的類型,代表任何可以由 React 渲染的東西。這包括原始類型(字串、數字、布林值)、 `JSX.Element` 、 `React.ReactElement` 、這些類型的陣列等等。這是道具的首選類型,可以接受各種內容,例如`children` 。 ``` const multiElementContent: React.ReactNode = ( <div> <p>This is a paragraph.</p> {'This is a text node.'} {null} </div> ); const primitiveTypeContent: React.ReactNode = "I'm a primitive-type React.ReactNode"; export const Container = () => { return ( <> {multiElementContent} {primitiveTypeContent} </> ); }; ``` 下面的維恩圖描述了`React.ReactNode`和`React.ReactElement`之間的關係: ![React.ReactNode 與 React.ReactElement](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rw8khfxekei6wydxqkmb.png) ### JSX.Element `JSX.Element`本質上是一個具有更廣泛定義的`React.ReactElement` ,允許各種程式庫以自己的方式實作 JSX。它是 TypeScript 內部使用的類型,用於表示 JSX 表達式的傳回類型。 ``` const jsxElement: JSX.Element = <span>Hello, JSX.Element!</span>; export const Container = () => <>{jsxElement}</>; ``` ### 比較筆記 - `React.ReactNode`是最靈活、最具包容性的,適合像孩子一樣可以接受多樣化內容的打字props。 - `React.ReactElement`和`JSX.Element`更具體, `React.ReactElement`適用於 React 建立的元素,而`JSX.Element`適用於使用 JSX 語法定義的元素。 💡有趣的事實 ------ - 函數元件的傳回值(也稱為渲染過程的結果)始終是`React.ReactNode`或`React.ReactElement` / `JSX.Element` 。基本上,函陣列件可以理解為: ``` type ReactFC<P = {}> = (props: P) => React.ReactNode; ``` - 像任何常規函數一樣呼叫函數元件會得到與使用 JSX 語法相同的結果,這意味著: ``` const MyComponent = ({ children }: { children: React.ReactNode }) => { return <div>{children}</div>; }; export const App = () => { return ( <div> <MyComponent> Rendering MyComponent with <strong>JSX Syntax</strong> </MyComponent> </div> ); } ``` 是相同的: ``` const MyComponent = ({ children }: { children: React.ReactNode }) => { return <div>{children}</div>; }; export const App = () => { return ( <div> {MyComponent({ children: ( <> Rendering MyComponent by  <strong>Invoking Function Component</strong> </> ), })} </div> ); } ``` 🏁 結論 ---- 了解這些 React 類型和介面之間的差異可以讓開發人員做出更明智的決策,從而產生更乾淨、更易於維護的程式碼。無論您是定義元件、接受動態內容還是處理子元件,選擇正確的類型對於充分發揮 React 和 TypeScript 的潛力至關重要。 請期待我即將發表的文章,這些文章將更深入地探討利用這些類型的理解的模式。 --- 原文出處:https://dev.to/itswillt/explaining-reacts-types-940

在本機上使用 HTTPS 的非常簡單的方法

測試您的網站在本機電腦上是否運作良好始終是一項繁重的工作。 我找到了一個非常簡單的工具[mkcert](https://github.com/FiloSottile/mkcert) : ``` ➜ localhost-https mkcert -install Using the local CA at "/Users/.../mkcert" ✨ The local CA is now installed in the system trust store! ⚡️ The local CA is now installed in the Firefox trust store (requires browser restart)! 🦊 The local CA is now installed in Java''s trust store! ☕️ ➜ localhost-https mkcert localhost Using the local CA at "/Users/.../mkcert" ✨ Created a new certificate valid for the following names 📜 - "localhost" The certificate is at "./localhost.pem" and the key at "./localhost-key.pem" ✅ ``` 然後你可以用一個簡單的 HTML 頁面來測試: ``` ➜ localhost-https cat index.html ───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ File: index.html ───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 1 │ <html> 2 │ <body> 3 │ HELLO WORLD 4 │ </body> 5 │ </html> ───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ➜ localhost-https ./node_modules/http-server/bin/http-server -S -C ./localhost.pem -K ./localhost-key.pem [18:12:41] Starting up http-server, serving ./ through https Available on: https://127.0.0.1:8080 https://192.168.1.69:8080 Hit CTRL-C to stop the server ``` 這是結果: ![](https://thepracticaldev.s3.amazonaws.com/i/1z5km8xkhgqqwgyrm80i.png) FiloSottile/mkcert --- 原文出處:https://dev.to/rhymes/really-easy-way-to-use-https-on-localhost-341m

軟體工程師,儘量避免職業倦怠吧!

沒有什麼神奇的方法可以解決職業倦怠。我們都有不同的願望、目標、動機和壓力來源。 這是一個簡短的故事,講述了我如何改變自己的觀點,並且透過這樣做,成功地應對了我的倦怠。 **除了顯而易見的事情之外,我們還能從工作中得到什麼? 💸** 成就感和價值感。在某種程度上,我們所有人都是由我們的工作定義的。我們怎麼能不呢?我們需要證明自己,發展我們的職業生涯,在我們所做的事情上做到最好,我們的貢獻得到認可和重視。通常,我們花在工作上的時間比陪伴家人的時間還要多。 如果你問我的話,這就是一個滑坡,因為,如果我們所做的工作對我們的要求超出了我們的能力,該怎麼辦?我們就接受這一點嗎?我們是否認為事情會及時好轉,而這只是暫時的挫折,因為某些根本原因可能與我們的能力無關?我們是否告訴自己,我們正在盡力而為,一切最終都會成功? 我不。至少我沒有。 相反,我覺得自己很失敗。但是,不要害怕!解決方案很簡單。只要多花一些時間,把問題帶回家來完成更多的事情,事情就會變得更好,你的努力也會得到認可。正確的? 一旦我感覺自己正在失去立足點,再多的額外工作時間也不會讓我感覺自己不再是一個不應該出現在這裡、隨時都會被發現的冒名頂替者。 然後我意識到。我從未被發現。這意味著要么我是有史以來最好的騙子,要么我用一個不可能的標準來要求自己。 **🌟小里程碑** 當我還在上大學時,我就開始了我的第一份工作,擔任軟體工程師。一切都是挑戰,也是我必須解決的有趣難題。儘管扮演偵探很有趣,但我注意到當我回家時它並沒有停止。某些後台進程始終在執行。它變得很累。同事們向我保證,這是“正常的”和“自然的”,因為那“就是工作”。我有一段時間相信了他們。 但為什麼要「正常」或「自然」呢?我從來沒有同意把所有的時間都花在工作上,無論是主動還是被動。因此,為了避免這種情況,我的第一個嘗試就是繼續工作,直到完成我開始的事情。這導致了相當多的加班,但它確實達到了目的。然後它演變成甚至不開始任何我知道在一天結束之前無法完成的事情。直到今天我仍然在做這件事——但我在此基礎上做了一些改進。 我沒有將每張票視為一個整體,而是將每張票視為自己的一個小專案。這樣,即使票據尚未完成,四分之三的整個里程碑也已完成,現在是下午 5 點,我可以關閉我的筆記型電腦,直到明天才考慮它。 **💚 照顧好自己** 聽你自己說。如果你需要休息一下——休息一下。如果你生病了,請病假並恢復到100%。我的意思是 100%,而不僅僅是勉強生存。 請病假並不違法,儘管有時可能會感覺像這樣。您的同事將幫助您度過幾天,直到您的身體得到所需的應得的休息。 假期也是如此。總是預訂假期——有一些值得期待的事情。定期花時間休息並遠離一切事情對於一個人的生產力和幸福感非常重要。 如果你不能再做的話,世界就不會停止。 **❗盡力而為,但不要全力以赴** 我怎麼強調都不為過。每當我開始新工作時,我總是需要證明自己,展示我能做多少。只要您每天都能保持這個速度,那就太棒了。 一旦出現問題,你的產出下降,每個人都會感到非常驚訝,並期望你盡快回到「原來的自己」。這通常會給我帶來進一步的壓力,導致我的產出下降得更低,直到我必須休息幾週來恢復。 所以我認為這不是最佳的或可持續的。我付出了一點努力來找到適合每個人的配速。這種節奏不會讓我筋疲力盡,我可以始終如一地跟上,並以足夠的時間間隔提供輸出。 然後,當假設的事情發生時,我的體重就不再是問題了,然後持續幾週,然後恢復到我舒適、高效的節奏,這不會對我的健康造成損害。 **🕔 這只是工作** 就那麼簡單。今天是這家公司,明天就是那家公司。我們本質上是在盡我們最大的能力出賣我們的時間和技能,為自己提供在空閒時間做我們喜歡做的事情的手段。 我們生命中最美好的事情應該是那些在我們沒有出售的時候發生的事情。如果我們不能享受屬於我們的時間,如果我們不能以充實的方式與我們所愛的人一起度過,那麼我們工作是為了什麼? 歸根結底,這確實只是工作。 --- 原文出處:https://dev.to/netcat5679/it-is-just-work-3k0k

React 元件設計模式 - 第 1 部分

React 設計模式是開發人員用來解決使用 React 建立應用程式時遇到的常見問題和挑戰的既定實踐和解決方案。這些模式封裝了針對重複出現的設計問題的可重複使用解決方案,從而提高了可維護性、可擴展性和效率。它們提供了一種結構化的方法來組織元件、管理狀態、處理資料流和最佳化效能。 **請考慮以下 6 種 React 設計模式:** 1. 容器和呈現模式 2. HOC(高階元件)模式 3. 複合元件模式 4. 提供者模式(使用提供者進行資料管理) 5. 狀態減速器模式 6. 元件組成模式 1. 容器和呈現模式 ---------- 在此模式中,容器元件負責管理資料和狀態邏輯。它們從外部來源獲取資料,在必要時對其進行操作,並將其作為 props 傳遞給展示元件。它們通常連接到外部服務、Redux 儲存或上下文提供者。 另一方面,展示元件僅專注於 UI 元素的展示。他們透過 props 從容器元件接收資料,並以視覺上吸引人的方式呈現它。展示元件通常是無狀態的功能元件或純元件,這使得它們更容易測試和重複使用。 **讓我們考慮一個複雜的範例來說明這些模式:** 假設我們正在建立一個社群媒體儀表板,用戶可以在其中查看朋友的貼文並與他們互動。以下是我們建立元件的方式: **容器元件(FriendFeedContainer):** 該元件將負責從 API 獲取有關好友貼文的資料、處理任何必要的資料轉換以及管理提要的狀態。它將相關資料傳遞給展示元件。 ``` import React, { useState, useEffect } from 'react'; import FriendFeed from './FriendFeed'; const FriendFeedContainer = () => { const [friendPosts, setFriendPosts] = useState([]); useEffect(() => { // Fetch friend posts from API const fetchFriendPosts = async () => { const posts = await fetch('https://api.example.com/friend-posts'); const data = await posts.json(); setFriendPosts(data); }; fetchFriendPosts(); }, []); return <FriendFeed posts={friendPosts} />; }; export default FriendFeedContainer; ``` **展示元件(FriendFeed):** 該元件將從其父容器元件 (FriendFeedContainer) 接收好友貼文資料作為 props,並以視覺上吸引人的方式呈現它們。 ``` import React from 'react'; const FriendFeed = ({ posts }) => { return ( <div> <h2>Friend Feed</h2> <ul> {posts.map(post => ( <li key={post.id}> <p>{post.content}</p> <p>Posted by: {post.author}</p> </li> ))} </ul> </div> ); }; export default FriendFeed; ``` 透過以這種方式建立我們的元件,我們將獲取資料和管理狀態的問題與 UI 渲染邏輯分開。這種分離使得我們的 React 應用程式在擴充時可以更輕鬆地進行測試、重複使用和維護。 2.HOC(高階元件)模式 ------------- 高階元件 (HOC) 是 React 中的一種模式,可讓您跨多個元件重複使用元件邏輯。它們是接受元件並傳回具有附加功能的新元件的函數。 為了示範 HOC 在具有 React hook 的社群媒體儀表板範例中的使用,讓我們考慮一個場景,其中您有多個元件需要從 API 取得使用者資料。您可以建立一個 HOC 來處理資料獲取並將獲取的資料作為 props 傳遞給包裝的元件,而不是在每個元件中重複取得邏輯。 這是一個基本範例: ``` import React, { useState, useEffect } from 'react'; // Define a higher-order component for fetching user data const withUserData = (WrappedComponent) => { return (props) => { const [userData, setUserData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { // Simulate fetching user data from an API const fetchData = async () => { try { const response = await fetch('https://api.example.com/user'); const data = await response.json(); setUserData(data); setLoading(false); } catch (error) { console.error('Error fetching user data:', error); setLoading(false); } }; fetchData(); }, []); return ( <div> {loading ? ( <p>Loading...</p> ) : ( <WrappedComponent {...props} userData={userData} /> )} </div> ); }; }; // Create a component to display user data const UserProfile = ({ userData }) => { return ( <div> <h2>User Profile</h2> {userData && ( <div> <p>Name: {userData.name}</p> <p>Email: {userData.email}</p> {/* Additional user data fields */} </div> )} </div> ); }; // Wrap the UserProfile component with the withUserData HOC const UserProfileWithUserData = withUserData(UserProfile); // Main component where you can render the wrapped component const SocialMediaDashboard = () => { return ( <div> <h1>Social Media Dashboard</h1> <UserProfileWithUserData /> </div> ); }; export default SocialMediaDashboard; ``` 在這個例子中: - `withUserData`是一個高階元件,用於處理從 API 取得使用者資料。它包裝傳遞的元件 ( `WrappedComponent` ) 並將取得的使用者資料作為 prop ( `userData` ) 提供給它。 - `UserProfile`是一個功能元件,它接收`userData`屬性並顯示使用者設定檔資訊。 - `UserProfileWithUserData`是透過使用`withUserData`包裝`UserProfile`傳回的元件。 - `SocialMediaDashboard`是主要元件,您可以在其中呈現`UserProfileWithUserData`或任何其他需要使用者資料的元件。 使用此模式,您可以輕鬆地跨社交媒體儀表板應用程式中的多個元件重複使用資料取得邏輯,而無需重複程式碼。 3. 複合元件模式 --------- React 中的複合元件模式是一種設計模式,可讓您建立協同工作以形成有凝聚力的 UI 的元件,同時仍保持明確的關注點分離並提供自訂元件行為和外觀的靈活性。 在此模式中,父元件充當一個或多個子元件(稱為「複合元件」)的容器。這些子元件協同工作以實現特定的功能或行為。複合元件的關鍵特徵是它們透過父元件彼此共享狀態和功能。 以下是使用 hooks 在 React 中實作複合元件模式的簡單範例: ``` import React, { useState } from 'react'; // Parent component that holds the compound components const Toggle = ({ children }) => { const [isOn, setIsOn] = useState(false); // Function to toggle the state const toggle = () => { setIsOn((prevIsOn) => !prevIsOn); }; // Clone the children and pass the toggle function and state to them const childrenWithProps = React.Children.map(children, (child) => { if (React.isValidElement(child)) { return React.cloneElement(child, { isOn, toggle }); } return child; }); return <div>{childrenWithProps}</div>; }; // Child component for the toggle button const ToggleButton = ({ isOn, toggle }) => { return ( <button onClick={toggle}> {isOn ? 'Turn Off' : 'Turn On'} </button> ); }; // Child component for the toggle status const ToggleStatus = ({ isOn }) => { return <p>The toggle is {isOn ? 'on' : 'off'}.</p>; }; // Main component where you use the compound components const App = () => { return ( <Toggle> <ToggleStatus /> <ToggleButton /> </Toggle> ); }; export default App; ``` 在這個例子中: - `Toggle`是保存複合元件( `ToggleButton`和`ToggleStatus` )的父元件。 - `ToggleButton`是負責渲染切換按鈕的子元件。 - `ToggleStatus`是另一個負責顯示切換狀態的子元件。 - `Toggle`元件管理狀態 ( `isOn` ) 並提供`toggle`功能來控制狀態。它克隆其子級並將`isOn`狀態和`toggle`函數作為 props 傳遞給它們。 透過使用複合元件模式,您可以建立可重複使用和可組合的元件,封裝複雜的 UI 邏輯,同時仍允許自訂和靈活性。 ### 4. Provider Pattern(使用Provider進行資料管理) React 中的提供者模式是一種設計模式,用於跨多個元件管理和共用應用程式狀態或資料。它涉及建立一個封裝狀態或資料的提供者元件,並透過 React 的上下文 API 將其提供給其後代元件。 讓我們透過一個範例來說明 React 中用於管理使用者身份驗證資料的 Provider 模式: ``` // UserContext.js import React, { createContext, useState } from 'react'; // Create a context for user data const UserContext = createContext(); // Provider component export const UserProvider = ({ children }) => { const [user, setUser] = useState(null); // Function to login user const login = (userData) => { setUser(userData); }; // Function to logout user const logout = () => { setUser(null); }; return ( <UserContext.Provider value={{ user, login, logout }}> {children} </UserContext.Provider> ); }; export default UserContext; ``` 在這個例子中: - 我們使用 React 的`createContext`函數來建立一個名為`UserContext`上下文。此上下文將用於跨元件共享用戶資料和與身份驗證相關的功能。 - 我們定義一個`UserProvider`元件作為`UserContext`的提供者。該元件使用`useState`鉤子管理使用者狀態,並提供`login`和`logout`等方法來更新使用者狀態。 - 在`UserProvider`內部,我們用`UserContext.Provider`包裝`children` ,並將`user`狀態以及`login`和`logout`函數作為提供者的值傳遞。 - 現在,任何需要存取使用者資料或驗證相關功能的元件都可以使用`useContext`掛鉤來使用`UserContext` 。 讓我們建立一個使用上下文中的使用者資料的元件: ``` // UserProfile.js import React, { useContext } from 'react'; import UserContext from './UserContext'; const UserProfile = () => { const { user, logout } = useContext(UserContext); return ( <div> {user ? ( <div> <h2>Welcome, {user.username}!</h2> <button onClick={logout}>Logout</button> </div> ) : ( <div> <h2>Please log in</h2> </div> )} </div> ); }; export default UserProfile; ``` 在此元件中: 我們匯入`UserContext`並使用`useContext`鉤子來存取`UserProvider`提供的使用者資料和`logout`功能。 根據使用者是否登錄,我們呈現不同的 UI 元素。 最後,我們用`UserProvider`包裝我們的應用程式,以使用戶資料和身份驗證相關的功能可供所有元件使用: ``` // App.js import React from 'react'; import { UserProvider } from './UserContext'; import UserProfile from './UserProfile'; const App = () => { return ( <UserProvider> <div> <h1>My App</h1> <UserProfile /> </div> </UserProvider> ); }; export default App; ``` 透過這種方式,Provider 模式允許我們跨多個元件管理和共享應用程式狀態或資料,而無需進行 prop 鑽取,從而使我們的程式碼更乾淨、更易於維護。 --- 原文出處:https://dev.to/fpaghar/react-component-design-patterns-part-1-5f0g

歡迎串 Part.16 👋👋👋

歡迎最近新註冊的用戶 @id3p6688 @katiewilson8210 @linejkf552 @tws9666 @8945689 @swotoutty @leemotseng @bear645 @jf76501 @assdee @kk00336 @Adjutle @imxp978 @jeff858484 @ytb0315 @Iven10252158 @AppleLily @wmw588ss52 @Weboai @1891722 @react @cian1223 @dd2d2d41 @vincentchen0606 @slinexm594 @sunmoonsky @reelvetut @4000889 @HansChang83 @wsx1688 @zc235475 @jensen @idziq888 @s1s2s4s5h @Imardaxia @vidmateApk @Skylar0628 @z2837777 @pikashowsapk1 @instaproapps @Vidmateapp @pon0620 @PikaShow23 @Excarrath @tenkai0812 @ScottX8 @Hannahdrorn @Learn20240303 @simon5537 @arielh1004 @hhkwe1 @line771554 @kinemasters @kgi-design-team @doochulk @pdmod @Cartinson @futemaxapk @av0988 @kinemastersapk @Taulinip @rectvindir @rhwang @Chengyi-Lin @nfc851026 @lanni0619 @max002215 @lline966757 @Luckypatcher1s @gary880306 @zzliou @hdstreamzapk03 @PinoyLambingan @aaronzhan0906 @lu4707xeop @Mia1314echooo @TsuPeiHo @roynitisha29 @ovallyfef @qun18009 @nozomi @Aaron @Filmy4WapAPK1 @lu10510 @joeyoldbar @prochini @Yutai @sherry860722 @hzf9Nf5P @yunie0216st @pikashowshd @Kuo-TingKai @alexwu @chelsea22222 @zoetanghk852 @MagicBenson @xd890872680 @Nehaambore01 @Note @shabazsayyed @1084926 @kenni1107 @0711kps @Shuntw6096 @capcutt @TopFollowAPK @YICHI1018 @kaede1904 @HxVfHNMpK @universitykart0101 @pikashowapks @ishad1 @GustavoFringgg @skrbomb @Luckypatcherapk @wwertytrd3 @av9397 @Asn66 @MarioooooLin @snapptube891 歡迎在留言處簡單自介一下~ 可以說一下從哪邊發現這論壇的~最近在學什麼東西~或者是關於你的一件小趣事~ 也請大家多多回覆別人的留言,問別人小問題,或者回個「嗨嗨 👋」都很好~ **歡迎各位加入這個技術成長社群!**

40 多種設計工具合而為一 - 😱 Web 開發人員和設計師的瑰寶

![標頭](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ep40ea9k26mx8rjhc77t.png) **你好👋開發者**!歡迎來到我的另一篇部落格文章。 我是[Md Taqui Imam](https://mdtaquiimam.vercel.app/) ,由於這幾天很忙,我一直沒有在開發中發布任何部落格。 因此,在這篇文章中,我想向您介紹一個令人興奮的新網站,該網站擁有**40 多種設計工具**,而且好處是所有**工具都是免費的**。 所以讓我們開始👇,不要**忘記**「💖🦄🔥」。 --- [fffuel.co🤪](https://fffuel.co/) -------------------------------- 我知道這個名字有點奇怪😅順便說一句,fffuel 是一個顏色**工具和免費**SVG 生成器的集合,用於漸變、圖案、紋理、形狀和背景。 ![截圖](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tf434tlpk41lpawvgqfp.jpeg) 它有 40 多個工具,例如 👇 --------------- 請參閱下面顯示的一些工具。 **1. tttexture - 免費垃圾、復古和具體紋理的集合** ![tt紋理](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/81hwqw4dkkih6fs7egsf.jpeg) --- **2. aaabstract - 🌊 製作波浪形抽象背景** ![AA摘要](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kmg82lvgegyunyd2l85z.jpeg) --- **3. iiisometric - 用於等距設計結構的 SVG 生成器** ![等距](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ib95jrr2sr14aqch4sev.jpeg) --- **4. ccclaymoji - 黏土形態風格的 SVG 表情符號製作者。** ![cclaymoji](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/chbni56jl79w1shy3ym1.jpeg) --- **5. sssplatter - 用於產生飛濺形狀的 SVG 產生器** ![sssplatter](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qzs3dhd9w0v4igftol95.jpeg) --- **... 🫠 還有更多工具 👉 [fffuel.co](https://fffuel.co/) ...** 就是這樣😊 ----- 使用[fffuel.co](https://fffuel.co/)可以輕鬆保持井井有條,因為一切都可以在一個地方找到。 最重要的是,它完全免費使用。 試試一下,看看為什麼 Fffuel 是開發人員的新好朋友。 感謝您閱讀這篇部落格🙏,我希望這能為您帶來一些新的去處! 如果您發現任何其他有用的網站,請發表評論📩。 並且不要忘記加上“💖🦄🔥” https://github.com/taqui-786 關注Github✅ **快樂編碼👋** --- https://dev.to/random\_ti [![github](https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white)](https://github.com/taqui-786) [![推特](https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white)](https://twitter.com/Taquiimam14) [![資料夾](https://img.shields.io/badge/Portfolio-255E63?style=for-the-badge&logo=About.me&logoColor=white)](https://mdtaquiimam.vercel.app) [![買米咖啡](https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/taquiDevloper) --- 原文出處:https://dev.to/random_ti/all-in-one-design-tools-a-gem-for-web-developer-designers-23g8