🔍 搜尋結果:10

🔍 搜尋結果:10

關於 GIT 你需要了解的一切

我相信您可以想像版本控製程式碼的重要性,以便我們可以**恢復變更**並**恢復遺失的資料以及其他可能性**。 我打賭你知道有人*(不是我呵呵)*通過使用越來越有創意的名稱建立文件副本來對其文件進行版本控制... ![GIF 模擬具有不同名稱的檔案的複製。範例:文章、文章最終版本等。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sffhjyl41pfnjklivnsv.gif) 在 1972 年之前,隨著**SCCS *(原始碼控制系統)***的發布,這是有史以來第一個**集中式**版本控制軟體之一,這可能是任何人對其程式碼進行版本控制的方式。 但我們在這裡不是在談論 SCCS,我們現在真正感興趣的是**GIT** ,這是一款**分散式**開源版本控制軟體,明年*(07/04/2005)*將慶祝其誕生 20 週年。 目錄 -- - [1.GIT是什麼?](#chapter-1) - [2.GIT如何運作?](#chapter-2) - [3.安裝GIT](#chapter-3) - [4.配置GIT](#chapter-4) - [5. 啟動本機儲存庫](#chapter-5) - [6. 使用 GIT](#chapter-6) - [7. 認識分支](#chapter-7) - [8. 與遠端倉庫同步](#chapter-8) - [9. 結論](#chapter-9) - [10. 參考文獻](#chapter-10) 1.GIT是什麼?<a name="chapter-1"></a> --------------------------------- GIT 是一個開源**分散式**版本控制系統,於 2005 年推出,由 Linus Torvald *(Linux 核心建立者)*開發。 使用GIT,我們可以在本地**控制專案的版本***(在工作資料夾中)*並將所有變更同步到遠端儲存庫*(例如在GitHub上)* 。 2.GIT如何運作?<a name="chapter-2"></a> ---------------------------------- 想像一個**實體**文件櫃,其中有一個包含所有專案文件的資料夾。每當有人需要操作文件時,他們都必須將其拾取,**將其從資料夾中刪除,並在完成後將其返回到資料夾中**。因此,兩個人**不可能**處理同一個文件,完全避免了任何可能的衝突。 **但這不是 Git 的工作原理!** *(感謝上帝)* 這就是**集中式**版本控制系統的工作方式,其中使用者需要**「簽出」**和**「簽入」**文件,即每當有人需要處理特定文件時,他們需要簽出該文件,**刪除從儲存庫中獲取**文件,然後在工作完成後簽入該文件,**並將其返回儲存庫**。 ![GIF 模擬集中式版本控制系統的操作。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26a9j0m4pcu5prb0kauo.gif) 在像**GIT**這樣的**分散式**系統中,多個人可以存取同一個遠端儲存庫中的檔案。每當有人需要操作文件時,他們只需將其**克隆***(或克隆整個存儲庫)*到本地計算機,然後將修改發送回遠端存儲庫。這使得**多人可以處理同一個專案**,甚至操作**相同的文件**。 ![GIF 模擬分散式版本控制系統的操作。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nb0x0u9kc6m7z2hz7zfj.gif) 這就是允許大型**開源**專案的分佈,來自世界不同地區的人們在同一個專案上工作,管理修改和可能的衝突*(是的,這裡可能會發生合併衝突)* 。 3.安裝GIT<a name="chapter-3"></a> ------------------------------- **GIT**適用於主要作業系統*(Windows、Linux、MacOs...),*安裝過程非常簡單,可以透過**命令列**或透過[git-scm.com](https://git-scm.com/)的**官方安裝程式**完成。 ### 3.1 在 Windows 上 要在 Windows 上安裝 GIT,只需存取官方網站並[下載安裝程式即可](https://git-scm.com/download/win)。然後只需**按照說明進行操作**,一切都會好起來,然後我們就可以在終端機中使用 GIT 命令了。 ### 3.2 在Linux上 對於Linux,我們可以使用以下**命令**安裝**GIT** : ``` sudo apt install git-all ``` 透過這樣做, **GIT**必須準備好在我們的終端中運作。 ### 3.3 在 MacOS 上 對於 Mac,安裝**GIT**最簡單的方法是安裝[Homebrew](https://brew.sh/) ,然後在終端機中執行以下**命令**: ``` brew install git ``` 然後**GIT**必須準備好在我們的終端中運作。 4.配置GIT<a name="chapter-4"></a> ------------------------------- 安裝後,使用以下**命令設定 GIT**很重要: ``` git config --global user.name "[username]" # e.g. John Doe ``` ``` git config --global user. email "[[email protected]]" # e.g. [email protected] ``` > 此外,也可以透過刪除`--global`標籤來為某些本機儲存庫配置特定使用者。 5. 啟動本機儲存庫<a name="chapter-5"></a> ---------------------------------- 配置**GIT**後,我們就可以**啟動本地儲存庫了**。為此,我們可以**從頭開始一個新的儲存庫**或**複製現有的遠端儲存庫**。 ### 5.1 從頭開始(git init) 要啟動新儲存庫,只需導航到所需的儲存庫**根資料夾**並執行以下命令: ``` git init ``` ![Linux 終端機執行「git init」命令並顯示結果的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iw35xe9jwrwzo937to5b.png) 透過這樣做,將在專案資料夾內建立一個`.git`目錄,該目錄將**負責此本機儲存庫的工作資料夾中的版本控制**。 ### 5.2 克隆現有儲存庫(git clone) 克隆現有遠端儲存庫就像從頭開始建立新儲存庫一樣簡單。為此,只需使用`git clone`命令,將要複製**的儲存庫的 URL**作為參數傳遞到要複製儲存庫的資料夾中: 複製現有的遠端儲存庫就像從頭開始建立新的儲存庫一樣簡單。為此,只需使用`git clone`命令,將**遠端儲存庫 URL**克隆到我們要下載儲存庫的資料夾中: ``` git clone [repository-url] ``` ![Linux 終端機執行「git clone」命令並顯示結果的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nlt8rtua4ri7kpnna5el.png) 然後整個存儲庫必須**克隆**到我們的本地機器並**自動連結到相關的遠端存儲庫**。 > 有了複製的儲存庫,我們以後就不再需要使用`git remote`指令了。 6. 使用 GIT<a name="chapter-6"></a> --------------------------------- 在我們的**本機儲存庫**中,我們可以建立專案所需的文件,但它們**不會由 GIT 自動同步**,當有任何變更需要版本控制時,我們需要報告它。 因此,我們可以根據需要**操作**文件,並**在完成所需的變更後**,**將更新的文件傳送到 GIT** 。 為此,重要的是要了解版本控制中有**3 個階段的無限流***(是的,無限)* : ``` MODIFY -> STAGE -> COMMIT ``` - **修改:**版本控制的第一階段,我們在這裡找到與上一個可用版本相比**已更改的檔案**。 - **STAGE:**版本控制的第二階段,這是我們放置**要新增到下次提交的修改檔案**的地方。 - **COMMIT:**版本控制的最後階段,當我們**確認變更**時,將階段中修改的檔案傳送到本機儲存庫。 提交修改後的文件後,我們在本地存儲庫中有一個可用的**新版本**,它可以再次接收更新,再次*“修改”* ,然後放入*“階段”* ,並再次*“提交”* ,確認較新的版本版本等等*(因此,「無限」哈哈)* 。 > 值得注意的是,提交不會覆蓋已修改文件的舊版本,而是包含新版本以及指向最後版本的指針,從而追蹤 GIT 追蹤的每個文件的版本。 ### 6.1 新增和提交(git add 和 git commit) 儘管聽起來很複雜,但執行版本控制流程**非常簡單**。由於所需的修改已完成,我們使用以下命令**新增要在舞台上提交的修改後的檔案**: ``` git add [filename] ``` > `git add -A` -> 將所有修改的檔案立即加入階段。 > > `git add *.[extensão-do-arquivo]` -> 將所有具有指定檔案副檔名的已修改檔案一次新增至暫存區(例如`git add *.html` ) 我們可以隨時使用`git status`指令檢查目前本機儲存庫**狀態**: ![Linux 終端機執行「git status」命令並顯示結果的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e28lg7wym8s0woytgzqz.png) 請注意,當我們**在建立新檔案後**在儲存庫中執行`git status`時,新檔案將顯示為*「Untracked」* 。這意味著該文件是**全新的**,仍然需要加入到任何提交中才能被**GIT追蹤**。 > 可以讓 GIT 忽略儲存庫中的特定檔案或資料夾。為此,我們只需將一個名為`.gitignore`的檔案新增到根資料夾中,並在其中寫入應忽略的檔案或資料夾的名稱。 > > 注意:被忽略的檔案和資料夾將不再出現在 GIT 軌道上,甚至不會顯示為「未追蹤」。要重置跟踪,只需從`.gitignore`文件中刪除所需的名稱即可。 要包含文件,我們可以使用要新增的文件的名稱來執行`git add`命令*(在本例中為「index.html」)* : ![Linux 終端機的螢幕截圖,執行命令“git add”,然後執行“git status”,顯示結果。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pz1hnk9gpnxtv2s8xort.png) 這樣,透過重新執行`git status`我們可以看到新檔案已新增至*「stage」* ,並**最終準備好在下一次提交中發送**,這可以使用以下命令完成: ``` git commit -m "[descriptive-message]" ``` > 提交具有唯一的 ID(雜湊碼)並且是**IMMUTABLE 的**,即一旦確認就無法修改。 > > `git commit -a` -> 執行直接提交,將所有修改的檔案新增至暫存區並提交它們。 **成功提交檔案後**,執行`git status`時,我們注意到**沒有更多修改的檔案需要上傳**,因為所有修改都已在上次**提交**時有效保存在我們的本機儲存庫中。 ![Linux 終端機的螢幕截圖,執行指令“git commit”,然後執行“git status”,顯示結果。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ryqqs4mi46hxtuex199i.png) 此外,還可以使用`git log`指令查看儲存庫的提交日誌來**驗證所做的更改**,該指令顯示所有提交的一些元資料,例如雜湊碼、分支、作者、日期等。 ![Linux 終端機執行命令「git log」並顯示結果的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ljvj9se6srxslsu8vsj7.png) 可以重複整個過程來加入我們專案所需的新文件,修改它們並透過進行新的提交將它們發送到本地儲存庫。 ![GIF 模擬 GIT 分支中的多次提交。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2uez3henix8kchperuw8.gif) > `git log -N` -> 顯示最近 N 次提交的日誌。 > > `git log [branch-A] [branch-B]` -> 顯示「branch-B」中但不在「branch-A」中的提交日誌。 > > `git log --follow [filename]` -> 顯示更改指定檔案的提交日誌,即使它已更改名稱。 > > `git diff` -> 列出與儲存庫中最新可用版本相比所做的變更。 > > `git diff [nome-do-arquivo]` -> 列出對指定檔案相對於儲存庫中最後一個可用版本所做的變更。 ### 6.2 撤銷提交前後的更改 **在提交之前**,對本地存儲庫所做的任何更改都可以撤消或更改,但**一旦提交,就無法更改**。這是因為提交是**不可變的物件**,這意味著不可能編輯或更改提交中的資料。 但是,**可以進行新的提交**來撤銷更改,或更正先前提交中的不正確資訊。無論哪種方式,我們都可以使用以下命令之一: ``` git checkout -- [filename] # Discards changes made to the local file before the commit (irreversible action) ``` ``` git reset --hard HEAD # Discards changes made to a file that is in stage (before the commit) ``` ``` git reset --hard HEAD~1 # Discards the last commit made in the local repository (only the last commit) ``` ``` git commit --amend # Creates a new commit, replacing the last commit made in the local repository ``` ``` git revert [commit-hash] # Creates a new commit, reverting the changes of the specified commit ``` 7. 認識分支<a name="chapter-7"></a> ------------------------------- **分支**只不過是儲存庫的一個**分支**,到目前為止,所有操作都已在分支`master/main'`上執行。 > 預設情況下,儲存庫中建立的第一個分支是`master/main` ,它是儲存庫的主分支。 ### 7.1 為什麼要使用分支? 乍看之下似乎沒什麼,但**分店卻為專案的發展賦予了巨大的力量**。 想像一下,我們正在開發一個 Web 平台,並且想要**測試一項新功能**,但我們的儲存庫已經**託管或與其他人共享**,任何有問題的更改都可能會給他們帶來糟糕的體驗。我們可以做什麼? 如果您一直在考慮**複製並貼上**專案資料夾,建立一個新的**「測試版本」** ,那麼您是對的!嗯,差不多… 透過 GIT,我們可以對分支做類似的事情。由於它們是**分支**,我們可以簡單地**建立一個名為「test」的新分支**,從而在完全**隔離的分支**中擁有我們專案的一個版本,準備好進行翻轉,**而不會危及主分支**。 ![GIF 模擬使用新提交建立新分支。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/szc081nndoi18vklty5r.gif) ### 7.2 建立分支(git分支) 建立**分支**意味著建立可以獨立工作的儲存庫的並行副本,而不會影響`master/main`分支。為此,我們只需執行以下命令: ``` git branch [branch-name] ``` > 在沒有特定分支名稱的情況下執行`git branch`指令必須顯示儲存庫中可用分支的列表,並用「\*」標記目前正在使用的分支。 在執行`git branch test`指令之前, `git branch`指令只會傳回`master`分支。 ![Linux 終端機執行「gitbranch」命令、建立新分支並顯示結果的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vqpdrtvhze9qhr31ewbh.png) 建立新分支後,我們可以執行以下命令在可用分支之間切換: ``` git checkout [branch-name] ``` 執行`git checkout test`指令後,我們可以看到**活動分支已切換**。從那一刻起,**所有提交的資訊都會傳送到儲存庫的`test`分支**,而不會影響分支`master/main` 。 ![Linux 終端機執行「git checkout」命令、切換活動分支並顯示結果的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/egau7y81leig8za36myi.png) > 可以根據需要建立任意數量的分支,並且我們可以使用以下命令與現有分支進行互動: > > `git checkout -b [branch-name]` -> 使用給定名稱建立一個新分支並直接切換到它。 > > `git branch -d [branch-name]` -> 刪除指定分支。 > > `git branch -m [new-name]` -> 將目前分支的名稱變更為給定名稱。 ### 7.3 合併分支(git merge) **當完成不同分支**上的工作,並且我們確定所做的更改不會在專案中引起任何問題時,我們可以將當前分支**合併**到`master/main`分支中,**應用當前分支中的所有更改分支到儲存庫的主分支**。 要**合併**分支,我們需要**切換到將接收更改的分支**並執行以下命令: ``` git merge [branch-name] # Merge the given branch into the active branch ``` 在這裡,由於我們位於分支`test`上,因此我們應該使用`git checkout`命令**切換到分支`master`** ,然後使用我們要合併的分支的名稱*(在本例中為“test”)*執行`git merge`命令。 ![Linux 終端機的螢幕截圖,執行命令“git checkout”,切換到 master 分支,然後“git merge”,顯示結果。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6tqap1uu5gjipkety6w.png) 透過這樣做,在分支`test`上完成的所有工作*(在本例中為`style.css`檔案的建立)*將合併到分支`master`中。 ![模擬兩個分支之間的合併過程的 GIF。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3hs17m005ogm0qlbedjy.gif) ### 7.4 合併衝突 如果**在同一行上更改了一個或多個檔案**並且合併無法**自動**完成,則使用`git merge`合併不同分支可能會導致一些**衝突**。 ![執行「git merge」命令的 Linux 終端機的螢幕截圖,該命令傳回衝突警告。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9mwedudsff1yf8kpzguc.png) 出現這種情況時,我們可以執行`git status`指令來檢查**哪些檔案**有衝突。 ![出現合併衝突警報後執行「git status」指令的 Linux 終端機的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcfpmta2yiy1xpyc729u.png) 在繼續合併之前,我們需要**解決衝突**,方法是定義應該進行哪些更改,或檢查更改以使它們相互相容。為此, **GIT 將在衝突文件中插入標記**以協助解決問題。 ![在文字編輯器中開啟的衝突檔案的螢幕截圖,顯示了 GIT 建立的用於幫助解決衝突的標記。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0e727le3ogmhtuq0g7w.png) 解決衝突後,我們只需要將修改過的檔案放回舞台,提交新的無衝突版本,然後再次執行`git merge`指令,這一定會成功合併,沒有任何問題。 8. 與遠端倉庫同步<a name="chapter-8"></a> ---------------------------------- 我們已經知道可以**將本地存儲庫連接到遠端存儲庫**並遠端同步我們的所有工作,使其**保持最新**。 為此,我們需要執行`git push`命令,該**命令將所有提交從本地存儲庫發送到遠端存儲庫**,但首先我們需要\*\*配置遠端存儲庫。 ### 8.1 配置遠端倉庫 啟動*遠端儲存庫*非常簡單。這裡我們將使用**GitHub**來完成它。 首先,我們需要在 GitHub 帳戶中**啟動一個新的空白儲存庫***(只需選擇一個名稱並點擊「建立儲存庫」)* : ![GitHub 上儲存庫建立頁面的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ug1aw5eq15du36vd1hri.png) 接下來,我們需要透過在本機儲存庫中執行以下命令**來配置遠端儲存庫和本機儲存庫之間的關係**: ``` git remote add origin [remote-repository-url] ``` ![Linux 終端機執行「git Remote」命令並顯示結果的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rhrlfg0f0pgljl5b18vl.png) > `git remote -v` -> 顯示實際連接到本機儲存庫的遠端儲存庫的 URL。 正確**連接**遠端儲存庫後,我們需要使用指令`git branch -m main`**將本機分支`master/main`的名稱變更**為「main」 *(如果您的本機分支已稱為`main` ,請忽略此步驟)* : ![Linux 終端機執行「gitbranch」指令、將「master」分支重新命名為「main」並顯示結果的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f0al7joro01pch0ac124.png) > 保持本機儲存庫的主分支與我們要推送到的遠端儲存庫的主分支同名非常重要。 最後,完成上述步驟後,我們可以使用以下命令首次將本機儲存庫與遠端儲存庫**同步**: ``` git push -u origin main ``` ![執行「git push」命令的 Linux 終端機的螢幕截圖,該命令需要 GitHub 身份驗證。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvkdyis8y989xron52nc.png) 當我們執行`git push -u origin main`指令時,我們可能需要輸入**GitHub 憑證***(使用者和存取權杖)* 。 > 如果您不知道**GitHub 存取令牌**是什麼,或者您沒有設定存取令牌, [請按一下此處](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic)。 > > 我們也可以透過**使用 GitHub CLI 設定身份驗證**來解決此問題。 [按此處](https://docs.github.com/en/get-started/getting-started-with-git/caching-your-github-credentials-in-git)了解具體方法。 經過**身份驗證**後, `git push`應該會成功執行,將本地儲存庫中的所有提交與遠端儲存庫同步。 ![Linux 終端機的螢幕截圖,顯示 GitHub 驗證後繼續執行「git Push」命令。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vp7q4htszkzrfc6vepcl.png) ![收到帶有新檔案的「git Push」後 GitHub 上的遠端儲存庫的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2rqfhi6s6jh369tseh5y.png) ### 8.2 第一次後的Git推送(git推送) 完成上述所有步驟後,可以單獨使用`git push`指令完成**新同步**,無需任何其他參數,如下所示。 ![Linux 終端機執行「git status」、「git commit」和「git Push」命令、執行新提交並將更新推送到遠端儲存庫的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aoatcspiwosywih07nsm.png) ![收到新更新後 GitHub 上的遠端儲存庫的螢幕截圖。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jskxpghboi62mqw2qcb2.png) > 在這種情況下,使用**GitHub CLI**繞過了執行命令`git push`所需的身份驗證。您可以[點擊此處](https://docs.github.com/en/get-started/getting-started-with-git/caching-your-github-credentials-in-git)了解具體方法。 ### 8.3 更新本地倉庫(git pull) 使用**分散式**遠端儲存庫,可以**遠端**進行更改*(直接在遠端儲存庫中)* ,從而導致我們的本機儲存庫**變得過時**。 考慮到這一點,**更新本機儲存庫**並同步我們在遠端儲存庫中獲得的任何變更非常重要,**以確保本機專案始終具有遠端儲存庫中可用的最新版本**。為此,我們可以執行以下命令: ``` git pull ``` 想像一下,一個**新檔案**`README.md`已**直接在我們的遠端儲存庫中**建立,因此我們的本機儲存庫現已過時。 ![遠端儲存庫的螢幕截圖,其中遠端新增了新的 README.md 檔案。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hccw00vyr7j6lcfm02d2.png) 在本機儲存庫中,我們可以使用上面提到的`git pull`**同步**遠端儲存庫中的變更。 ![Linux 終端機執行「git pull」命令的螢幕截圖,使用遠端儲存庫中的新變更更新本機儲存庫。](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/it9ylx1imd94yey5d0wd.png) > 當我們執行`git pull`指令時回傳的前 7 行是`git fetch`指令的回傳。換句話說,如果我們執行`git pull`命令而不先執行`git fetch`命令,GIT 將同時執行這兩個命令以從遠端存儲庫檢索更新並將其同步到本地存儲庫。 > > `git fetch` -> 從遠端儲存庫取得更新,但不同步本機儲存庫(需要`git pull` )。 9. 結論<a name="chapter-9"></a> ----------------------------- 這一切讓我們確信GIT是程式設計師日常生活中必備的版本控制系統,了解它的主要指令和用途可以成為我們技術資歷的轉捩點。最後,隨著本地和遠端儲存庫的同步和更新,以及我們迄今為止所學到的一切,我們已經準備好繼續推進這個令人敬畏的版本控制系統的實用性。 10. 參考文獻<a name="chapter-10"></a> --------------------------------- - [GIT 的官方文件。](https://git-scm.com/docs/git#_git_commands) - [\[PT-BR\] GIT:入門迷你課程(45 分鐘內學會) - Codigo Fonte TV](https://youtu.be/ts-H3W1uLMM?si=-hKGkUmwgT2lZJwy) --- 原文出處:https://dev.to/reenatoteixeira/everything-that-you-need-to-know-about-git-2440

🐱Product Hunt 已成為付費獲勝💰,但您仍然應該使用它來發布您的產品🚀

我們中的許多人已經在 Product Hunt 上推出了一段時間,**越來越多的人開始質疑那裡的受眾是否真誠,以及是否仍然值得在他們自己的平台上推出**。 一周前剛剛推出了我們的最新產品,我想在這裡分享我們的第一手經驗並涵蓋三個主要內容: - 今天就推出 Product Hunt 的外觀和感覺如何 - 我們從發布中得到了什麼 - 如何(最好)利用 Product Hunt 來開發您的產品 關於我們 - 推出 6 次,超過 2,000 票贊成 -------------------------- 在過去 3 年裡,我們在 Product Hunt 上推出了 6 次,贏得了「最佳產品」獎(當天排名第 1 和第 5 名),並總共收集了超過 2,000 個讚。一週前,我們剛完成了[Open SaaS 的第六次發布,這是 300 美元以上 SaaS 入門產品的開源替代品](https://github.com/wasp-lang/open-saas/)。 ![最近推出](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spu3cpuo64ao50r3227u.png) 您會發現許多文章為在 PH 上推出提供建議,並從那些獲得推薦的人那裡贏得故事,但幾乎沒有人分享幕後知識以及實現這一目標的真正需求。這就是這篇文章的目的。 我將引導您完成啟動步驟並發表評論並分享我們在每個步驟中的經驗。讓我們開始吧: 安排您的發布並建立“即將推出”預告片 - “讓我們交換贊成票” ------------------------------- ![即將推出](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qoogy6m4da5ajswtrplg.png) 一旦您安排了Product Hunt 的發布,您就可以建立一個橫幅,顯示在他們的「即將推出」頁面(https://www.producthunt.com/coming-soon) 上,這就是您的旅程開始的地方。這使 PH 訪客有機會了解接下來會發生什麼,並訂閱以在發布後收到通知,這也是您可以用來行銷您的發布的第一個東西。 **這也是 PH 經濟開始的時候 - 一旦您發布發布預告片,您將開始收到與其他即將推出其產品的人交換贊成票的報價**: ![預告片幫助我們](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aznuya45vj10t8mzysxf.png) 這實際上是一種合法的策略(從共享激勵而不是購買選票的意義上來說),可以透過自動化非常有效地利用。它不會帶來任何合格的潛在客戶(也就是真正對您的產品感興趣的人),但它可能有助於獲得投票,從而提高您的產品發布的知名度和影響力。 我們根本沒有使用過這個策略(所以我無法證明它的效率),因為我們很晚才發布“即將推出”頁面,就在發布前一兩天,而且我們也沒有工作流程沒有地方也沒有人力來完成它。 Linkedin、WhatsApp 和其他平台上也有專門的小組,讓 PH 參與者可以互相支持。如果您加入這些活動,您將會收到更多此類訊息和請求。 發布日 - 主動發送的電子郵件和「購買投票」優惠 ------------------------ 發布當天,類似上述的要求愈加強烈。我甚至收到了其他人在同一天推出產品的幾封電子郵件,要求我投票,因為他們刪除了我的電子郵件並將我加入到他們的時事通訊中。 ### 當天的前 4 小時 - 隱藏點讚 Product Hunt 最近推出了在一天的前 4 小時內以隨機順序顯示產品的功能,並隱藏點讚數。背後的想法是保證所有產品一開始就有平等的知名度,並有公平的機會吸引觀眾的注意。 隨著我們最新推出的 Open SaaS,我們取得了有史以來最好的開局 - 4 小時內獲得 100 票贊成! ![開幕](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c2b7i5ddfk8k37m0g089.png) 當然,我們參與了我們的網絡,但也注意到來自我們不認識的人的大量投票和評論。有瞭如此強勁的開局,我非常有信心我們能躋身排行榜前 5 名產品之列。 > 進入前 5 名產品是 Product Hunt 主頁上的「首屏」位置,因此儘早到達那裡是最終進入該位置的最佳方式。 > 但當排行榜最終揭曉時,Open SaaS 勉強躋身當天發布的前 10 名! ![排行榜揭曉](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ck8hbz4oiamhkj99z5gu.png) 前五名與其他產品之間存在著相當明顯的差距,第一名的產品的支持率幾乎是第二名的兩倍。**這對我們來說相當沮喪,因為感覺我們追趕的機會幾乎是零。** ### “嘿,想買點讚嗎?” 排行榜揭曉後,我們開始收到另一種類型的訊息——直接購買點讚的報價。仍然相對接近前 5 名的產品可能使我們成為一個非常合格的領導者: ![購買贊成票](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n20qhgmvpk72zu5t8ojk.png) 與此略有不同的是,讓不同的社群媒體影響者和社群所有者伸出援手,向他們的追隨者推銷您的產品,並承諾獲得 X 票: ![購買優惠2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qo7qlwcgpafek2g4bd36.png) ![進入前 3 名優惠](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1ndsehw06oax11uh2gu.png) 甚至我們的一些直接聯絡人也知道“一個人”可以讓你到達 Product Hunt 的頂端,並主動提出介紹我們,所以這有點像一個“公共秘密”,而我們是少數不知道的人關於它。 我們從發布中得到了什麼 - #7、HN 頭版、GitHub 上的趨勢… ----------------------------------- ![推文發布統計](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cc8wa4vzl6htfrjanxkk.png) **我們 PH 發布的主要好處不是發布本身,而是我們可以將其與其他東西結合起來,例如**[在 HackerNews 上發布 Open SaaS](https://news.ycombinator.com/item?id=39192304) **,**它最終在其中展示了大約半天(在 Show 上展示的時間更長) HN 選項卡)。 ![恩頭版](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ve2jf1qjy649sxe6gofu.png) 最後,所有這些參與度加起來讓我們能夠在 GitHub 上獲得全球趨勢,這反過來又為 Open SaaS 帶來了更多流量(今天,在發布一周後,它已經擁有[超過 2500 顆星](https://github.com/wasp-lang/open-saas/))。 ![gh 推文趨勢](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yfvramertsi8cyim0uyk.png) ### 由此產生的流量 看看過去兩週 Open SaaS 儲存庫帶來的流量,我們可以觀察到以下內容: ![回購訪客](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3tw0kbqfkd520egehfaq.png) ![回購參考網站](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6qxz1awc2fm4bwaufj8s.png) HackerNews 的推出吸引的人數是 Product Hunt 的三倍多。 GitHub 吸引了更少的人存取實際的儲存庫,但我的直覺是,更多的人在沒有離開「趨勢」頁面的情況下加註了星標。 在 PH 的每日時事通訊中獲得專題報告 - 有幫助嗎? --------------------------- ![被刊登在 ph 通訊中](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3bxgy7jtmpljx9egwpn4.png) Open SaaS 在發布結束時成為當天排名第七的產品,獲得約 400 票贊成。根據 Product Hunt 的資料,當日排名前 10 名的產品最終會出現在擁有超過 50 萬訂閱者的每日新聞通訊中。 該時事通訊以 3 個大型促銷區塊開始,因此您必須滾動相當長的時間才能到達前一天的熱門產品。 ![時事通訊滾動](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uumomkgthubjwwphce5f.gif) 對我們來說,它並沒有產生太大的影響,我認為它為我們贏得了大約 20 票。也許是因為我們不是第一,或者只是因為它是一個相當深的漏斗(打開電子郵件 → 一直向下滾動 → 檢查所有產品 → 喜歡 Open SaaS → 決定投票)。 ![ph 讚圖表](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p92a0r19refow1wkxh19.png) 在沒有任何提升策略的情況下是否有可能贏得當天的第一名? --------------------------- **是的,這絕對是可能的。我已經得到了幾個我信任的聯絡人的證實,他們用他們的產品贏得了第一名,沒有任何機器人或支付贊成票。**但它也肯定變得不那麼常見和難以預測。 大多數時候,我們推出的產品首先會表現出一些不尋常的行為。有一次,是該公司在前一周推出,但他們只是稍微重新命名了產品和網站,然後重新推出。還有一次,一款產品在發布結束前幾個小時突然獲得了很高的支援率。 那麼,這意味著什麼?它還值得在 Product Hunt 上推出嗎? ---------------------------------- 顯然,今天雙方都有不同的力量和動機驅動 Product Hunt 用戶的行為。最初,有一個社區想要了解最新產品並表達他們的興趣,並且有一些創始人想要連接到該社區。 **現在,也有一些創作者最希望自己的產品獲勝,無論實際的受眾參與度如何,因為他們相信這將有助於他們實現最終目標,例如影響範圍、籌款或對其他用戶的社會認可。顯然,有一方願意滿足這項需求,但對產品並沒有任何真正的興趣。** 為什麼這可能? Product Hunt 正在採取許多措施來偵測和防止此類行為,但如果不嚴格限制 Product Hunt 所追求的網路效應(即能夠分享您的啟動連結),就很難做到這一點。 **除此之外,對我們來說,定期在 Product Hunt 上發布仍然是值得的。原因如下。** 產品搜尋是一個很棒的藉口 ------------ Product Hunt 為您提供了一個獨特的機會來宣布您的產品「正式」發布。您可以決定在哪一天執行此操作並安排時間,並且 100% 所有人都能看到它,您也可以分享並邀請人們查看。**你有 24 小時的時間,在此期間,你完全有理由聯繫你認識的每個人(以及其他人)並繼續按喇叭。** ![打開 saas ph 推文](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7vazu6ezrf5goukk6mk3.png) **Reddit 和 HackerNews 等其他高影響力平台無法做到這一點。**當然,您可以隨時分享有關您產品的新聞,但不能保證任何人都會看到它(實際上恰恰相反),除非社區的集體思想決定如此,這幾乎是確定性的。您可以輕鬆地花費一周的時間來準備您的發布帖子,但它會在幾分鐘內被演算法淹沒。 **這就是為什麼我們不將 Product Hunt 視為最終目標(贏得第一名),而只是將其視為我們整個發布過程的一部分。這是一個很棒的講台,也是一個談論你的產品的好藉口,而上面的任何其他東西都只是一個額外的好處。** 我們保持簡單 ------ 您會發現很多來自「PH 專家」的文章(和付費課程),解釋您應該如何提前幾個月準備發布、預熱您的受眾、準備他們將分享的評論等。**我們不做任何這些事情。我們只需準備內容(影片+一些螢幕截圖和介紹性評論),然後在發布當天邀請我們認識的所有人支持我們。然後,白天我們也會在 Reddit、Hackernews 和 dev.to 上發文。** ![法師成長圖](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cy7kdtpyyok5hgkm00js.png) 有時我們最終會進入前 5 名,有時則不然,**但每次,我們的用戶參與度都會穩步提升,並且通常會在接下來的幾天/幾週內出現更好的結果**。例如, [MAGE,我們基於 GPT 的全端應用程式啟動器](https://usemage.ai/),在 PH 發布後就出現了爆炸性增長,並[在幾個月內被用來建立了 30,000 多個專案](https://dev.to/wasp/how-we-built-a-gpt-web-app-generator-for-react-nodejs-from-idea-to-25000-apps-in-4-months-1aol)。 我們經常這樣做 ------- 我們的目標是每 3 個月發布一次 Product Hunt,作為發布週的一部分,這就是我們迄今為止所做的。除非 6 個月過去了或有重大更新,否則您無法真正推出完全相同的產品,但您可以自由地推出與主產品相關的其他(子)產品和功能。 > **💡 提示**:當您提交發佈時,您可以要求 PH 團隊將其「連接」到您的產品,以便它將出現在該產品的發布清單中。通常,他們自己做。它看起來像這樣: ![黃蜂全部發射](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xebrqdzvk5kcs7tpr1bk.png) 雖然我們的主要產品是[Wasp,一個基於 React 和 Node.js 的全端框架](https://github.com/wasp-lang/wasp),但到目前為止我們推出的產品如下: - **Wasp Alpha** - 純產品,v0 差不多 - **Wasp Beta** - 差不多兩年過去了,我們還沒有採用「經常發布」的方法 - **免費 SaaS 模板**- [Open SaaS](https://github.com/wasp-lang/open-saas)的前身,4 個月後 - [\*\*MAGE,GPT Web 應用程式產生器](https://usemage.ai/)\*\* - 由 Wasp 提供支援的全端 Web 應用程式產生器 - [**React/Node 的全端身份驗證,無第三方服務**](https://wasp-lang.dev/docs/auth/overview)- Wasp 的身份驗證功能 - 最後, **[Open SaaS - 300 美元以上 React 和 Node.js SaaS 初學者的免費開源替代品](https://github.com/wasp-lang/open-saas/)** 它已成為我們發布工作流程的常規部分,對於我們在該季度推出的任何新功能,我們都會尋找一個好的候選人在即將推出的發布中展示。這使我們能夠繼續談論我們所做的事情,並且我們還獲得了很多可以嵌入到我們的文件、部落格文章等中的好內容(例如影片、橫幅)。 例如,這個影片展示了 Wasp 中的身份驗證如何運作 - 首先我們將它用於我們的[Product Hunt 發布](https://www.producthunt.com/products/wasp-lang-alpha#full-stack-auth-for-react-node-by-wasp),現在它[位於我們的身份驗證文件的頂部](https://wasp-lang.dev/docs/auth/overview)。 {% 嵌入 https://www.youtube.com/watch?v=Qiro77q-ulI&amp;ab\_channel=Wasp %} 謝謝閱讀! ----- 感謝您閱讀本文!這篇文章比我最初預期的要長得多,但我不斷獲得更多關於要寫什麼的想法。我希望您會發現它對計劃下一次發布有所幫助,並且您也會更好地了解在此過程中會發生什麼。 我也很想得到您的回饋,並了解您在 Product Hunt 上推出的經驗和策略。 快樂發射! --- 原文出處:https://dev.to/wasp/product-hunt-has-become-pay-to-win-but-you-should-still-use-it-to-launch-your-product-508d

😁您不知道可以用 DEV 做的 12 件事

身為開發人員,我總是在尋找那些小細節,因為細節很重要。 我們都是 DEV 上一個大社群的一部分,在這篇文章中,我很高興分享一些您可能不知道的這個平台上意想不到的功能和技巧。 讓我帶您了解在 DEV 上可以做的 12 件令人驚訝的事情,從建立自訂按鈕到建立評論範本! 請評論並讓我知道哪一點最讓你驚訝。 --- 1.使用標籤過濾貼文。 ----------- 隨著我們的提要中不斷出現帖子,擁有一些控制和過濾器至關重要。一種方法是使用標籤過濾貼文。 例如,要查看帶有`#discuss`標籤的帖子,只需導航到[dev.to/t/discuss](https://dev.to/t/discuss) 。 同樣,如果您想要帶有標籤`#softwaredevelopment`的帖子,請前往[dev.to/t/softwaredevelopment](https://dev.to/t/softwaredevelopment) 。 作為一般規則,您可以使用它。 ``` https://dev.to/t/paste_your_tag_without_spaces ``` 您可以將上述 URL 與您的標籤貼在一起,以查看相關類別中的熱門貼文。 ![討論直接頁面](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xez2qykasum194xa3t6z.png) 您可以找到負責處理該特定標籤的標籤管理員。 如果您想知道,標籤管理員負責維護標籤與貼文的相關性。 您可以在[dev.to/dashboard/following\_tags](https://dev.to/dashboard/following_tags)檢查您關注的標籤。 所有標籤的完整清單可在[dev.to/tags](https://dev.to/tags)上找到。 --- 2.基於官方標籤的便利資源。 -------------- 它可能與第一個相關,但並非每個標籤都如此。 某些標籤提供了方便的官方資源,例如`tailwindcss`的文件或`nextjs`的有用指南。這些資源可能很有價值,尤其是當您不熟悉某個特定標籤時。 ![文件](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnik2l3b2x5bp649qkoz.png) 例如, `nextjs`標籤有不錯的資源:) ![資源](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p7oqgn0muzzk8o9egf55.png) 這些「小細節」讓DEV平台更加人性化、資訊豐富。 --- 3.RSS 源。 -------- 向 5 歲的孩子解釋 RSS feed: > 想像一下,您有一個最喜歡的卡通節目,每次有新劇集時,您的神奇電視就會向您展示它。 RSS 提要就像網站的神奇信使。當您最喜歡的網站上有新內容時,它會告訴您的計算機,這樣您就可以看到它,而無需一直檢查。這就像一個友好的通知,說:「嘿,您喜歡的網站上發生了一些有趣的事情!」。 這就像擁有來自多個來源的內容的個人化新聞源。 - 使用以下命令檢查您的 DEV RSS 提要: `dev.to/feed/your_username` - 檢查我用來尋找 RSS 來源 URL 的[Chrome 擴充功能](https://chromewebstore.google.com/detail/get-rss-feed-url/kfghpdldaipanmkhfpdcjglncmilendn)。 在本[指南](https://dev.to/p/publishing_from_rss_guide)中詳細了解如何從 DEV 的 Feed 建立草稿。 前往[dev.to/settings/extensions](https://dev.to/settings/extensions)貼上您的 RSS Feed URL 並將其與您的 DEV 設定檔整合。 假設您有自己的博客,每當您將博客發佈到您的網站時,開發人員都會將該博客作為草稿帖子獲取,您可以從儀表板發布該博客。 ![將您的 RSS feed url 貼到開發設定中](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ca9lfcew9a524hcjq3dd.png) ### 什麼是規範 URL? 想像一下您有一個網頁,並且有它的一些副本或變體。 (您的個人部落格+DEV部落格) 規範 URL 就像將主要 URL 標記為老闆一樣——原始來源。 它可以幫助搜尋引擎了解哪個版本是最重要或首選的,從而防止混淆並提高網頁的搜尋引擎排名。 重新發佈內容以保持搜尋引擎的清晰度時,了解規範 URL 至關重要。 --- 4.許多創新事物的瘋狂徽章。 -------------- DEV 每週根據文章中介紹的技術授予多個徽章。從技術堆疊徽章到「喜愛的評論」徽章等古怪徽章,每個徽章都有自己的魅力。 例如,如果您使用 React 撰寫文章並被視為本週最佳作者,您將獲得 React 徽章。 ![技術堆疊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7valy0cbn7wouq0b1o3c.png) 我忍不住分享我對我看到的一些可愛徽章的興奮之情。 ![破冰船](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rd4gcyakplp2p6jc34am.png) 我認識幾個擁有這枚心愛徽章的人。 如果你知道,請評論! ![親愛的評論](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0o6tl1cd8yrvkirvzsfw.png) ![徽章](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py0vn9hfgmy4xfcv5e8n.png) ![徽章](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2stxb69m95gc64ce94wo.png) 誰有這個?哈哈!值得聚會。 ![特別徽章](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ouklp3ttg8i6dl8ctrsb.png) 我有這個,但沒有贏得任何遊戲🤣 ![遊戲時間](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rn4x22j94wgsb5sg3s8.png) 前 7 位作者徽章通常被認為是最負盛名的,是我個人最喜歡的。獲得此徽章本身就是一種榮譽。 ![頂級作者](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rcw2pzgwypm555lff2dn.png) 我無法一一列舉;否則,人們會生氣。哈哈! 在[dev.to/badges](https://dev.to/badges)上探索徽章的完整清單。 --- 5.軟體比較。 ------- 比較軟體並不是一個新趨勢。我們一直這樣做。 因此,開發團隊列出了社群建立的熱門貼文清單。人們通常會一遍又一遍地瀏覽這些帖子。 名單包含約 350 多家軟體公司。必須檢查! - [dev.to/software-comparisons](https://dev.to/software-comparisons) - 軟體比較 ![軟體比較](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mblkz3u3rnogkpivsgjr.png) --- 6. 為圖像新增標題。 ----------- 在 DEV 貼文中,您可以為圖像加入標題,以提供上下文或附加資訊來補充所顯示的圖像。 這是在圖像中導航的一種有趣的方式。 以下是您可以如何做到這一點。 您必須在圖像後面使用`<figcaption>`標記。 例如,請參見下圖及其文法。 ![GitHub 設定文件,使用者名稱為 Anmol Baranwal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2klya81kv58vcr94yqks.png) Anmol Baranwal 的 GitHub 簡介 ``` ![GitHub Profile with username Anmol-Baranwal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2klya81kv58vcr94yqks.png) <figcaption> GitHub Profile of Anmol-Baranwal </figcaption> ``` --- 7.訂閱評論。 ------- 通常,作為帖子的作者,您會自動訂閱所有評論。 這意味著您將收到該帖子的每條評論的通知。 然而,有趣的是,您還可以訂閱其他貼文的評論。我建議這樣做,特別是對於帶有`#discuss`標籤的帖子,因為它可以讓您接觸到各種觀點,最終獲得寶貴的學習經驗。 - `top-level comments`的通知是一個方便的功能。 ![訂閱評論](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6uiol91dzwo41gw8mwzf.png) --- 8. 嵌入和換行。 --------- 大多數人都已經知道這一點了。 但對於那些不這樣做的人,您可以嵌入任何影片,以便可以播放影片而不是粘貼連結。 它允許觀眾直接觀看影片,而無需存取其他網站。 ``` {% embed paste_url_here %} ``` 例如,嵌入我的 DEV 設定檔將如下所示。 {% 嵌入 https://dev.to/anmolbaranwal %} 有些人可能不知道使用`&nbsp;`建立換行符。 這種簡單的技術可以提高貼文的可讀性。 例如,可以使用`&nbsp;`將第一個句子與下一個內容分開。 。 第二句話由換行符號分隔。 --- 9. 號召性用語按鈕。 ----------- 這是最酷的! 您知道您可以製作帶有描述的個人化按鈕嗎?如此令人興奮! 這是吸引註意力和增強參與度的便捷方式,而且非常容易實施。 例如,讓我們為我的 GitHub 個人資料建立一個 CTA: {% cta https://github.com/Anmol-Baranwal %} 🚀 造訪我的 GitHub 個人資料 {% endcta %} 您可以使用以下語法來建立該按鈕: ``` {% cta https://github.com/Anmol-Baranwal %} 🚀 Visit My GitHub Profile {% endcta %} ``` 這種個人化的風格可以為您的貼文增添全新的維度。 該語法使用 Shopify 建立的[Liquid 標籤](https://github.com/Shopify/liquid)。 --- 10. 完整的編輯指南。 ------------ 這是即使是頂級作者也可能不知道的隱藏寶石。 DEV 團隊製作了一份全面的編輯器指南,幾乎涵蓋了使用編輯器的各個方面。它是回答以下問題的一站式資源: - 如何為圖像加入標題 - 支援的 URL 嵌入 - 如何新增不會顯示在內容中的評論(作者註) - Markdown 基礎+推薦封面圖片尺寸(1000 \* 420) - 他們甚至涵蓋了可存取性等等。 請在[dev.to/p/editor\_guide](https://dev.to/p/editor_guide)閱讀完整指南。 非常感謝開發團隊建立瞭如此方便的指南!請關注官方開發團隊並加入其中:) {% 嵌入 https://dev.to/devteam %} --- 11.評論範本。 -------- DEV 提供的另一個很棒的功能是保存評論範本的能力。無論是自我介紹還是分享社群媒體 URL,這些範本都可以節省您的時間並提高互動的一致性。 它可能很小,但它的威力很大! 它與 GitHub 上常見的功能非常相似。 ![GitHub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2dqbw39cdchi56atqnd1.png) 讓我們看看它是如何工作的。 若要設定評論模板,請造訪[dev.to/settings/response-templates](https://dev.to/settings/response-templates) ![DEV 設定評論模板](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3vble5ghyx9i0urv929g.png) 您可以輕鬆新增帶有短標題的新範本以供快速參考。 ![新增模板](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z7lwfn9lq5zr2qwxqg24.png) 當您位於帖子的評論部分時,請點擊右下角的三個點 -&gt; 然後點擊書籤符號。您將找到可以直接使用的模板清單。 ![插入評論模板](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8m8g8q72po3vhmy7n4ik.png) 值得信賴的用戶甚至可以獲得預先定義的模板列表,以更加方便。 ![作為受信任用戶的預定義評論模板列表](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zrekwoyiftsdg567m0b.png) --- 12. 播客?影片?以及隱藏標籤的力量。 -------------------- 您知道您可以在 DEV 上傳貼文影片嗎? ![上傳影片草稿帖子](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b2i3qcgje263mcyihvg9.png) 您可以在[dev.to/dashboard](https://dev.to/dashboard)的左下角找到上傳影片的選項 ![開發人員在儀表板中上傳](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khabbv85ptmnkuvartfq.png) 這是改進您的帖子的絕佳方法。在[dev.to/videos](https://dev.to/videos)上發現這些影片貼文。 DEV 還設有專門討論播客的部分。您甚至可以在[dev.to/pod](https://dev.to/pod)上提交自己的播客以供審查並探索其他各種播客。 > 個人化提要的隱藏標籤 隱藏標籤是一種讓您能夠更好地控制所看到的內容的方法,也是一種從 Feed 中隱藏您不想看到的內容的方法。 ![您可以在標籤頁面上隱藏標籤 - 使用搜尋來尋找您想要隱藏的特定標籤](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypwlmwzt2wi6o80j8syo.png) 您可以在標籤頁面上隱藏標籤 - 使用搜尋來尋找您想要隱藏的特定標籤 ![您也可以在儀表板的「以下標籤」部分隱藏標籤 - 按三個點即可存取隱藏選項](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3lia6wh3w3f7by8k3ih6.png) 您也可以在儀表板的「以下標籤」部分隱藏標籤 - 按三個點即可存取隱藏選項 - 您可以在[dev.to/dashboard/hidden\_tags](https://dev.to/dashboard/hidden_tags)找到隱藏標籤。 ![您可以查看儀表板上隱藏的標籤並取消隱藏它們](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/if2z1yl7ezb3w2qkdsjk.png) 您可以查看儀表板上隱藏的標籤並取消隱藏它們 此功能可確保在 DEV 上提供更個人化和愉快的瀏覽體驗。 我不會討論 API,因為這會讓帖子變得很長。 不過,如果您有興趣,可以探索有關[Forem API 的](https://developers.forem.com/api/v1)更多資訊。 --- 獎金 -- 我知道我知道! 我承諾了 12 件事,但這裡還有一些關於「只要有人讀你的博客,你就可以賺錢!」的額外內容。 在這篇富有洞察力的[部落格文章](https://dev.to/hacksultan/web-monetization-like-i-m-5-1418)中探討網路貨幣化的概念。這是一本很棒的指南,解釋了您需要了解的一切。 您還可以閱讀有關如何成為[DEV Mod](https://dev.to/community-moderation)並與其他社區成員合作的更多資訊。 --- 我不知道你怎麼想,但我特別興奮, `DEV`團隊可能還隱藏著更多寶藏。哈哈! 我希望你今天學到了一些新東西。 我喜歡 DEV 社區,因為它是接觸各種精彩內容的絕佳場所:生動的討論帖子、深入的教程、庫更新、職業建議等等。 > 如果您熱衷於贊助這篇文章,請給我發訊息 [email protected] 或在 Twitter 上聯繫我! 🚀 如果您喜歡我的內容,請透過在我的 GitHub 和 Twitter 上關注我來支持我。 - [GitHub](https://github.com/Anmol-Baranwal) - 繼續建造! - [推特](https://twitter.com/Anmol_Codes) - [領英](https://www.linkedin.com/in/Anmol-Baranwal/) {% 嵌入 https://dev.to/anmolbaranwal %} 多寫,多啟發。 ![結束 GIF 揮手告別](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ylsck6b9c7ei6makpqd.gif) --- 原文出處:https://dev.to/anmolbaranwal/12-things-you-didnt-know-you-could-do-with-dev-2041

下一個專案來玩玩看吧:10 個有趣 API

在程式設計社群中,從事業餘專案的想法被許多人拋棄。坐在空白的程式碼編輯器前思考要建立什麼可能會令人生畏。許多部落格文章都建議建立計算器、待辦事項清單和社交媒體克隆等應用程式。雖然這些肯定對學習技術堆疊有幫助,但讓我們面對現實吧——這世界不需要更多的計算器或待辦事項清單應用程式。相反,我們可以圍繞面向公眾的 REST API 建立新的、有趣的應用程式。 > 這是我經營的部落格[Imago Dev](https://imago.dev)的交叉貼文。 ### 什麼是 REST API? 可表示狀態傳輸 (REST) 應用程式介面 (API) 提供了一組方法,程式設計師可以使用這些方法透過 HTTP 發送和接收資料。由於這些方法是透過 HTTP 實現的,因此任何程式語言都可用於使用 REST API。 幾乎所有可以想像的不同領域都有數以千計的 REST API 可用。天氣或股票市場等常用公共資料有數十個 API 可供使用。許多流行的網路平台,例如 Facebook 和 Twitter,也向開發人員提供 API。有些專有 API 對呼叫次數有限制。許多需要註冊並接收私有 API 金鑰。最安全的 API 需要設定 OAuth 以便使用者安全登入。 您可以[在此 Github 上](https://github.com/public-apis/public-apis)找到大量公共 api 列表,並在[RapidAPI](https://rapidapi.com)上找到更豐富的列表。 ### 10 個有趣的公共 REST API 這個清單當然並沒有詳盡地列出很酷的 REST API,而只是一些我認為特別簡潔且值得進行一些副專案的 API。所有這些都是完全免費的,除了獲取 API 金鑰之外不需要任何其他東西 - 無需弄清楚如何處理 OAuth 或為其使用付費。 1. [PokeAPI](https://pokeapi.co)有史以來最大的媒體特許經營商現在可以輕鬆獲得 800 多個 Pokemon 的資料。 2. [NASA API](https://api.nasa.gov/index.html)空間,最後的前沿。取得有關小行星、星係等的資料。 3. [Open Food Facts](https://world.openfoodfacts.org/data)來自世界各地的大量食品資料。 4. [TransLoc OpenAPI](https://rapidapi.com/transloc/api/openapi-1-2)取得城市和大學校園公共交通的即時資料。 5. [Urban Dictionary API](https://rapidapi.com/community/api/urban-dictionary)人們想出的俚語真是令人驚訝。 6. [Merriam-Webster Dictionary API](https://dictionaryapi.com)適合需要真實單字定義和同義詞的人。 7. [Numbers API](http://numbersapi.com)有關數字的有趣事實和瑣事。 8. [WeatherBit API](https://www.weatherbit.io/api)當前和歷史天氣資料。 9. [美國政府資料 API](https://www.data.gov/developers/apis)一個相當大的包羅萬象的美國農業、健康和公共安全等數十個資料樣本。 10. [Bible API](https://scripture.api.bible)有史以來最暢銷的書。有史以來最偉大的故事。 ### 如何處理它們 所有這些公共 API 都很棒,但是擁有一系列有趣的資料來源並不能本質上幫助解決確定新專案要做什麼的初始問題。 最好的起點是簡單地獲取和顯示資料。也許這正在顯示當天的神奇寶貝或鍵入的單字的定義。對於更具創意的類型,請嘗試獲取資料片段並將其映射到視覺元素,例如溫度到顏色或根據公車移動繪製線條。 最困難的部分就是開始。一旦您克服了獲取和顯示資訊的最初障礙,我相信您會為您的專案想到很多後續步驟! --- 原文出處:https://dev.to/camerenisonfire/10-intriguing-public-rest-apis-for-your-next-project-2gbd

C/C++ 中的雙指標

新 C 程式設計師的困惑來源之一是指標。乍一看,使用它們似乎沒有多大用處。但是,理解指標至關重要,因為它是一個有用的工具,任何比「Hello, World」程式更大的專案都會有指標。一旦初學者開始掌握指針的概念和適用性,另一波恐怖浪潮就會深入他們的內心:雙指針。 在繼續之前,讓我們回顧一下指標是什麼。 在 C 和其他語言(如 C++)中,指標是保存物件記憶體位址的東西。它們是一個數值,當輸出到控制台時,它們通常以十六進位顯示。這意味著,本質上,指針只是奇特的整數。 現在回到雙指針。 當初學者看到雙指針時,就會開始不舒服地移動,汗水從額頭一直流到下巴。就像生活中其他一切新鮮或陌生的事物一樣,人們一想到要面對以前從未遇到過的事物,就會感到尷尬和不安,即使只是輕微的。但隨著你了解的越多,你開始對自己對想要征服的任何事物的新理解充滿信心。雙指針也是如此。 那麼,什麼是雙指針呢?那麼,如果常規指標要引用記憶體中的物件,那麼雙指標就是指向另一個指標的變數,而另一個指標又指向記憶體中的物件。 例子: ``` #include <stdio.h> int main(void) { int value = 100; int *value_ptr = &value; int **value_double_ptr = &value_ptr; printf("Value: %d\n", value); printf("Pointer to value: %d\n", *value_ptr); printf("Double pointer to value: %d\n", **value_double_ptr); } ``` 輸出: ``` ~/Desktop ➜ clang main.c ~/Desktop ➜ ./a.out Value: 100 Pointer to value: 100 Doublue pointer to value: 100 ~/Desktop ➜ ``` 當取消引用雙指標時,我們不會得到最終物件,而是得到預期的結果:必須再次取消引用才能檢索最終值的指標。它類似於下面的程式碼。 ``` int *ptr = *value_double_ptr; int final_value = *ptr; ``` 現在我確信大多數剛接觸雙指標的人一定會問自己這樣的問題:「我將在哪裡使用它?」。也許展示雙指標有用性的最佳方法是記住常規指標的實際用途之一。這就是說,常規指標可以用作函數中的輸出參數。如果您不知道的話,輸出參數是一個填充結果的參數。為什麼要使用輸出參數取決於幾個因素,並且超出了本文的範圍,但我覺得這就是可以利用雙指標的地方。 我們將要了解的一個函數是 POSIX `getline()`函數。其目的是從文件中讀取一行。當讀取該行時,人們可能會懷疑它被返回,但是,情況並非如此,因為返回值用於不同的用途。相反,第一個參數採用雙指針,填入包含該行的緩衝區。 為什麼需要雙指針?因此,它可以分配足夠的記憶體來保存整行加上空終止符。如果記憶體分配和讀取一行成功,則提供的指標將被修改為指向新的且已填入的緩衝區。只有使用雙指針,他們才能實現這一目標。 將任何內容傳遞給函數時,傳遞的是副本而不是實際物件。指針也是如此。如果我們傳遞一個常規指針,我們只能修改該指針指向的內容。如果我們更改指標本身,則更改不會反映在函數外部,因為它是副本。 如果我們想要改變指標指向的位置,我們必須新增另一個間接定址並採用雙指標。 使用`getline()`的範例如下。 ``` #include <stdio.h> int main(void) { FILE *file = fopen("test", "r"); char *line = 0; int line_length = 0; getline(&line, &line_length, file); printf("%s\n", line); printf("Line length: %d\n", line_length); } ``` `getline()`有兩個輸出參數:一個用於緩衝區,另一個用於讀入的行的長度。 概括 -- 雙指針對許多初學者來說是一個挑戰。當您對雙指標的概念越來越熟悉並在自己的程式碼中必要時使用它們時,您開始認為曾經害怕雙指標是多麼愚蠢。 現在我將帶著你的新知識送你走! --- 原文出處:https://dev.to/noah11012/double-pointers-in-cc-2n96

65 個漂亮的 CSS 按鈕

*最初發佈於[webdeasy.de](https://webdeasy.de/?referer=dev-f41) 。* --- ### ➡️*[更新,提供更多可用按鈕(點擊)!](https://webdeasy.de/en/top-css-buttons-en/?action=updated) 🚀* --- 按鈕不僅有利於可用性,而且還是網站極為重要的設計元素。因此,這裡收集了一些最好的 CSS 按鈕! 無論是主頁上粗大的按鈕還是頁腳中小而謹慎的按鈕,對於網站上的使用者流程來說,按鈕都是非常重要的設計元素。對於公司網站來說,通常會使用更謹慎的設計,而創意產業則使用更引人注目和「奇怪」的CSS按鈕。讓所有行業得到平等的服務,你會在這裡發現許多不同的風格和組合。 我和許多其他 Web 開發人員/設計師也對懸停或焦點動畫設定了很高的價值,這就是為什麼以下所有按鈕都會帶來漂亮的動畫。但現在我們直接開始! *所示筆已獲得麻省理工學院許可。您可以在[Codepen 部落格](https://blog.codepen.io/documentation/licensing/)上找到有關您自己使用的更多資訊。* \#1 懸停發光效果 ========== {% codepen https://codepen.io/twhite96/pen/rggjXp %} [新增一名](https://codepen.io/kocsten)作者 編碼方式:HTML、CSS; \#2 圓形按鈕 ======== {% codepen https://codepen.io/twhite96/pen/zBZwOP %} [新增一名](https://codepen.io/alticreation/)作者 編碼方式:HTML、CSS (SCSS); \#3 3D 觸摸 ========= {% codepen https://codepen.io/twhite96/pen/ojhCp %} [新增一名](https://codepen.io/jemware/)作者 編碼方式:HTML、CSS; \#4 圖示按鈕 ======== {% codepen https://codepen.io/twhite96/pen/KLbwJw %} 作者:[安德里亞·馬塞利](https://codepen.io/andrea-maselli) 編碼方式:HTML、CSS; \#5 斑點按鈕 ======== {% codepen https://codepen.io/twhite96/pen/BeemVX %} 作者:[希拉蕊](https://codepen.io/hilwat/) 編碼方式:HTML、CSS (SCSS); \#6 細紐扣 ======= {% codepen https://codepen.io/twhite96/pen/oRRjPP %} 作者:[納塔莉亞‧雷舍特尼科娃](https://codepen.io/natalia-reshetnikova/) 編碼方式:HTML、CSS; \#7 引導按鈕 ======== {% codepen https://codepen.io/twhite96/pen/wbZXYR %} 作者: [dew31794](https://codepen.io/dew31794) 編碼格式:HTML、CSS (SCSS)、JS; \#8 圓形脈衝按鈕 ========== {% codepen https://codepen.io/twhite96/pen/NVJzQW %} 作者:[拉吉·卡邁勒](https://codepen.io/avvign) 編碼方式:HTML、CSS (SCSS); \#9 CSS 泡棉按鈕 ============ {% codepen https://codepen.io/twhite96/pen/XwGENz %} 作者:[於爾根‧萊斯特](https://codepen.io/webLeister) 編碼格式:HTML (Haml)、CSS (SCSS); \#10 按鈕編號 045 ============= {% codepen https://codepen.io/twhite96/pen/xNBExN %} 作者:[維托爾·西凱拉](https://codepen.io/vitor-siqueira) 編碼方式:HTML、CSS; \#11 沖水鈕 ======== {% codepen https://codepen.io/twhite96/pen/joXzOw %} [新增一名](https://codepen.io/abhishekbaiju)作者 編碼方式:HTML、CSS; \#12 按鈕概念 ========= {% codepen https://codepen.io/twhite96/pen/Bevpxd %} 作者:[夏姆](https://codepen.io/Shtam3x) 編碼格式:HTML、CSS (SCSS)、JS (CoffeeScript); \#13 切片按鈕 ========= {% codepen https://codepen.io/twhite96/pen/NpwdGv %} 作者:[莎拉](https://codepen.io/saraharaya) 編碼方式:HTML、CSS; \#14 更精美的圖示按鈕 ============= {% codepen https://codepen.io/twhite96/pen/WoJGRK %} 作者:[伊尚‧薩克塞納](https://codepen.io/ishaansaxena) 編碼格式:HTML (Pug)、CSS (SCSS); \#15 按鈕變化 ========= {% codepen https://codepen.io/twhite96/pen/WEXwMO %} [新增一名](https://codepen.io/thelaazyguy)作者 編碼方式:HTML、CSS; \#16 簡單按鈕 ========= {% codepen https://codepen.io/twhite96/pen/YgJGMX %} 作者:[蒂貝裡烏·拉杜西亞](https://codepen.io/tyberiu88) 編碼方式:HTML、CSS (SCSS); \#17 按鈕翻轉 ========= {% codepen https://codepen.io/twhite96/pen/NBwNZa %} 作者:[亞歷克斯摩爾](https://codepen.io/MoorLex) 編碼方式:HTML、CSS (SCSS); \#18 向右滑動按鈕 =========== {% codepen https://codepen.io/twhite96/pen/brryVq %} [新增一名](https://codepen.io/thelaazyguy)作者 編碼方式:HTML、CSS; \#19 精美按鈕 ========= {% codepen https://codepen.io/twhite96/pen/ZMxQJp %} 作者:[亞歷山大·多·維爾](https://codepen.io/alexandrevale) 編碼方式:HTML、CSS、JS; \#20 翻蓋按鈕 ========= {% codepen https://codepen.io/twhite96/pen/Areng %} 作者:[維琳娜·V·維萊娃](https://codepen.io/vveleva) 編碼格式:HTML、CSS (SCSS)、JS; \#21 按鈕懸停效果集合 ============= {% codepen https://codepen.io/davidicus/pen/emgQKJ %} 作者:[大衛康納](https://codepen.io/davidicus) 編碼方式:HTML、CSS (SCSS); \#22 CSS 按鈕效果:動畫邊框和發光 ===================== {% codepen https://codepen.io/AnthonyBmm/pen/poooJmO %} 作者:[安東尼](https://codepen.io/AnthonyBmm) 編碼方式:HTML、CSS; \#23 CSS 按鈕懸停 ============= {% codepen https://codepen.io/folaad/pen/YvmRpz %} 作者:[伊姆蘭‧帕德斯](https://codepen.io/folaad); 編碼方式:HTML、CSS; \#24 仍在視野中 ========== {% codepen https://codepen.io/Alexb98/pen/XWrqpxB %} 作者:[亞歷克斯‧博丁](https://codepen.io/Alexb98); 編碼方式:HTML、CSS; \#25 環形指示器的純 CSS 按鈕 =================== {% codepen https://codepen.io/mccombsc/pen/ZEzxWPy %} 作者:[科爾‧麥庫姆斯](https://codepen.io/mccombsc); 編碼方式:HTML、CSS; \#26 按鈕懸停效果 =========== {% codepen https://codepen.io/kjbrum/pen/wBBLXx %} 作者:[凱爾‧維尼](https://codepen.io/kjbrum); 編碼格式:HTML、CSS (SCSS)、JS; \#27 黏糊糊的菜單 =========== {% codepen https://codepen.io/lbebber/pen/LELBEo %} 作者:[盧卡‧貝伯](https://codepen.io/lbebber); 編碼方式:HTML、CSS (SCSS); \#28 SVG CSS3 選單/漢堡按鈕 ===================== {% codepen https://codepen.io/kylehenwood/pen/Alayb %} 作者:[凱爾‧亨伍德](https://codepen.io/kylehenwood); 編碼格式:HTML、CSS (SCSS)、JS; \#29 按鈕氣泡效果 =========== {% codepen https://codepen.io/Grsmto/pen/RPQPPB %} 作者:[阿德里安‧格拉斯姆托](https://codepen.io/Grsmto); 編碼格式:HTML、CSS (SCSS)、JS; \#30 動畫提交按鈕 =========== {% codepen https://codepen.io/valentingalmand/pen/MYMZZK %} 作者:[瓦倫丁‧加爾曼德](https://codepen.io/valentingalmand); 編碼格式:HTML、CSS (SCSS)、JS; \#31 誰不喜歡有趣的按鈕? =============== {% codepen https://codepen.io/derekmorash/pen/XddZJY %} 作者:[德里克·莫拉什](https://codepen.io/derekmorash); 編碼方式:HTML、CSS (SCSS); \#32 另一面 ======== {% codepen https://codepen.io/hakimel/pen/ZYRgwB %} 作者:[哈基姆·埃爾·哈塔布](https://codepen.io/hakimel); 編碼格式:HTML、CSS (SCSS)、JS; \#33 柔軟的切換鈕 =========== {% codepen https://codepen.io/soulwire/pen/bKens %} 作者:[賈斯汀溫德爾](https://codepen.io/soulwire); 編碼方式:HTML、CSS (Sass); \#34 CSS 按鈕動畫 ============= {% codepen https://codepen.io/sashatran/pen/KaLqKR %} 作者:[薩沙](https://codepen.io/sashatran); 編碼格式:HTML (Pug)、CSS (SCSS)、JS; \#35 提交鈕 (Anime.js) =================== {% codepen https://codepen.io/andrewmillen/pen/MoKLob %} 作者:[安德魯‧米倫](https://codepen.io/andrewmillen); 編碼格式:HTML、CSS (SCSS)、JS(jQuery 和 Anime.js); … --- ### ➡️[查看我博客上的其餘按鈕](https://webdeasy.de/en/top-css-buttons-en/?action=read-more)❤️ --- 原文出處:https://dev.to/webdeasy/top-20-css-buttons-animations-f41

最好的遠距工作是令人愉快的乏味

今天我的推特上看到了這樣的訊息: {% 推文 1074722960768929792 %} 布里安娜慶祝這種情況是多麼棒是正確的。如果你必須工作,你不妨在一個美妙的環境中工作。從我個人對她的了解來看,她在這裡過著最美好的生活,這很棒。 但對我來說,這並不是遠距工作的理想選擇。我目前在家庭辦公室工作。我無聊的家庭辦公室。 我的設定最棒的是所有東西都已插入,我的所有 A/V 都運作良好,而且我每天都有相同的設定。最棒的是我不用通勤,並且可以真正按照我想要的方式有效工作。 「從任何地方」進行遠距工作很難做到正確。 在 95% 的時間裡,我坐在同一張桌子上,連接著相同的外圍設備,我已經能夠顯著優化。 有關“針對 95% 進行優化”的更多訊息,請參見此處: {% 連結 https://dev.to/nickjj/optimize-your-programming-decisions-for-the-95-not-the-5-2n42 %} 有 5% 的時間我發現自己遠離了這種設置,但仍然完全處於工作模式,這是一個相當不理想的情況。這可能是令人愉快的,但這些天我努力讓它成為有計劃的例外。 有*很多*關於遠端設定的具體建議的精彩帖子: {% 連結 https://dev.to/ivancrneto/what-i-have-learned-from-eight-years-of-being-a-remote-developer-3eob %} {% 連結 https://dev.to/peteranglea/6-months-of-working-remotely-taught-me-a-thing-orten %} 其中許多都傾向於涉及設備和設置。其他建議通常圍繞溝通和團隊合作。不管怎樣,這並不容易,一致、優化的家庭設定對我來說似乎很關鍵。 我們的社區中有數位遊牧者,看到他們如何組織自己是很有趣的: {% 連結 https://dev.to/vickylai/knapsack-problem-algorithms-for-my-real-life-carry-on-knapsack-33jj %} 如果你想走這條路,你的 95% 優化將是完全不同的方法。如果你想做好工作,我建議你不要半途而廢。 這是一篇關於為自己創造出色的開發人員體驗這項重要任務的好文章: {% 連結 https://dev.to/theoutlander/how-to-improve-your-development-experience-ldl %} 言語很重要。我們*是一個分散式團隊*,而不是*遠距工作人員*。這是整個團隊的一個身份,甚至是那些在我們布魯克林辦公室工作的人。 這是一種很棒的工作方式,而且很平凡。快樂編碼。 --- 原文出處:https://dev.to/ben/the-best-remote-work-is-delightfully-unglamorous-4h5f

我正在建立一個人工智慧專案:這是我將要使用的程式庫......

有了正確的函式庫,任何開發人員都可以在他們的應用程式中建立強大的人工智慧功能(如 Ninja 🥷)。 在此列表中,我編譯了 7 個很棒的 AI 庫,您現在可以使用它們(相對)輕鬆地發布功能。 不要忘記為這些圖書館加註星標以表達您的支持。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qqoipyuoxgb83swyoo4a.gif) https://github.com/CopilotKit/CopilotKit --- 1. [CopilotPortal](https://github.com/CopilotKit/CopilotKit) :建構應用程式原生人工智慧聊天機器人 ------------------------------------------------------------------------------- ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0x1bwwzvc2mnrfrvsqn7.png) 應用程式內人工智慧聊天機器人助理可以「查看」您目前的應用程式狀態並在前端和後端採取操作。 一組完全可自訂的反應元件和掛鉤以及用於建立 LLM 和您的應用程式之間互動的架構。 定義*useMakeCopilotReadable* 、 *useMakeCopilotActionable*和*CopilotSidebarUIProvider*使其運作。 ``` import "@copilotkit/react-ui/styles.css"; import { CopilotProvider } from "@copilotkit/react-core"; import { CopilotSidebarUIProvider } from "@copilotkit/react-ui"; export default function App(): JSX.Element { return ( <CopilotProvider chatApiEndpoint="/api/copilotkit/chat"> <CopilotSidebarUIProvider> <YourContent /> </CopilotSidebarUIProvider> </CopilotProvider> ); } ``` https://github.com/CopilotKit/CopilotKit --- 2. [RAGxplorer](https://github.com/gabrielchua/RAGxplorer) - 視覺化並探索您的 RAG 文件 ---------------------------------------------------------------------------- ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z365bk6wa7i4md3w4b5z.png) RAGxplorer 是一個 Python 工具,用於視覺化機器學習和自然語言處理中的 RAG(檢索增強生成)文件。 以互動方式探索 RAG 流程中使用的文件中的聯繫和內容。 若要設定 RAGxplorer,請在程式碼中定義 RAG 檢查點路徑並安裝指定的依賴項。 ``` import streamlit as st from utils.rag import build_vector_database st.set_page_config(page_title="RAGxplorer", page_icon="🔍") uploaded_file = st.file_uploader("Upload your PDF", type='pdf') query = st.text_input("Enter your query") search = st.button("Search") top_k = st.number_input("Number of Chunks", value=5, min_value=1) st.session_state["chroma"] = build_vector_database(uploaded_file, ...) st.session_state['retrieved_id'] = query_chroma(...) plot_embeddings(...) ``` https://github.com/gabrielchua/RAGxplorer --- 3. [Tavily GPT 研究員](https://github.com/assafelovic/gpt-researcher)- 獲得法學碩士以搜尋網路和資料庫 ----------------------------------------------------------------------------------- ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4accv5t5ep1l1tkj4ze2.png) Tavilly 可讓您將 GPT 支援的研究和內容產生工具新增至您的 React 應用程式中,從而增強其資料處理和內容建立功能。 ``` # Create an assistant assistant = client.beta.assistants.create( instructions=assistant_prompt_instruction, model="gpt-4-1106-preview", tools=[{ "type": "function", "function": { "name": "tavily_search", "description": "Get information on recent events from the web.", "parameters": { "type": "object", "properties": { "query": {"type": "string", "description": "The search query to use. For example: 'Latest news on Nvidia stock performance'"}, }, "required": ["query"] } } }] ) ``` https://github.com/assafelovic/gpt-researcher --- 4. [Pezzo.ai](https://github.com/pezzolabs/pezzo) - 開發者優先的 LLMOps 平台 -------------------------------------------------------------------- ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nxvbgi5zkghkb0t64npw.jpeg) 用於管理 OpenAI 通話的集中平台。 優化您的提示和令牌使用。追蹤您的人工智慧使用情況。 免費且易於整合。 ``` const prompt = await pezzo.getPrompt("AnalyzeSentiment"); const response = await openai.chat.completions.create(prompt); ``` https://github.com/pezzolabs/pezzo --- 5. [DeepEval](https://github.com/confident-ai/deepeval) - 評估 LLM、RAG 和微調性能 -------------------------------------------------------------------------- ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dowjupr91bepvopxsudd.jpeg) DeepEval 是一個開源框架,透過將評估視為單元測試來簡化法學碩士的評估。 它提供了評估 LLM 輸出的各種指標,其模組化設計允許開發人員定制他們的評估流程 要使用它,您需要安裝該程式庫、編寫測試案例並執行這些用例來評估您的 LLM 的效能。 ``` Pytest Integration: from deepeval import assert_test from deepeval.metrics import HallucinationMetric from deepeval.test_case import LLMTestCase test_case = LLMTestCase( input="How many evaluation metrics does DeepEval offers?", actual_output="14+ evaluation metrics", context=["DeepEval offers 14+ evaluation metrics"] ) metric = HallucinationMetric(minimum_score=0.7) def test_hallucination(): assert_test(test_case, [metric]) ``` https://github.com/confident-ai/deepeval --- 6. [CopilotTextarea](https://github.com/RecursivelyAI/CopilotKit) - React 應用程式中的 AI 驅動寫作 ---------------------------------------------------------------------------------------- ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a2ctyhzd1hytek22s500.gif) 具有 Github CopilotX 功能的任何 React `<textarea>`的直接替代品。 自動完成、插入、編輯。 可以即時或由開發人員提前提供任何上下文。 ``` import { CopilotTextarea } from "@copilotkit/react-textarea"; import { CopilotProvider } from "@copilotkit/react-core"; // Provide context... useMakeCopilotReadable(...) // in your component... <CopilotProvider> <CopilotTextarea/> </CopilotProvider>` ``` https://github.com/RecursivelyAI/CopilotKit --- 7. [SwirlSearch](https://github.com/swirlai/swirl-search) - 人工智慧驅動的搜尋。 ---------------------------------------------------------------------- ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8f4hycstwmx2gev8di7.gif) Swirl Search 是一個開源平台,它使用人工智慧同時搜尋多個資料來源並提供有關這些資料的起草報告。 它可以跨各種來源進行搜尋,包括搜尋引擎、資料庫和雲端服務,並且可以按照儲存庫中提供的安裝說明輕鬆設定。 Swirl Search 建置在 Python/Django 堆疊上,在 Apache 2.0 授權下發布,並作為 Docker 映像提供,使其可供使用者存取和自訂。 https://github.com/swirlai/swirl-search --- 謝謝閱讀!不要忘記為文章加入書籤,給出您的反應,並支持和查看提到的很棒的庫。 乾杯! --- 原文出處:https://dev.to/copilotkit/im-building-an-ai-project-here-are-the-libraries-im-going-to-use-pd0

專屬雲端的程式語言

> 面向雲程式設計的宣言。 別誤會我的意思,我喜歡雲!它使我能夠建立令人驚嘆的東西,並徹底改變了我使用軟體創新和解決問題的方式。 它是「*新電腦*」、終極電腦、「*無電腦電腦*」。它可以彈性擴展,永遠在線,無處不在,可以做任何事情。這是無邊無際的。它肯定會留在這裡。 但天哪,這絕對不是我們在未來十年內建立雲端應用程式的方式。隨著雲端從“我不想讓伺服器放在我的辦公桌下”發展到“我的應用程式需要30 個不同的託管服務來執行其任務”,我們有點忘記了優秀的開發人員體驗是什麼樣子的。 為雲端建立應用程式有時感覺就像把我孩子的袋子裡未使用的樂高積木灑滿了客廳地板並試圖建造一座城堡。在經歷了撕碎的撲克牌、可怕的芭比娃娃頭和漏電的電池之後,你讀了第一百萬次說明書,卻發現你最終建造的東西與上次建造的東西基本上相同。 分類樂高積木很有趣!和孩子們一起打發時間。它甚至滿足了我的強迫症……但見鬼,這不是我想要建立專業軟體的方式! *讓我試著描述一下我和我的開發人員朋友正在努力解決的問題。* ### 我想專注於為我的用戶創造價值 當我建立專業軟體時,我希望將大部分時間花在應用程式的*功能*領域,而不是我使用的平台的*非功能*機制。 每次我想要在 AWS Lambda 函數內執行程式碼時,我都必須了解它需要與 tree-shaken 依賴項捆綁在一起,作為 zip 檔案上傳到 S3 並透過 Terraform 部署,這是沒有意義的。或者,為了能夠向 SNS 發布訊息,我的 IAM 策略必須有一個允許對主題的 ARN 執行`sns:Publish`操作的語句。*每個開發人員都需要了解 ARN 是什麼嗎?* 所有這些東西與我試圖為用戶創造的價值沒有任何關係。這是純粹的力學。**我們能擺脫它嗎?** ### 我想獨立 作為一名開發人員,最令人沮喪和最扼殺流程的情況之一是我必須停下來等待某人或某事才能繼續前進。 就像快樂地在空中滑翔,欣賞風景,欣賞優美的背景音樂,突然,*砰!*混凝土牆。 當您為雲端建立應用程式時,這堵混凝土牆有多種形狀和尺寸。是 DevOps 人員排隊;需要更新的是 IAM 策略;是只有外部兼職顧問才知道如何除錯的部署失敗;我們希望內部平台中不斷積壓的缺失旋鈕和 API 能夠改變一切。 這些障礙令人沮喪,因為它們迫使我切換環境,應用「臨時」安全策略,並發明我不想談論的醜陋駭客。這是一個破碎的世界。 我想獨立。我希望能夠把事情做好,保持順其自然。我想一次一點地改善世界,並在完成*後*繼續下一件事。我想要完成任務時的多巴胺激增,而不是另一個未完成的線程的羞恥感。 ### 我想要即時回饋 我說過我想要獨立,但不要誤以為我會寫完美的程式碼。這就是為什麼我想用鉛筆而不是鋼筆寫程式碼。 有些開發人員可以花一整天的時間進行編碼,甚至無需呼叫編譯器,最終,他們進行編譯和部署,然後就可以正常工作了。 我很欽佩他們,但我不是那種類型的開發人員。不,先生。對我來說,這就是迭代、迭代、迭代。我從小處開始,用輕鉛筆畫草圖,看一看,擦掉一堆東西,畫一條更粗的線,後退一步,瞇著眼睛,畫更多,擦掉更多,再看一眼,*沖洗並重複*。 這就是為什麼對我來說,最重要的是迭代速度。我越早執行並測試我的應用程式,我就能越快地返回並迭代。這就是我的流量所在。 當我開始程式設計時,我使用 Borland C++。過去,在 IBM PC AT 機器(TURBO ON)上編譯和執行一個程式大約需要 100ms。**雲端中的平均迭代周期需要幾分鐘。分鐘!有時要幾十分鐘!** 這是當今雲端中迭代的樣子:我對程式碼進行了更改;然後我需要編譯它;將其部署到我的測試帳戶;找到管理控制台的方式來實際觸發它;等待它執行並去搜尋 登入另一個服務。然後我意識到有一個錯誤回應告訴我我很愚蠢,因為我怎麼不知道我必須傳入 Accept-Content: application/json,否則我會得到一些名為「XML」的奇怪結果我不知道該怎麼辦(開個玩笑,XML 很棒,不是真的)。現在一切又重新來過… 因此,您說“編寫單元測試”,以居高臨下的方式試圖證明當前的現實是合理的。 「偉大的開發人員編寫單元測試」。好的!因此,現在我需要獲取我的程式碼,該程式碼進行了大約20 個外部API 呼叫,並透過從過時的文件中複製並貼上它們來以某種方式模擬API 回應,結果卻發現我的請求被拒絕了,因為我缺少了一些隱式操作我的 IAM 安全聲明。我們都去過那裡。 **說實話,給我90年代的開發者經驗**。我想要進行更改,並且希望能夠以互動方式或透過在幾毫秒內的單元測試來測試此更改,並且我想坐在沒有 WiFi 的飛機上執行此操作,好嗎? (我們在 90 年代沒有 WiFi)。 ### 所以這只是一句吐槽? 一定不行!我是電腦程式編制員。有時我覺得我從出生起就一直在寫軟體。我一直在社會危險的時期這樣做,當時成為電腦極客並不酷。 我一直喜歡成為開發人員,因為如果我對自己的工具不滿意,我可以製作自己的工具。畢竟,製造工具已經融入了我們的 DNA——人類製造工具的歷史已經超過一百萬年。 我對我的工具不滿意。 2022 年 4 月,我與好朋友、前微軟同事 \[Shai Ber\] 聯手,創立了 \[Wing\],其使命是***為開發者解鎖雲端***。我們聚集了一群令人難以置信的美麗極客,他們與我們一樣對開發人員體驗和開源充滿熱情,並開始了我們的旅程,使開發人員(即我們自己)能夠解決這些基本問題。 ### 編譯器來救援 那麼我們該如何一次解決所有這些問題呢? **我們正在為雲端建立一種程式語言。** 「*一種程式語言!?* 」你問。 “*世界上沒有足夠的程式語言嗎?* ”,“*編寫一個編譯器真的很難嗎?* ”, *“開發人員想要學習一門全新語言的機會有多大?* ”,“*為什麼不能你侵入了現有的語言工具鏈,瞇起眼睛,然後就到此為止了嗎?* ” 我不是一個心血來潮就建立程式語言的人。事實上,我花了過去五年的時間建立 \[AWS CDK\],這是一個*多語言庫*,它允許開發人員使用他們最喜歡的程式語言定義雲端基礎設施,從而解決了我正在談論的一些挑戰。 「滿足開發人員所在的位置」是 AWS 和 CDK 的美好宗旨,它激勵我們建立 \[JSII\] 和 \[constructs\] 等出色的技術。 ***但有時,「他們在哪裡」並不是一個足夠好的模型來創造所需的體驗。*** 用程式碼定義基礎設施確實使我們能夠建立更高層級的抽象,但只要我的應用程式程式碼需要與此基礎設施交互,抽象就變得太\[洩漏\]。我被迫要了解比我需要的更多的知識,而且我必須成為 IAM、VPC、ALB、EBS 等領域的專家,基本上還有比我想記住的更多的 TLA。 我們今天使用的語言都是圍繞著*電腦是一台機器*的想法而設計的。他們已經達到了能夠為我們提供對這些機器的可靠抽象的程度。它們抽象化了 CPU、記憶體、檔案系統、行程管理和網路。作為開發人員,我不必關心文件在磁碟上的佈局方式,甚至不必關心哈希映射需要多少記憶體。我只需寫`readFile()`或`new Dictionary()`即可開始我的一天。是的,對我來說,了解幕後發生的事情並不是一個壞主意,但我並不是被迫這樣做。 大多數這些語言還為我提供類型安全。當我使用錯誤數量的參數呼叫函數時,我的編譯器會對我大喊大叫。我不必等到我的應用程式執行時才意識到我忘記了參數,或者傳遞了錯誤的類型。 **在雲端,我獨自一人**。每當我的程式碼需要與雲端資源或服務互動時(隨著產業的發展,這種情況越來越多)我必須放棄程式語言的舒適性和安全性。我必須跳出機器的邊界,進入網路的狂野西部,而我的編譯器卻一無所知。 突然之間,所有痛苦的來源幾乎變得非常明顯。如今的雲端應用程式只是由互不相連的部分拼湊而成。我有一個用於我的基礎設施的編譯器,另一個用於我的函數,另一個用於我的容器,另一個用於我的 \[CI/CD 管道\]。每個機器都非常認真地對待自己的工作,並讓我在每台機器中保持安全和快樂,但我的應用程式不再在單台機器上執行,我的應用程式在雲端上執行。 ***雲就是計算機。*** ### Wing,一種面向雲端的程式語言 當新的程式設計範式出現時,語言需要時間來迎頭趕上。我曾經喜歡用 C 語言建立物件導向的程式碼,但它是一個有漏洞的抽象。我必須了解物件在記憶體中的佈局方式、\[V 表\] 的工作原理,並記住將物件作為每個函數的第一個參數傳遞。當程式語言開始像一等公民一樣支援物件導向的概念時,這種範式就民主化了,今天大多數開發人員甚至不知道 V 表是什麼,世界一直在旋轉。 **Wing** ,或者***winglang,***如果你想可愛一點的話,它擁有你所期望的現代、面向物件、強類型和通用語言的所有好東西,但它還包括一些額外的原語,旨在支持分佈式雲作為一等公民的基於服務的性質。 ### 一探究竟 我們在 Wing 上的工作已經快一年了,我很高興邀請您查看並告訴我您的想法。雖然仍處於 Alpha 階段,尚未準備好投入生產使用,但已經可以用它來建立一些[實際的應用程式](https://github.com/winglang/research/tree/main/dogfooding)。 https://github.com/winglang/wing --- 原文出處:https://dev.to/winglang/cloud-why-so-difficult-3j33

開源 SaaS:您無需為 SaaS 模板付費

展示開放 SaaS 🎉 ----------- 我們非常高興推出[Open SaaS](https://opensaas.sh) ,這是適用於 React、NodeJS 和 Prisma 的完全免費、開源、生產級 SaaS 樣板。 在這裡查看它的實際效果: https://www.youtube.com/watch?v=rfO5SbLfyFE Open SaaS 擁有您最近看到的那些付費 SaaS 入門者的所有功能,除了它完全**免費**且**開源**。 **我們覺得為一些需要自己管理的樣板程式碼支付 300-2,000 美元是瘋狂的**。最重要的是,許多樣板文件嚴重依賴第三方服務。再加上託管和其他費用,您需要花費大量資金才能將您的想法推向世界。 **這就是為什麼透過開放 SaaS,我們有意識地決定盡可能嘗試使用開源和免費服務。**例如,我們在[OpenSaaS.sh](http://OpenSaaS.sh)上託管的演示應用程式及其管理儀表板由 Plausible 分析的自架版本提供支援。希望您的 SaaS 具有相同的功能嗎?那麼,Open SaaS 已為您預先配置好! 此外,Open SaaS 使用的[Wasp 框架](https://wasp.sh)可以為您建立許多功能,例如 Auth 和 Cron 作業,這樣您就不必支付第三方服務費用或完全自己編寫程式碼(我們稍後會更詳細地解釋這一點)。 在我們開始之前... ---------- 悠悠悠悠👋 [![開放 SaaS - 開源且 100% 免費的 React 和 Node.js SaaS 初學者! |產品搜尋](https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=436467&theme=light)](https://www.producthunt.com/posts/open-saas?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-open-saas) Open SaaS[現已在 Product Hunt](https://www.producthunt.com/posts/open-saas)上線!快來支持我們的免費開源倡議🙏 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wppn8mlby0p7h1f8xl6w.png)](https://www.producthunt.com/posts/open-saas) 為什麼我們要建造它......然後免費贈送它 ---------------------- [我們預發布版本](https://devhunt.org/tool/open-saas)中的初步回饋基本上是正面的,但我們也收到了一些問題,例如: - “它會保持免費嗎?” - “您開源這個的動機是什麼?” 所以我們認為我們應該先回答這些問題。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5rac9o1rxgrwfx51mc50.png) 首先,是的,它是 100% 免費和開源的,並將保持這種狀態。 其次,我們相信,開發者、獨立駭客和個人企業家社群的集體知識將比個人或小團體產生更好的樣板。當您從某些開發人員那裡購買SaaS 入門版時,您已經獲得了一個固執己見的堆棧,然後除此之外,您還獲得了按照他們認為最好的方式建置的應用程式- 這可能並不總是最適合*您。* 第三, [Open SaaS](https://opensaas.sh)是[Wasp](https://wasp.sh)的一個專案,一個超強的開源React + NodeJS + Prisma全端框架。我們 Wasp 團隊相信 Wasp 非常適合快速且有效率地建立 SaaS 應用程式,我們希望這個模板能夠證明這一點。另外,身為開發人員,我們從其他開源專案中學到了很多東西,而 Wasp 本身就是一個開源專案。 基本上,我們熱愛開源理念,並且希望將其發揚光大。 🙏 因此,我們希望能夠為開發者社群提供非常有價值的資產,同時宣傳我們的開源全端框架。我們很高興看到社區為其做出貢獻,以便它不斷發展並成為最好的 SaaS 樣板。 開放 SaaS 是由什麼組成的 --------------- 我們在 Open SaaS 上投入了大量的精力,包括[文件](https://docs.opensaas.sh),以便開發人員可以自信、輕鬆地啟動 SaaS 應用程式。 我們還花了一些時間檢查其他免費的開源 SaaS 啟動器,並希望確保 Open SaaS 具有可立即投入生產的啟動器的所有正確功能,而不顯得臃腫。我們認為我們已經在很大程度上實現了這一點,儘管我們將繼續加入功能並隨著時間的推移進行改進。 目前的主要特點如下: - 🔐 身份驗證(電子郵件驗證、Google、github) - 📩 電子郵件(sendgrid、emailgun、SMTP) - 📈 管理儀表板(合理或谷歌分析) - 🤑 Stripe 付款(只需加入您的訂閱產品 ID) - ⌨️ 端對端類型安全性(無需配置) - 🤖 OpenAI 整合(AI 驅動的範例應用程式) - 📖 Astro 博客 - 🚀 部署在任何地方 - 📄 完整的文件和社群支持 值得深入了解其中每個功能的細節,所以讓我們開始吧。 ### 授權 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wbistoghxrxft9zxxra1.png)](https://www.producthunt.com/posts/open-saas) 感謝 Wasp,Open SaaS 附帶了許多可能的身份驗證方法: - 使用者名稱和密碼(最簡單/最容易進行開發測試) - 已驗證電子郵件並重設密碼 - Google 和/或 Github 社群登入 這就是 Wasp 真正發揮作用的地方,因為設定全端 Auth 並取得預先配置的 UI 元件所需要做的就是: ``` //main.wasp app SaaSTemplate { auth: { userEntity: User, methods: { usernameAndPassword: {}, google: {}, gitHub: {}, } } } ``` 嚴重地。就是這樣! 只需確保您已設定社交身份驗證並擁有 API 金鑰以及定義的`User`和`ExternalAuth`實體,就可以開始了。不用擔心,這部分內容已在[Open SaaS Docs](https://docs.opensaas.sh)中詳細記錄和解釋。 最重要的是,Open SaaS 預先配置了一些範例,說明如何自訂和建立一些真正強大的身份驗證流程。 ### 管理儀表板和分析 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4mm6s1c3txxgm49e2k7w.png)](https://www.producthunt.com/posts/open-saas) 透過利用[Wasp 的工作功能](https://wasp-lang.dev/docs/advanced/jobs),Open SaaS 每小時從 Plausible 或 Google 的網站分析(您的選擇!)和 Stripe 的資料 API 中提取資料,並將其保存到我們的資料庫中。然後,該資料將顯示在我們的管理儀表板上(前往[OpenSaaS.sh](https://OpenSaaS.sh)查看其實際情況)。好的部分是,要為您自己的應用程式存取這些資料,您所要做的就是按照我們的指南獲取分析 API 金鑰,插入提供的腳本,然後就可以開始了! 再次強調,Wasp 讓整個過程變得非常簡單。透過已經為您定義的查詢 API 和取得我們需要的資料的功能,Open SaaS 然後在`main.wasp`設定檔中使用 Wasp 作業: ``` job dailyStatsJob { executor: PgBoss, perform: { fn: import { calculateDailyStats } from "@server/workers/calculateDailyStats.js" }, schedule: { cron: "0 * * * *" }, entities: [User, DailyStats, Logs, PageViewSource] } ``` 就是這樣! Wasp 負責為您設定和執行 cron 作業。 ### 條紋支付 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ugy3mx9xo1d9i9vfysr7.png)](https://www.producthunt.com/posts/open-saas) 如果您是以前從未建立過自己的 SaaS 的開發人員,那麼與 Stripe 這樣的支付處理器整合可能是您將面臨的少數挑戰之一。 當我建立第一個 SaaS [CoverLetterGPT.xyz](https://coverlettergpt.xyz)時,我的情況就是如此。這實際上是我建造它的主要動機之一;了解如何將 Stripe 支付整合到應用程式以及 OpenAI API 中。 儘管 Stripe 因擁有豐富的文件而聞名,但這個過程仍然令人畏懼。你必須: - 建立正確的產品類型 - 設定 webhook 端點 - 告訴 Stripe 將正確的 Webhook 事件傳送給您 - 正確使用事件 - 處理重複付款和失敗付款 - 在上線之前透過 CLI 進行正確測試 這就是為什麼為您設定 Stripe 訂閱付款是一個巨大的勝利。 但比這更重要的是,為您方便地記錄整個過程!這就是為什麼 Open SaaS[在我們的文件中為您提供方便的 Stripe 指南](https://docs.opensaas.sh)🙂 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uehwot350u3dl02s4w7r.png)](https://www.producthunt.com/posts/open-saas) ### 端對端類型安全 Open SaaS 是使用 Typescript 建置的,因為它是一個全棧應用程式,所以從後端到前端的類型安全可以成為真正的救星。我的意思是,一些[固執己見的堆疊](https://create.t3.gg/)在此基礎上變得非常流行。 幸運的是,Wasp 為您提供開箱即用的端到端類型安全性(無需配置!),因此 Open SaaS 可以輕鬆利用它。 這是一個例子: 1. 讓 Wasp 了解您的伺服器操作: ``` // main.wasp action getResponse { fn: import { getResponse } from "@server/actions.js", entities: [Response] } ``` 2. 輸入並實施您的伺服器操作。 ``` // src/srever/actions.ts type RespArgs = { hours: string; }; const getResponse: GetResponse<RespArgs, string> = async ({ hours }) => { } ``` 3. 導入並在客戶端呼叫。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fah81r1g4bg3vdqapju.png) 客戶端類型將被正確推斷! ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7n04yh6de9slhhnjrgf3.png) ### AI 驅動的範例應用程式(附有 OpenAI API) [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbbc2gkxbxjl3q2y01a3.png)](https://www.producthunt.com/posts/open-saas) 人工智慧正在使新的應用程式創意成為可能,這也是我們看到開發人員對建立 SaaS 應用程式的興趣重新抬頭的部分原因。正如我上面提到的,我建造的第一個 SaaS 應用程式[CoverLetterGPT](https://coverlettergpt.xyz)是「GPT 包裝器」之一,我很自豪地說它帶來了約350 美元MRR(每月經常性收入)的可觀被動收入。 我個人認為,我們在軟體開發方面處於最佳狀態,開發新的、有利可圖的人工智慧應用程式有很大的潛力,尤其是「獨立駭客」和「個人企業家」。 這就是 Open SaaS 推出 AI 調度助手演示應用程式的原因。您輸入任務及其分配的時間,AI Scheduler 會為您的一天建立詳細的計劃。 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j4suf7g9jm5w93ri3bqx.png)](https://www.producthunt.com/posts/open-saas) 在幕後,這是使用 OpenAI 的 API 為每個任務分配優先級,並將它們分解為詳細的子任務,包括喝咖啡休息時間!它還利用 OpenAI 的函數呼叫功能以使用者定義的 JSON 物件形式回傳回應,以便客戶端每次都能正確使用它。此外,我們計劃在未來加入開源法學碩士,敬請期待! 示範版 AI Scheduler 可協助開發人員學習如何有效使用 OpenAI API,並激發一些 SaaS 應用程式創意! ### 隨處部署。容易地。 許多流行的 SaaS 新創公司都使用依賴託管的框架,這意味著您只能依賴一個提供者進行部署。雖然這些都是簡單的選擇,但它可能並不總是最適合您的應用程式。 Wasp 為您提供了部署全端應用程式的無限可能性: - 使用`wasp deploy`一鍵部署到[Fly.io](http://Fly.io) - 使用`wasp build`並部署 Dockerfiles 和客戶端,無論您喜歡什麼! `wasp deploy`的優點在於它會自動產生和部署您的資料庫、伺服器和用戶端,並為您設定環境變數。 Open SaaS 還內建了環境變數和常數驗證器,以確保您已正確設定部署所需的所有內容,以及文件中的部署指南 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fihbij250xtbdtjbjoks.png)](https://www.producthunt.com/posts/open-saas) 最後,您擁有自己的程式碼,並且可以自由地將其部署到任何地方,而無需受供應商鎖定。 幫助我們,幫助你 -------- [![開放 SaaS - 開源且 100% 免費的 React 和 Node.js SaaS 初學者! |產品搜尋](https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=436467&theme=light)](https://www.producthunt.com/posts/open-saas?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-open-saas) 想支持我們的免費開源計畫嗎?那麼現在就去[Product Hunt 上](https://www.producthunt.com/posts/open-saas)向我們提供一些支援吧! 🙏 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wppn8mlby0p7h1f8xl6w.png)](https://www.producthunt.com/posts/open-saas) 現在就開始建立您的 SaaS! --------------- 我們希望 Open SaaS 能夠讓更多的開發人員能夠發布他們的想法和副專案。我們也希望從開發人員那裡獲得一些回饋和意見,以便我們能夠使其成為最好的 SaaS 樣板啟動器。 因此,如果您有任何意見或發現任何錯誤,請[在此處提交問題](https://github.com/wasp-lang/open-saas/issues)。 如果您發現 Open SaaS 和/或 Wasp 很有用,最簡單的支援方法就是給我們一顆星: - 為[Open SaaS 儲存庫](https://github.com/wasp-lang/open-saas)加註星標 - 給[黃蜂倉庫](https://github.com/wasp-lang/wasp)加註星標 --- 原文出處:https://dev.to/wasp/you-dont-need-to-pay-for-saas-boilerplates-open-saas-56lj

資料庫 101:如何為 100 萬玩家的遊戲建立排行榜模型。

有沒有想過像**《英雄聯盟》** 、 **《要塞英雄**》甚至**《Rockband》**這樣的遊戲是如何建立排行榜模型的?在本文中,我們將了解如何正確建模模式以以極其高效的方式處理它們! 如果您剛開始使用一般資料庫或資料庫,您可能需要閱讀我的第一篇文章[《資料庫 101:初學者的資料一致性](https://dev.to/danielhe4rt/database-101-why-so-interesting-1344)》。那篇文章記錄了我自己對有多少資料庫範例的探索,因為我的眼光遠遠超出了我以前僅使用 SQL 和 MySQL 的經驗。我正在**資料庫 101**系列中追蹤我的研究。 > 距離我發表本系列的第一篇文章已經快一年了!感謝您在我學習主題時與我在一起。您的評論和想法總是非常有幫助! 1. 序言 ----- ![YARG 遊戲玩法截圖](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvensca2v67ma66vssnh.png) 從我還是個孩子的時候起,就像大多數普通開發者一樣,我就對遊戲及其製作方式著迷。說到這裡,我要跟大家介紹一下我兒時最喜歡的遊戲:《吉他英雄3:搖滾傳奇》。 十多年後,我決定嘗試在開源環境中為一些遊戲做出貢獻,例如[rust-ro(Rust Ragnarok Emulator)](https://github.com/nmeylan/rust-ro)以及本文的主角: [YARG(Yet Another Rhythm Game)](https://github.com/YARC-Official/YARG) 。 YARG 實際上是另一個節奏遊戲,但這個專案的不同之處在於它是完全**開源的**,他們聯合了遊戲開發和設計方面的傳奇貢獻者來讓這個專案能夠運作。 突然之間,這款遊戲被 Twitch 上的 Guitar Hero/Rockband 主播們所採用並玩,我想:好吧,這是一個開源專案,所以也許我可以利用我的資料庫技能來建立一個**速度極快的排行榜**或儲存過去的比賽。 一開始只是在他們的 Discord 上進行了一次簡單的聊天,後來變成了關於如何讓這個專案更快發展的長時間討論。 然後我決定和我的老闆談談,問他我是否可以和 YARG 的人一起工作,條件是建立一些足夠酷的東西來實現[ScyllaDB(NoSQL 寬列資料庫)](https://scylladb.com/) ,因為我在那裡擔任開發倡導者。您不會相信ScyllaDB帶來的簡單性和可擴展性如何完美契合YARG.in的需求! 無論如何,談話是廉價的。讓我向您展示一些程式碼和概念! 2.QDD-查詢驅動的資料建模 --------------- ![NoSQL 與關係型資料庫](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ivkj9j8ni2fakkctx53n.png) 當我們談論使用**NoSQL**進行開發時,大多數情況下我們應該理解,根據範例(文件、圖形、寬列等),您應該先了解**要執行哪個查詢**。 在 MySQL 中,主要目標是了解一致性,而在 Scylla 中,您應該專注於查詢並基於該查詢建立模式。 在這個專案中,我們將處理兩種類型的範例,它們是: - 核心價值 - 寬列(聚類) 現在讓我們來談談我們建模的查詢/功能。 ### 2.1 功能:儲存匹配 ![提交詳情 YARG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jaw4q7349upgrsa5p5g3.png) 每次完成 YARG 遊戲時,最有趣的事情就是提交您的分數以及許多其他遊戲內指標。 基本上它將是基於主索引的單一查詢,僅此而已。 ``` SELECT score, stars, missed_notes, instrument, ... FROM leaderboard.submisisons WHERE submission_id = 'some-uuid-here-omg' ``` ### 2.2 功能:排行榜 ![排行榜 Figma 文件](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69jp0vgxef71titt9ks0.png) 現在我們的主要目標是:一個超酷的**排行榜**,在良好的資料建模之後你不需要關心它。排行榜是按歌曲計算的,因此每次您播放特定歌曲時,您的最佳成績都會被保存並排名。 然而,這個介面有一個重要的點,那就是有過濾器來準確地知道要帶來「哪個」排行榜: - 歌曲 ID:必填 - 儀器:必填 - 修飾符:必需 - 難度:必填 - 玩家 ID:可選 - 分數:可選 想像一下我們的查詢如下所示,它會傳回按分數降序排列的結果: ``` SELECT player_id, score, ... FROM leaderboard.song_leaderboard WHERE instrument = 'guitar' AND difficulty = 'expert' AND modifiers = {'none'} AND track_id = 'dani-california' LIMIT 100; -- player_id | score ----------------+------- -- tzach | 12000 -- danielhe4rt | 10000 -- kadoodle | 9999 ----------------+------- ``` 現在我們知道了將在這裡使用的功能,但是您能想像最終的模式將如何嗎? 不?好的,讓我來幫助你! 3. 資料建模時間! ---------- 是時候深入研究 ScyllaDB 的資料建模並更好地了解如何擴展它了。 ### 3.1 - 匹配建模 ![遊戲結束畫面](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b6kedk7iu67zg7myj9mp.png) 首先,讓我們先來了解遊戲本身: - 這是一個節奏遊戲; - 您一次播放一首特定的歌曲; - 您可以在遊戲前啟動“修改器”,讓您的生活變得更輕鬆或更困難; - 您必須選擇一種樂器(例如吉他、鼓、貝斯和麥克風)。 - 遊戲玩法的各個方面都會被跟踪,例如: - Score; - Missed notes; - Overdrive count; - Play speed (1.5x ~ 1.0x); - Date/time of gameplay; - And other cool stuff. 考慮到這一點,我們可以輕鬆地開始我們的資料建模,這將變成這樣: ``` CREATE TABLE IF NOT EXISTS leaderboard.submissions ( submission_id uuid, track_id text, player_id text, modifiers frozen<set<text>>, score int, difficulty text, instrument text, stars int, accuracy_percentage float, missed_count int, ghost_notes_count int, max_combo_count int, overdrive_count int, speed int, played_at timestamp, PRIMARY KEY (submission_id, played_at) ); ``` 讓我們跳過所有`int/text`值並跳到`set<text>` 。 **集合**類型可讓您儲存特定類型的專案清單。我決定使用這個清單來儲存修飾符,因為它非常適合。看看查詢是如何執行的: ``` INSERT INTO leaderboard.submissions ( submission_id, track_id, modifiers, played_at ) VALUES ( some-cool-uuid-here, 'starlight-muse' {'all-taps', 'hell-mode', 'no-hopos'}, '2024-01-01 00:00:00' ); ``` 使用這種類型,您可以輕鬆儲存專案清單以供以後檢索。 另一個很酷的資訊是這個查詢是一個鍵值對!這意味著什麼? 由於您始終僅透過`submission_id`來查詢它,因此它可以歸類為鍵值。 ### 3.2 排行榜建模 ![排行榜濾鏡 Figma](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lpmzngra3jk5ipf3os3i.png) 在本文的這一部分中,您將學習一些很酷的寬列資料庫概念。 在我們的排行榜查詢中,如前所述,我們總是需要在 WHERE 子句中使用一些動態值,這意味著這些值將屬於**分區鍵**,而**聚類鍵**將具有可以是「可選」的值。 **分區鍵**是基於您新增的用於標識值**的欄位組合的**雜湊。你明白了嗎?不?好吧,我也花了一段時間才明白這一點,但讓我向你展示一些東西: 假設您玩了`Starlight - Muse` 100 次。如果您要查詢此訊息,將透過`score`或`player_id`等聚類鍵區分出100倍不同的結果。 ``` SELECT player_id, score --- FROM leaderboard.song_leaderboard WHERE track_id = 'starlight-muse' LIMIT 100; ``` 如果有 1.000.000 個玩家播放這首歌,你的查詢會變得很慢,並且將來會成為一個問題,因為你的分區鍵只包含一個字段,即`track_id` 。 但是,如果您向**Partition Key**加入更多字段,例如玩遊戲之前的強制性內容,也許我們可以縮小這些可能性以實現更快的查詢。現在你看到大局了嗎?加入諸如**“樂器”** 、 **“難度**”和**“修改器”等**欄位將為您提供一種均勻分割有關特定曲目的資訊的方法。 讓我們想像一些簡單的數字: ``` -- Query Partition ID: '1' SELECT player_id, score, ... FROM leaderboard.song_leaderboard WHERE instrument = 'guitar' AND difficulty = 'expert' AND modifiers = {'none'} AND -- Modifiers Changed track_id = 'starlight-muse' LIMIT 100; -- Query Partition ID: '2' SELECT player_id, score, ... FROM leaderboard.song_leaderboard WHERE instrument = 'guitar' AND difficulty = 'expert' AND modifiers = {'all-hopos'} AND -- Modifiers Changed track_id = 'starlight-muse' LIMIT 100; ``` 因此,如果您以特定形狀建立查詢,它將始終查找特定令牌並根據這些特定分區鍵檢索資料。 我們來看看最終的建模,談談聚類鍵和應用層: ``` CREATE TABLE IF NOT EXISTS leaderboard.song_leaderboard ( submission_id uuid, track_id text, player_id text, modifiers frozen<set<text>>, score int, difficulty text, instrument text, stars int, accuracy_percentage float, missed_count int, ghost_notes_count int, max_combo_count int, overdrive_count int, speed int, played_at timestamp, PRIMARY KEY ((track_id, modifiers, difficulty, instrument), score, player_id) ) WITH CLUSTERING ORDER BY (score DESC, player_id ASC); ``` 分區鍵的定義如上所述,由我們**所需的參數**組成,例如:track\_id、修飾符、難度和樂器。在**聚類鍵**上,我們新增了**Score**和**player\_id** 。 > 請注意,預設情況下,聚類欄位按`score DESC`排序,以防萬一玩家得分相同,選擇獲勝者的標準將按`alphabetical` ¯\\\_(ツ)\_/¯。 首先很容易理解的是,我們**每個玩家只有一個分數**,但透過這種建模,如果玩家以不同的分數兩次經歷同一條賽道,它將產生兩個不同的條目。 ``` INSERT INTO leaderboard.song_leaderboard ( track_id, player_id, modifiers, score, difficulty, instrument, stars, played_at ) VALUES ( 'starlight-muse', 'daniel-reis', {'none'}, 133700, 'expert', 'guitar', '2023-11-23 00:00:00' ); INSERT INTO leaderboard.song_leaderboard ( track_id, player_id, modifiers, score, difficulty, instrument, stars, played_at ) VALUES ( 'starlight-muse', 'daniel-reis', {'none'}, 123700, 'expert', 'guitar', '2023-11-23 00:00:00' ); SELECT player_id, score FROM leaderboard.song_leaderboard WHERE instrument = 'guitar' AND difficulty = 'expert' AND modifiers = {'none'} AND track_id = 'starlight-muse' LIMIT 2; -- player_id | score ----------------+------- -- daniel-reis | 133700 -- daniel-reis | 123700 ----------------+------- ``` 那我們要如何解決這個問題呢?嗯,這本身不是問題。這是一個特點!哈哈 身為開發人員,您必須根據專案需求建立自己的業務規則,這也不例外。我這麼說是什麼意思? 您可以在插入新條目之前執行簡單的**DELETE**查詢,並確保在該特定**分區鍵**組內, **player\_id**中的特定資料不會低於新**分數**。 ``` -- Before Insert the new Gampleplay DELETE FROM leaderboard.song_leaderboard WHERE instrument = 'guitar' AND difficulty = 'expert' AND modifiers = {'none'} AND track_id = 'starlight-muse' AND player_id = 'daniel-reis' AND score <= 'your-new-score-here'; -- Now you can insert the new payload... ``` 這樣我們就完成了簡單的排行榜系統,該系統與 YARG 中執行的系統相同,也可以在每秒數百萬個條目的遊戲中使用:D 4. 如何為 YARG 做出貢獻 ---------------- 這是我邀請您為這個精彩的開源專案做出貢獻的文字部分! 今天,我們正在為所有玩家建立一個全新的平台,使用: - 遊戲:Unity3d [(儲存庫)](https://github.com/YARC-Official/YARG) - 前端:NextJS [(儲存庫)](https://github.com/YARC-Official/yarg.in) - 後端:Laravel 10.x [(儲存庫)](https://github.com/YARC-Official/yarg-api) 我們將需要盡可能多的開發人員和測試人員與主要貢獻者一起討論遊戲的未來實現! ![YARG 不和諧](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y5b2pdxvrth2o6jfmada.png) 首先,請確保加入他們的[Discord 社群](https://discord.gg/sqpu4R552r)。在進入開發板之前,所有技術討論都會在社群後台進行。 此外,在 Discord 之外,YARG 社群主要關注[EliteAsian](https://twitter.com/EliteAsian123) (核心貢獻者和專案所有者)Twitter 帳戶的開發展示。一定要跟著他去那裡。 https://twitter.com/EliteAsian123/status/1736149319382671766 僅供參考,遊戲的**首席美術師**(又稱[Kadu)](https://twitter.com/kaduyarg)也是**Elgato**的**廣播專家**和**產品創新**開發人員,曾與以下串流媒體合作: - 忍者 - 納德肖特 - 石山64 - 以及傳奇 DJ Marshmello。 Kadu 也使用他的 Twitter 分享一些見解以及 YARG 新功能和實驗的早期預覽。所以,別忘了在 Twitter 上關注他! https://twitter.com/kaduyarg/status/1689489132060397568 以下是一些有用的連結,可以幫助您了解有關該專案的更多訊息: - [官方網站](https://yarg.in/) - [Github 儲存庫](https://github.com/YARC-Official/YARG) - [任務板](https://yarg.youtrack.cloud/agiles/147-7/current) > 有趣的事實:YARG 受到了 Guitar Hero 專案負責人[Brian Bright](https://twitter.com/BrianBright/status/1744533504531317194)的關注,他喜歡該專案的開源特性。太棒了,對吧? 5. 結論 ----- 資料建模有時具有挑戰性,這項研究花了 3 個月的時間研究了許多新的 ScyllaDB 概念,並與我在 Twitch 的社群一起進行了大量測試。 我還發布了[遊戲排行榜演示](https://github.com/scylladb/gaming-leaderboard-demo),您可以在其中獲得有關如何使用**NextJS**和**ScyllaDB**實現同一專案的一些見解! 另外,如果您喜歡 ScyllaDB 並想了解更多訊息,我強烈建議您觀看我們的免費[大師班課程](https://lp.scylladb.com/masterclass-ondemand-main?siteplacement=navigation)或存取[ScyllaDB 大學](https://university.scylladb.com/)! 不要忘記喜歡這篇文章,在社交上關注我並填滿你的水瓶 xD 下一篇文章見! [在推特上關注我](https://twitter.com/danielhe4rt) [在 Github 上關注我](https://twitter.com/danielhe4rt) [在 Github 上關注我](https://twitter.com/danielhe4rt) [關注並訂閱我的 Twitch 頻道](https://twitch.tv/danielhe4rt) --- 原文出處:https://dev.to/danielhe4rt/database-101-how-to-model-leaderboards-for-1m-players-game-2pfa

使用 Flexbox 實現極為簡單的行和列佈局

CSS 中的超簡單響應式行和列 ================== 網格佈局是 Web 開發設計的基礎,您很可能已經使用 Bootstrap 或 Foundation 等工具來使您的佈局成為現實。但是,像你們大多數人一樣,我不喜歡執行 Bootstrap 或 Foundation 所需的依賴項,也不喜歡頁面加載時間的叮噹聲。 事實上,當我將Bootstrap 用於我正在編寫的應用程式時,我幾乎只將它用於網格佈局,有時我會將它用於通知或基本的相當合理的CSS 預設值,但90% 的時間,我想要的都是是網格佈局。 我也不喜歡只有將列拆分為 12 列或更少的選項。感覺有時你必須做一些瘋狂的工作才能讓列成列,或類似奇怪的事情。 我們如何更快、更輕鬆地進行網格佈局? Flexbox 就是您的答案。我認為 ### flexbox 此時,flexbox 幾乎無所不在。所有主要[瀏覽器](https://caniuse.com/#feat=flexbox)都支援它。它允許更簡單的佈局,並且受到 React-Native 的支持,這意味著當我為 React-Native 佈局頁面時,我首先會使用 Flexbox,但我發現自己在 Web 開發中也首先使用了 Flexbox。 事實上,我佈置的最後一個應用程式完全是使用 Flexbox 完成的。我發現它*很*容易使用。 如果您對 Flex Box 不太了解。我喜歡這個頁面,它很好地介紹了[Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) ### layout 首先,我將整個頁麵包裹在一個 div 中。 ``` <div class='some-page-wrapper'> </div> ``` 然後我定義一個可以幫助佈局的`.row`和`.column`類別。 ``` .row { display: flex; flex-direction: row; flex-wrap: wrap; width: 100%; } .column { display: flex; flex-direction: column; flex-basis: 100%; flex: 1; } ``` 現在,如果我們想要兩列佈局: ``` <div class='some-page-wrapper'> <div class='row'> <div class='column'> <div class='blue-column'> Some Text in Column One </div> </div> <div class='column'> <div class='green-column'> Some Text in Column Two </div> </div> </div> </div> ``` CSS 看起來像: ``` .some-page-wrapper { margin: 15px; background-color: red; } .row { display: flex; flex-direction: row; flex-wrap: wrap; width: 100%; } .column { display: flex; flex-direction: column; flex-basis: 100%; flex: 1; } .blue-column { background-color: blue; height: 100px; } .green-column { background-color: green; height: 100px; } ``` https://codepen.io/drews256/pen/zLerNx 如果我們想新增第三列怎麼辦? HTML 可以輕鬆更新為: ``` <div class='some-page-wrapper'> <div class='row'> <div class='column'> <div class='blue-column'> Some Text in Column One </div> </div> <div class='column'> <div class='green-column'> Some Text in Column Two </div> </div> <div class='column'> <div class='orange-column'> Some Text in Column Two </div> </div> </div> </div> ``` https://codepen.io/drews256/pen/djaYKo 我們新增了第三列。這無縫地融入了我們的行。 https://codepen.io/drews256/pen/djaYKo 現在如果我們想要更複雜的佈局呢? 我們可以加入更多行,這非常簡單。 ``` <div class='some-page-wrapper'> <div class='row'> <div class='column'> <div class='orange-column'> Some Text in Column One </div> </div> <div class='column'> <div class='blue-column'> Some Text in Column Two </div> </div> <div class='column'> <div class='green-column'> Some Text in Column Three </div> </div> </div> <div class='row 2'> <div class='column'> <div class='green-column'> Some Text in Row 2, Column One </div> </div> <div class='column'> <div class='orange-column'> Some Text in Row 2, Column Two </div> </div> <div class='column'> <div class='blue-column'> Some Text in Row2, Column Three </div> </div> </div> </div> ``` https://codepen.io/drews256/pen/WKPwxN 或者我們可以調整列的大小。 要擁有雙列,我們可以新增一個`.double-column`類別。不過,這可以適用於任何尺寸的列,您可以做60/40,您可以做10/10/10/10/10/10/10/10/10/10,老實說,這裡任何組合都是可能的。您可以做 1 X 100。或 10 x 1,然後 20 x 3,然後 30 x 1。選項是無窮無盡的! 在一種佈局上,我在“列”周圍加入了很大的邊距,並且由於行將向下滾動,因此我有一行包含所需數量的“列”。這些列是固定寬度的卡片,因此它們只是換行到下一行,而彈性盒巧妙地響應式地將卡片沿著螢幕包裹起來。 ``` .double-column { display: flex; flex-direction: column; flex-basis: 100%; flex: 2; } ``` https://codepen.io/drews256/pen/djaMWj 但這不是很敏感嗎?我們可以使用媒體查詢來加入一些響應性。 只需將`flex: 1`和`flex: 2`移動到媒體查詢(大小取決於應用程式,我只是提供一個選項) ``` @media screen and (min-width: 800px) { .column { flex: 1 } .double-column { flex: 2 } } ``` `> 800` 像素時: ![反應速度大,大於 800](https://thepracticaldev.s3.amazonaws.com/i/vzblza9096iap76a55ju.png) `< 800` 像素時: ![低於800時有響應](https://thepracticaldev.s3.amazonaws.com/i/g4vz31amzqbpn5duuu5l.png) 最終的codepen,提示點擊右下角的1x或0.5x按鈕來查看「響應式」佈局的差異。 https://codepen.io/drews256/pen/bjzpvd 本質上,我們只是用 20 行 CSS 將 bootstrap 的行/列從水中炸出來。我們有一種快速建立行/列佈局的方法,而且由於我們使用 Flexbox,我們幾乎不必擔心佈局會破壞或出現任何問題。它可以輕鬆適應各種用途,並允許大量的可自訂性。您對彈性盒有何看法?你試過了嗎? 另一個隱藏的好處是,如果我以這種方式佈局 React 元件,那麼很容易佈局 React-Native 元件,使其看起來相似。 我通常在我的專案中使用 SCSS,所以如果您發現一些不完美的 CSS,請告訴我! --- 原文出處:https://dev.to/drews256/ridiculously-easy-row-and-column-layouts-with-flexbox-1k01

🪄與您的簡歷製作者聊天 - 使用 Next.js、OpenAI 和 CopilotKit 📑✨

#TL;博士 在本文中,您將了解如何使用 Nextjs、CopilotKit 和 OpenAI 建立人工智慧驅動的簡歷產生器應用程式。 我們將涵蓋: - 利用 ChatGPT 撰寫履歷和求職信 📑 - 透過與履歷聊天逐漸完善你的履歷💬 - 將您的履歷和求職信匯出為 PDF 🖨️ ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jxzcx6jqet2anmr2pu6c.gif) --- ## CopilotKit:建構深度整合的應用內人工智慧聊天機器人 💬 只是簡單介紹一下我們的背景。 CopilotKit 是[開源 AI 副駕駛平台。](https://github.com/CopilotKit/CopilotKit) 我們可以輕鬆地將強大的 AI 聊天機器人整合到您的 React 應用程式中。完全可定制和深度集成。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6wf9zcyvtu9q293uej2n.gif) {% cta https://github.com/CopilotKit/CopilotKit %} Star CopilotKit ⭐️ {% endcta %} 現在回到文章。 --- ## **先決條件** 要開始學習本教程,您需要在電腦上安裝以下軟體: - 文字編輯器(例如 Visual Studio Code) - 節點.js - 套件管理器 ## **使用 NextJS 建立簡歷應用程式前端** **步驟 1:** 開啟命令提示字元並執行下列命令。 ``` npx create-next-app@latest ``` --- **第 2 步:** 系統將提示您選擇一些選項,如下所示。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvk0mgct4ypra7ao9u18.png) **步驟 3:** 使用您選擇的文字編輯器開啟新建立的 Nextjs 專案。然後,在命令列上執行以下命令,以使用 Tailwind CSS 安裝帶有 NextJS 的 Preline UI。依照[本指南](https://preline.co/docs/frameworks-nextjs.html)完成 Preline 設定。 ``` npm install preline ``` --- **步驟4:** 在resume/app/page.tsx檔案中,新增以下程式碼內容。 ``` export default function Home() { return ( <> <header className="flex flex-wrap sm:justify-start sm:flex-nowrap z-50 w-full bg-slate-900 bg-gradient-to-b from-violet-600/[.15] via-transparent text-sm py-3 sm:py-0 dark:bg-gray-800 dark:border-gray-700"> <nav className="relative max-w-7xl w-full mx-auto px-4 sm:flex sm:items-center sm:justify-between sm:px-6 lg:px-8 " aria-label="Global"> <div className="flex items-center justify-between"> <a className="flex-none text-xl text-gray-200 font-semibold dark:text-white py-8" href="#" aria-label="Brand"> ResumeBuilder </a> </div> </nav> </header> {/* <!-- Hero --> */} <div className="bg-slate-900 h-screen"> <div className="bg-gradient-to-b from-violet-600/[.15] via-transparent"> <div className="max-w-[85rem] mx-auto px-4 sm:px-6 lg:px-8 py-24 space-y-8"> {/* <!-- Title --> */} <div className="max-w-3xl text-center mx-auto pt-10"> <h1 className="block font-medium text-gray-200 text-4xl sm:text-5xl md:text-6xl lg:text-7xl"> Craft A Compelling Resume With AI Resume Builder </h1> </div> {/* <!-- End Title --> */} <div className="max-w-3xl text-center mx-auto"> <p className="text-lg text-gray-400"> ResumeBuilder helps you create a resume that effectively highlights your skills and experience. </p> </div> {/* <!-- Buttons --> */} <div className="text-center"> <a className="inline-flex justify-center items-center gap-x-3 text-center bg-gradient-to-tl from-blue-600 to-violet-600 shadow-lg shadow-transparent hover:shadow-blue-700/50 border border-transparent text-white text-sm font-medium rounded-full focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-offset-2 focus:ring-offset-white py-3 px-6 dark:focus:ring-offset-gray-800" href="#"> Get started <svg className="flex-shrink-0 w-4 h-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="m9 18 6-6-6-6" /> </svg> </a> </div> {/* <!-- End Buttons --> */} </div> </div> </div> {/* <!-- End Hero --> */} </> ); } ``` **步驟 5:** 在命令列上執行命令 *npm run dev*。導航至 http://localhost:3000/,您應該會看到新建立的 NextJS 專案。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56ymnb9iir7z14bx4ofm.png) --- ## 使用 GitHub GraphQL 從 GitHub 取得履歷資料 **步驟 1:** 使用下列命令安裝 Axios HTTP 用戶端。 ``` npm i axios ``` **步驟 2:** 在應用程式資料夾中,建立一個名為 API 的資料夾。然後,在 API 資料夾中建立一個名為 GitHub 的資料夾。在GitHub資料夾中建立一個名為route.ts的檔案並加入以下程式碼。 ``` import { NextResponse } from "next/server"; import axios from "axios"; // Environment variables for GitHub API token and user details const GITHUB_TOKEN = "Your GitHub personal access token"; const GITHUB_USERNAME = "Your GitHub account username"; // Axios instance for GitHub GraphQL API const githubApi = axios.create({ baseURL: "https://api.github.com/graphql", headers: { Authorization: `bearer ${GITHUB_TOKEN}`, "Content-Type": "application/json", }, }); // GraphQL query to fetch user and repository data const getUserAndReposQuery = ` query { user(login: "${GITHUB_USERNAME}") { name email company bio repositories(first: 3, orderBy: {field: CREATED_AT, direction: DESC}) { edges { node { name url description createdAt ... on Repository { primaryLanguage{ name } stargazers { totalCount } } } } } } } `; // API route to handle resume data fetching export async function GET(request: any) { try { // Fetch data from GitHub const response = await githubApi.post("", { query: getUserAndReposQuery }); const userData = response.data.data.user; // Format resume data const resumeData = { name: userData.name, email: userData.email, company: userData.company, bio: userData.bio, repositories: userData.repositories.edges.map((repo: any) => ({ name: repo.node.name, url: repo.node.url, created: repo.node.createdAt, description: repo.node.description, language: repo.node.primaryLanguage.name, stars: repo.node.stargazers.totalCount, })), }; // Return formatted resume data return NextResponse.json(resumeData); } catch (error) { console.error("Error fetching data from GitHub:", error); return NextResponse.json({ message: "Internal Server Error" }); } } ``` **步驟 3:** 在應用程式資料夾中,建立一個名為 Components 的資料夾。然後,在元件資料夾中建立一個名為 githubdata.tsx 的檔案並新增以下程式碼。 ``` "use client"; import React, { useEffect, useState } from "react"; import axios from "axios"; // Resume data interface interface ResumeData { name: string; email: string; company: string; bio: string; repositories: { name: string; url: string; created: string; description: string; language: string; stars: number; }[]; } export const useGithubData = () => { const [resumeData, setResumeData] = useState<ResumeData | null>(null); // Fetch resume data from API useEffect(() => { axios .get("/api/github") .then((response) => { setResumeData(response.data); }) }, []); return { resumeData, }; } ``` --- ## 建立求職信和履歷功能 **步驟 1:** 透過在命令列上執行以下命令來安裝 CopilotKit 前端軟體包。 ``` npm i @copilotkit/react-core @copilotkit/react-ui @copilotkit/react-textarea ``` **步驟2:** 在元件資料夾中建立一個名為resume.tsx 的檔案。然後在檔案頂端匯入 useMakeCopilotReadable、useMakeCopilotActionable 和 useGithubData 自訂掛鉤,如下所示。 ``` import React, { useState } from "react"; import { useGithubData } from "./githubdata"; import { useMakeCopilotReadable, useMakeCopilotActionable, } from "@copilotkit/react-core"; ``` **第 3 步:** 建立一個名為 CoverLetterAndResume 的元件。在元件內部,使用 useGithubData 掛鉤檢索從 GitHub 取得的資料。然後,宣告一個名為 createCoverLetterAndResume 的狀態變數和一個用於更新它的名為 setCreateCoverLetterAndResume 的函數。使用包含 letter 和 resume 兩個屬性的物件初始化 useState,如下所示。 ``` export const CoverLetterAndResume = () => { const {resumeData } = useGithubData(); const [createCoverLetterAndResume, setCreateCoverLetterAndResume] = useState({ letter: "", resume: "" }); } ``` **步驟 4:** 使用 useMakeCopilotReadable 掛鉤將從 GitHub 取得的資料新增為應用程式內聊天機器人的上下文。 ``` useMakeCopilotReadable(JSON.stringify(resumeData)); ``` **步驟 5:** 使用 useMakeCopilotActionable 掛鉤設定一個名為 createCoverLetterAndResume 的操作,其中包含描述和實作函數,該函數使用提供的求職信和簡歷更新 createCoverLetterAndResume 狀態,如下所示。 ``` useMakeCopilotActionable( { name: "createCoverLetterAndResume", description: "Create a cover letter and resume for a software developer job application.", argumentAnnotations: [ { name: "coverLetterMarkdown", type: "string", description: "Markdown text for a cover letter to introduce yourself and briefly summarize your professional background as a software developer.", required: true, }, { name: "resumeMarkdown", type: "string", description: "Markdown text for a resume that displays your professional background and relevant skills.", required: true, }, ], implementation: async (coverLetterMarkdown, resumeMarkdown) => { setCreateCoverLetterAndResume((prevState) => ({ ...prevState, letter: coverLetterMarkdown, resume: resumeMarkdown, })); }, }, [] ); ``` **步驟 6:** 在 CoverLetterAndResume 元件外部,建立一個名為 CoverLetterResume 的元件,用於在 Web 應用程式 UI 上顯示求職信和履歷。 ``` type CoverLetterResumeProps = { letter: string; resume: string; }; const CoverLetterResume = ({ letter, resume }: CoverLetterResumeProps) => { return ( <div className="px-4 sm:px-6 lg:px-8 bg-slate-50 py-4"> <div className="sm:flex sm:items-center"> <div className="sm:flex-auto"> <h1 className="text-3xl font-semibold leading-6 text-gray-900"> ResumeBuilder </h1> </div> </div> {/* Cover Letter Start */} <div className="mt-8 flow-root bg-slate-200"> <div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"> <div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"> <div> <h2 className="text-lg font-semibold leading-6 text-gray-900 mb-4 p-2"> Cover Letter </h2> <div className="min-w-full divide-y divide-gray-300 p-2"> {/* <Thead /> */} <div className="divide-y divide-gray-200 bg-white p-2"> <ReactMarkdown>{letter}</ReactMarkdown> </div> </div> </div> </div> </div> </div> {/* Cover Letter End */} {/* Cover Letter Preview Start */} <div className="mt-8 flow-root bg-slate-200"> <div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"> <div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"> <div> <h2 className="text-lg font-semibold leading-6 text-gray-900 mb-4 p-2"> Cover Letter Preview </h2> <div className="min-w-full divide-y divide-gray-300"> {/* <Thead /> */} <div className="divide-y divide-gray-200 bg-white"> <textarea className="p-2" id="coverLetter" value={letter} rows={20} cols={113} /> </div> </div> </div> </div> </div> </div> {/* Cover Letter Preview End */} {/* Resume Start */} <div className="mt-8 flow-root bg-slate-200"> <div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"> <div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"> <h2 className="text-lg font-semibold leading-6 text-gray-900 mb-4 p-2"> Resume </h2> <div className="min-w-full divide-y divide-gray-300"> {/* <Thead /> */} <div className="divide-y divide-gray-200 bg-white"> <ReactMarkdown>{resume}</ReactMarkdown> </div> </div> </div> </div> </div> {/* Resume End */} {/* Cover Letter Preview Start */} <div className="mt-8 flow-root bg-slate-200"> <div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"> <div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"> <div> <h2 className="text-lg font-semibold leading-6 text-gray-900 mb-4 p-2"> Cover Letter Preview </h2> <div className="min-w-full divide-y divide-gray-300"> {/* <Thead /> */} <div className="divide-y divide-gray-200 bg-white"> {/* {letter} */} {/* <ReactMarkdown>{letter}</ReactMarkdown> */} <textarea className="p-2" id="resume" value={resume} rows={20} cols={113} /> </div> </div> </div> </div> </div> </div> {/* Cover Letter Preview End */} </div> ); }; ``` **第7步:**然後返回CoverLetterAndResume元件內的CoverLetterResume元件,如下圖所示。 ``` return <CoverLetterResume {...createCoverLetterAndResume}/>; ``` **第8步:** 在應用程式資料夾中建立一個名為resumeandcoverletter的資料夾。然後,建立一個名為 page.tsx 的檔案並新增以下程式碼。 ``` "use client"; import { CopilotProvider } from "@copilotkit/react-core"; import { CopilotSidebarUIProvider } from "@copilotkit/react-ui"; import "@copilotkit/react-textarea/styles.css"; // also import this if you want to use the CopilotTextarea component import "@copilotkit/react-ui/styles.css"; // also import this if you want to use the chatbot component import React, { useEffect, useState } from "react"; import { CoverLetterAndResume } from "../components/resume"; function buildResume () { return ( <CopilotProvider chatApiEndpoint="./../api/copilotkit/chat"> <CopilotSidebarUIProvider> <CoverLetterAndResume /> </CopilotSidebarUIProvider> </CopilotProvider> ); } export default buildResume; ``` **步驟 9:** 使用下列指令安裝 openai 軟體套件。 ``` npm i openai ``` **步驟 10:** 在應用程式資料夾中,建立一個名為 API 的資料夾。然後,在 API 資料夾中建立一個名為 copilotkit 的資料夾。在 copilotkit 資料夾中,建立一個名為 chat 的資料夾。然後,在聊天資料夾中建立一個名為route.ts的檔案並新增以下程式碼。 ``` import OpenAI from "openai"; const openai = new OpenAI({ apiKey: "Your ChatGPT API key", }); export const runtime = "edge"; export async function POST(req: Request): Promise<Response> { try { const forwardedProps = await req.json(); const stream = openai.beta.chat.completions .stream({ model: "gpt-4-1106-preview", ...forwardedProps, stream: true, }) .toReadableStream(); return new Response(stream); } catch (error: any) { return new Response("", { status: 500, statusText: error.error.message }); } } ``` **步驟 11:** 在應用程式資料夾中的 page.tsx 檔案中,在「開始」按鈕中新增一個連結,用於導航到簡歷和求職信頁面,如下所示。 ``` <div className="text-center"> <Link className="inline-flex justify-center items-center gap-x-3 text-center bg-gradient-to-tl from-blue-600 to-violet-600 shadow-lg shadow-transparent hover:shadow-blue-700/50 border border-transparent text-white text-sm font-medium rounded-full focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-offset-2 focus:ring-offset-white py-3 px-6 dark:focus:ring-offset-gray-800" href="/resumeandcoverletter"> Get started <svg className="flex-shrink-0 w-4 h-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="m9 18 6-6-6-6" /> </svg> </Link> </div> ``` **第12步:**導航至http://localhost:3000/,點擊「開始」按鈕,您將被重新導向到與聊天機器人整合的履歷和求職信頁面,如下所示。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqfjykc75pherkjxut4p.png) **第 13 步:** 向右側的聊天機器人發出諸如“建立求職信和簡歷”之類的提示。聊天機器人將開始產生回應,完成後,它將在頁面左側顯示產生的求職信和履歷,如下所示。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t7muhhi4a85ol0ddyi1l.png) --- ## 建立更新求職信功能 **第 1 步:** 宣告一個名為 updateLetter 的變數,用於保存先前產生的求職信。 ``` const updateLetter = createCoverLetterAndResume.letter; ``` **步驟 2:** 使用 useMakeCopilotReadable 掛鉤新增 updateLetter 作為應用程式內聊天機器人的上下文。 ``` useMakeCopilotReadable("Cover Letter:" + JSON.stringify(updateLetter)); ``` **步驟 3:** 使用 useMakeCopilotActionable 掛鉤設定一個名為 updateCoverLetter 的操作,其中包含描述和實作函數,該函數使用提供的求職信更新來更新 createCoverLetterAndResume 狀態,如下所示。 ``` useMakeCopilotActionable( { name: "updateCoverLetter", description: "Update cover letter for a software developer job application.", argumentAnnotations: [ { name: "updateCoverLetterMarkdown", type: "string", description: "Update markdown text for a cover letter to introduce yourself and briefly summarize your professional background as a software developer.", required: true, }, { name: "resumeMarkdown", type: "string", description: "Markdown text for a resume that displays your professional background and relevant skills.", required: true, }, ], implementation: async (updatedCoverLetterMarkdown) => { setCreateCoverLetterAndResume((prevState) => ({ ...prevState, letter: updatedCoverLetterMarkdown, })); }, }, [] ); ``` ** 步驟 4:** 給聊天機器人一個提示,例如“更新求職信並加入我正在申請 CopilotKit 的技術寫作職位。”如下圖所示,您可以看到求職信已更新。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4dkm8zacgbmn19j9qtw6.png) --- ## 建立更新復原功能 **第 1 步:** 宣告一個名為 updateResume 的變數,用於保存先前產生的求職信。 ``` const updateResume = createCoverLetterAndResume.resume; ``` **步驟 2:** 使用 useMakeCopilotReadable 掛鉤新增 updateResume 作為應用程式內聊天機器人的上下文。 ``` useMakeCopilotReadable("Resume:" + JSON.stringify(updateResume)); ``` **步驟 3:** 使用 useMakeCopilotActionable 掛鉤設定一個名為 updateResume 的操作,其中包含描述和實作函數,該函數使用提供的求職信更新來更新 createCoverLetterAndResume 狀態,如下所示。 ``` useMakeCopilotActionable( { name: "updateResume", description: "Update resume for a software developer job application.", argumentAnnotations: [ { name: "updateResumeMarkdown", type: "string", description: "Update markdown text for a resume that displays your professional background and relevant skills.", required: true, }, ], implementation: async (updatedResumeMarkdown) => { setCreateCoverLetterAndResume((prevState) => ({ ...prevState, resume: updatedResumeMarkdown, })); }, }, [] ); ``` **第 4 步:** 向聊天機器人發出提示,例如「更新履歷並將我的姓名加入為 John Doe,將我的電子郵件加入為 [email protected]」。如下圖所示,可以看到履歷已更新。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2d9y6pmfynxwzff8be86.png) --- ## 建立下載求職信和履歷表 Pdfs 功能 **第 1 步:** 安裝 jsPDF,一個用 JavaScript 產生 PDF 的函式庫。 ``` npm i jspdf ``` **步驟 2:** 在 CoverLetterAndResume 元件內,使用 useMakeCopilotActionable 掛鉤設定一個名為“downloadPdfs”的操作,其中包含描述和實現函數,該函數使用 jsPDF 庫為求職信和簡歷建立 PDF,然後保存它們, 如下所示。 ``` function addTextToPDF(doc: any, text: any, x: any, y: any, maxWidth: any) { // Split the text into lines const lines = doc.splitTextToSize(text, maxWidth); // Add lines to the document doc.text(lines, x, y); } useMakeCopilotActionable( { name: "downloadPdfs", description: "Download pdfs of the cover letter and resume.", argumentAnnotations: [ { name: "coverLetterPdfA4", type: "string", description: "A Pdf that contains the cover letter converted from markdown text and fits A4 paper.", required: true, }, { name: "resumePdfA4Paper", type: "string", description: "A Pdf that contains the resume converted from markdown text and fits A4 paper.", required: true, }, ], implementation: async () => { const marginLeft = 10; const marginTop = 10; const maxWidth = 180; const coverLetterDoc = new jsPDF(); addTextToPDF( coverLetterDoc, createCoverLetterAndResume.letter, marginLeft, marginTop, maxWidth ); coverLetterDoc.save("coverLetter.pdf"); const resumeDoc = new jsPDF(); addTextToPDF( resumeDoc, createCoverLetterAndResume.resume, marginLeft, marginTop, maxWidth ); resumeDoc.save("resume.pdf"); }, }, [createCoverLetterAndResume] ); ``` **第 3 步:** 返回網頁應用程式中的聊天機器人,並提示「下載求職信和簡歷的 pdf 檔案」。 PDF 將開始下載,如果您開啟 coverLetter.pdf,您應該會看到產生的求職信,如下所示。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4p853urbqn43jh6454at.png) --- ## 結論 總而言之,您可以使用 CopilotKit 建立應用內 AI 聊天機器人,該機器人可以查看當前應用程式狀態並在應用程式內執行操作。 AI 聊天機器人可以與您的應用程式前端、後端和第三方服務對話。 對於完整的源程式碼: https://github.com/TheGreatBonnie/AIPoweredResumeBuilder --- 原文出處:https://dev.to/copilotkit/how-to-build-the-with-nextjs-openai-1mhb

React 和 NextJS 2024 最佳免費開源 SaaS 初學者

## 長篇大論;博士 SaaS 樣板啟動器隨處可見,但它們非常昂貴(約 200-800 美元)。 我想為 React 和 NextJS 找到最好的免費開源 SaaS Starters,這些 Starters 將在 2024 年積極維護。 在下面的文章中,我將介紹每個初學者的功能及其優缺點,所以如果您有興趣,請繼續閱讀。但我還在下面整理了這個漂亮的圖表,可以一目了然地對它們進行比較(順便說一句,文章底部有同一圖表的文本版本,帶有可點擊的連結)。 享受! ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wr6z6jqmypnl5hzrgyr1.png) ## 介紹 軟體即服務 (SaaS) 應用程式是獨立駭客和個人企業家賺錢的最佳方式之一。這就是為什麼 SaaS 樣板啟動器正在崛起!但其中一些售價高達 2,000 美元以上,平均價格約為 200 美元。 這就是為什麼我開始尋找是否有免費的開源 SaaS 啟動器以及它們的表現如何。在找到了很多但注意到大多數不再積極維護後,我將範圍縮小到這四個免費的開源 SaaS Starter:BoxyHQ 的 SaaS Starter、Open SaaS、SaaS Starter Kit 和 Next SaaS Stripe Starter。 ## BOXYHQ SaaS 入門套件 “**您的終極企業級 Next.js 樣板”** ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/51svaqq6lu6s3ldoy5i0.png) ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xd6cftpnl9robmmtw36b.png) - GitHub:https://github.com/boxyhq/saas-starter-kit - 影片演練:[https://www.youtube.com/watch?v=oF8QIwQIhyo](https://www.youtube.com/watch?v=oF8QIwQIhyo) BoxyHQ 是一家專注於安全的公司,專注於單一登入 (SSO) 和企業安全解決方案。因此,這個 SaaS 入門套件雖然免費且開源,但更專注於企業需求也就不足為奇了。 因此,如果您正在尋找一個外觀簡潔、具有安全 SAML SSO、使用者帳戶建立、團隊建立和管理以及 Webhooks 和事件整合功能的樣板,那麼這就是您的範本。 優點: - SAML 單一登入 - 全面的角色和權限 - 專注於企業SaaS應用程式開發 缺點: - 更適合企業級應用程式,這對於較小的專案來說可能有點過分 - 一些即將推出的功能(例如計費和訂閱)尚未實現 ## 開放 SaaS 「***免費*具有超能力的 SaaS 範本」** ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awz3renuql3k5awlvkms.png) ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ptji6f1viufkonb3bzw.png) - 網站與示範:https://OpenSaaS.sh - Github:https://github.com/wasp-lang/open-saas Open SaaS 專注於建立一個功能齊全的開源 SaaS 樣板,它擁有您期望從付費模板中獲得的一切,包括整合的人工智慧。範例、為您的網站流量和收入統計配置的分析儀表板以及完整的文件和支援。 它由 Wasp 團隊為您帶來,這是一個全端 React / NodeJS / Prisma 框架,可透過設定檔為您管理功能。例如,這意味著您只需幾行程式碼即可“推出您自己的身份驗證”,因為 Wasp 會為您管理樣板檔案。 優點: - 利用Wasp進行全端開發,減少開發時間 - 擁有完整的文件和多元化且支持性的社區 - 與 OpenAI API 集成,並包含人工智慧驅動的應用程式範例 - 開箱即用的端到端類型安全 缺點: - 可能缺少一些更廣泛的 SaaS 應用程式功能,例如測試 - 依賴 Wasp,一個鮮為人知但高效能的全端框架 ## SaaS 入門套件 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rdy7kkxnwvddia1qcxii.png) ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vqikv8rshdqq0yj1sas6.png) - 網站與示範:[https://www.saasstarterkit.com/](https://www.saasstarterkit.com/) - GitHub:[https://github.com/Saas-Starter-Kit](https://github.com/Saas-Starter-Kit) SaaS 入門套件是一個現代 SaaS 樣板,旨在建立具有免費/開源和專業/付費選項的全面 SaaS 解決方案。 這是一個簡單、乾淨的 UI,包含許多漂亮的 UI 元件,包括 Shadcn UI 分析儀表板元件。但不幸的是,您必須將它們與您自己的資料來源集成,因為大多數樣板都沒有管道。 目前它缺少很多配置,但看起來它在未來可能是一個有前途的模板 優點: - 提供免費版和專業版,使其能夠滿足多種需求 - 精心設計的 UI 元件,專門用於管理儀表板 缺點: - 具有增強功能的專業版不是免費的,這可能會讓一些用戶望而卻步 - 主要是內建Auth的UI元件集合,所以開發者還需要做很多工作 ## 下一個 SaaS Stripe 入門者 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ui7rg0yqafp9mf5nki0d.png) ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pd9uqi903h358oqu37w9.png) - 網站與示範:[https://next-saas-stripe-starter.vercel.app/](https://next-saas-stripe-starter.vercel.app/) - GitHub:https://github.com/mickasmt/next-saas-stripe-starter Next SaaS Stripe Starter 是一個簡單、乾淨的 SaaS 樣板,可利用現代、流行的工具。儘管它不像其他一些軟體那麼功能齊全,但由於使用了 Shadcn UI 和 Contentlayer,它看起來很漂亮,並且有一個時尚的部落格。一般來說,它處於良好的狀態,可以用作 SaaS 的基礎。 如果您正在尋找一個最小的 NextJS 模板並且可以進行大量自訂和功能開發,那麼這就是適合您的模板。 優點: - 看起來不錯並且利用了各種流行的工具。 - 它包括未來的更新,涵蓋成功訂閱和切換訂閱計劃的重新發送功能。 缺點: - 很少甚至沒有文件 - 不像其他模板那樣功能豐富。 ##六。結論與建議 雖然所有 SaaS Starter 都為您的專案提供了良好的基礎,但如果您正在開發企業級應用程式,請考慮 BOXYHQ。如果您正在尋找可立即投入生產的模板並希望快速交付,那麼 Open SaaS 將是理想的整體模板,而如果您正在建置簡單/微型 SaaS 並且想要現代設計美感,則 Next SaaS Stripe Starter 則適合您。 | | [BoxyHQ SaaS 入門套件](https://github.com/boxyhq/saas-starter-kit) | [開放SaaS](https://opensaas.sh) | [SaaS 入門套件](https://www.saasstarterkit.com/) | [下一個 SaaS Stripe 入門](https://next-saas-stripe-starter.vercel.app/) | | --- | --- | --- | --- | --- | | **適合** | 🏢 📈<br/>企業。對於需要 Teams 功能的應用程式 | 🧑‍💻🤖 <br/>獨立駭客和新創公司快速建立現代 (AI) 應用程式 | 🧑‍💻🔧 <br/>獨立駭客正在尋找優秀的 UI 元件集合 | 🧑‍💻🎨 <br/>獨立駭客正在尋找簡約、時尚的 SaaS 樣板。 | | **易於使用** | 6/10 <br/>複雜,以企業為中心。 | 8/10 <br/>精簡且快速。有據可查。 | 5/10 <br/>需要大量額外設定。 | 7/10 <br/>良好的基礎,但缺乏一些功能 | | **授權** |透過 Auth.js 驗證電子郵件、SAML SSO、Google、Github |電子郵件已驗證,Google,Github 透過 Wasp w/ Lucia |電子郵件、Google 透過 Auth.js |谷歌透過 Auth.js | | **管理儀表板** |限團隊管理 |內建和預先配置的網站和收入分析 |用於收入分析的 UI 元件(未配置) |無 | | **付款** |否(即將推出)|條紋| Stripe(+ Lemonsqueezy 付費版)|條紋| | **分析** |透過 Mixpanel 進行第 3 方(付費)|合理(免費、開源)或 Google | Vercel 分析(付費)| Vercel 分析(付費)| | **人工智慧.準備好了** |沒有 |內建 AI 支援 https://opensaas.sh (OpenAI API) |沒有 |沒有 | | **端對端類型安全性** |沒有 |是的 |沒有 |沒有 | | **電子郵件發送器** |郵件發送 | SendGrid、EmailGun 或 SMTP |重新發送 |重新發送 | | **內建部落格** |沒有 |是(透過 https://astro.build/)|否(付費版本,是)|是(透過 https://contentlayer.dev/)| | **造型** |順風|順風| Tailwind,Shadcn ui | Tailwind,Shadcn ui | | **使用者介面與設計** |基本 |款式好看|帶有漂亮 UI 元件的基本 |現代、時尚的造型| | **社區支持** | https://discord.gg/uyb7pYt4Pa | https://discord.gg/aCamt5wCpS | https://www.reddit.com/r/saas_kit/(發佈時沒有討論)|無 | | **文件** |基本 |非常詳細|基本 |可憐| | **演示應用程式** |無 | https://opensaas.sh | https://www.saasstarterkit.com/ | https://next-saas-stripe-starter.vercel.app/ | https://next-saas-stripe-starter.vercel.app/ --- 原文出處:https://dev.to/vincanger/best-free-open-source-saas-starters-for-react-nextjs-2024-4nbn

10 個可以在網路上免費學習任何內容的網站

網路蘊藏著許多寶藏,但很多人卻不知道。 這裡有 10 個資源豐富的網站,可以在網路上免費學習任何東西: --- ## 1. 編碼 **免費程式碼營** 您可以免費學習編碼、建立專案並獲得認證。 **您可以獲得以下認證:** - 響應式網頁設計 - Javascript演算法與資料結構 - 前端開發庫 - 資料視覺化 - 關係型資料庫 - 和更多 ``` Link: https://www.freecodecamp.org/ ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e1p5uuz40iub2l7u2z5f.png) --- ## 2. 行銷 **行銷範例** 簡短、溫馨、實用的行銷範例之家,可幫助您更好地進行行銷。 **取得範例:** - 客戶獲取 - 轉換 - 保留 - 品牌策略 - 推薦策略 - 和更多 ``` Link: https://marketingexamples.com/ ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5b7t6d2nmw2aiml2iibx.png) --- ## 3. 無程式碼 每天獲得 30 分鐘的簡短課程,指導您 100 天的無程式碼之旅,以提升您的無程式碼技能。 - 你得到什麼? - 指導課程 - 技巧和竅門 - 靈感鏡頭 - 驚喜獎勵 - 獎勵迷你挑戰 - 內建公共提示 ``` Link: https://www.100daysofnocode.com/start-the-challenge ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lq2r5ykrguazod5b7hrp.png) --- ## 4.人工智慧 **人工智慧 100 天** 每天獲得 30 分鐘的簡短課程,指導您的 AI 學習之旅。 **你了解什麼?** - 人工智慧在日常生活中的無限應用 - 你知道科技兄弟在談論什麼。 - 你每天都使用人工智慧來建立很酷的專案並消除無聊的工作。 - 你知道為什麼你對人工智慧感到焦慮,甚至更興奮。 ``` Link: https://www.100daysai.com/ ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r1q3fklkja9pkk93elnm.png) --- ## 5. 語言 **多鄰國** 以遊戲化的方式學習您想要學習的任何語言,以保持您的動力。 **你得到什麼?** - 透過快速、簡短的課程,您將獲得積分並解鎖新級別,同時獲得現實世界的溝通技巧。 - 結合研究支援的教學方法和令人愉快的內容來建立課程。 - 類似遊戲的功能、有趣的挑戰和提醒,輕鬆養成語言學習的習慣。 - 課程經過量身定制,可幫助您以適當的水平和節奏學習。 ``` Link: https://www.duolingo.com/ ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hu7kwsknz8i57dqe9pvy.png) --- ## 6. 資料結構與演算法 **CSVISTOOL** 了解資料結構和演算法如何以視覺化方式運作。 **你能學到什麼?** - 清單 - 堆疊、佇列和出隊 - 樹和跳過列表 - 哈希圖 - 排序和快速選擇 - 字串搜尋 - 圖形演算法 - 和更多 ``` Link: https://csvistool.com/ ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vp7z77dyhhm87i94xx8j.png) --- ## 7. 使用者體驗 **使用者體驗法則** 策劃設計人員在建立使用者介面時可以考慮的最佳實踐。 **你得到什麼?** - 啟發式 - 原則 - 格式塔 - 認知偏差 ``` Link: https://lawsofux.com/ ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qi0nqfadsvvky9ea66um.png) --- ## 8.Excel + Power BI **尚杜** 每週接收有關 Excel 和 Power BI 最佳提示的電子郵件 **你得到什麼?** - 強大的提示、資源和影片,幫助您在工作中取得進步。 - 資料分析、圖表、報告和自動化的真實範例 - 獎勵文件、PDF 指南和先睹為快 ``` Link: https://chandoo.org/wp/subscribe/ ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdo19vjlpbg5e7gz1tw0.png) --- ## 9. 時事通訊的成長 **反向成長** 了解如何從網路上最好的時事通訊成長故事中發展您的時事通訊。 **你得到什麼?** - 時事通訊企業如何賺錢 - 他們如何成長 - 他們如何透過時事通訊獲利 ``` Link: https://growthinreverse.com/ ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bebb1sbr2mt94udzv77p.png) --- ## 10.心智模型 **法南街** 了解讓您生活更美好的心理模式。 **如何取得?** - 核心心智模型 - 物理和化學的心理模型 - 生物學的心理模型 - 系統思維的心智模型 - 以及更多 ``` Link: https://fs.blog/mental-models/ ``` ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5tmyafxsxl9xbvbcgn0c.png) --- ## 與我聯繫 領英:https://www.linkedin.com/in/durgesh4993/ GitHub:https://github.com/Durgesh4993 LeetCode:https://leetcode.com/durgesh4993/ 簡介:https://linktr.ee/durgesh4993 --- 原文出處:https://dev.to/durgesh4993/10-websites-to-learn-anything-for-free-on-the-internet-4ahe

反應性的推導

當您第一次了解反應式系統時,範例總是看起來像這樣,這是有原因的: ``` let name = state("John"); effect(() => { console.log("Hi" + name); }) ``` > *我們將使用偽程式碼,而不是為了迎合特定庫或框架的語法。* 不需要太多就能理解,當我更新此狀態時,會發生一個呼叫我的副作用的事件。自己實現這種行為也不是太困難。但這還遠遠不是故事的全部。 無論您是想忘記 React、使用 Svelte 探索符文還是想嘗試 Angular;無論您是建立 Solid 應用程式、在 Vue 中建立視圖還是生活在 QwikCity 中,這個主題都相關。它超越了虛擬 DOM 或訊號。在您認為「useEffect」被建立為每個人存在的禍根之前,讓我們先來看看反應性最重要的部分:派生。 ----------------- ## 派生與同步 您可能已經在您選擇的 JS 框架/反應系統中看到了派生值。它可能看起來像“useMemo”,或者可能是“compulated”,或者可能就在分配了值的“$”後面。但所有這些的不變之處是你被告知它們是為了產生一種反應性關係。即使 B 或 C 發生變化,A 也是 B + C 總和: ``` let a = state(1); let b = state(1); const c = memo(() => a + b); effect(() => console.log(c)); ``` 他們可能告訴您派生值應該是純粹的——也就是說它不應該寫入任何其他狀態——但該規則也適用於它的內部。 您可以先將其應用為派生狀態的心理模型: ``` function memo(fn) { let internal = state(); effect(() => internal = fn()); return internal; } ``` 但這永遠無法正常工作。 大多數 UI 框架都關心提供互動性。即取得使用者操作的輸入,將其套用到某種狀態,然後更新 UI。我們看到它形式化為“ui = fn(state)”,但這是一個重複的循環。 就反應性而言,它看起來像: > 更新狀態-> > 執行純計算 -> > 執行副作用(例如更新 DOM) 原因是最終用戶與 UI 互動需要一致性。他們看到的(和看不到的)應該全部同步。您無法與過時的頁面部分進行交互,因為它設定了錯誤的期望。 UI 庫安排其副作用同步執行,以確保最終用戶可以信任體驗。 這意味著程式碼執行有明確的階段。庫需要確保在渲染之前解決所有相關計算。 這導致了以下之間的確切區別: ``` let name = state("John"); const upperName = memo(() => name.toUpperCase()); updateUI(name, upperName); ``` ``` let name = state("John"); let upperName = state(); effect(() => upperName = name.toUpperCase()); updateUI(name, upperName); ``` 第一個例子是推導,其中推導的狀態是它所依賴的狀態的函數。第二個範例是同步,其中狀態的變更會導致其他狀態更新。這是一個重要的區別。 在第二個範例中,根據您的反應模型,可能會發生不同的事情,而不是簡單地按預期立即顯示所有內容。根據效果安排時間與 UI 渲染時間的不同,當您更新「name」時,您可能會短暫看到更新後的「name」和「upperName」的先前值。在像 React 這樣的粗粒度渲染框架中,您的元件可能會執行兩次。因為更新效果中的狀態會再次開始循環。 ---------------- ## 無故障一致性 即使您始終可以在渲染之前進行同步,您仍然有可能使用不同中間狀態(可能是意外狀態)的值多次執行表達式,直到圖形穩定下來。推導可以提供可預測性。 現在,許多反應式系統保證對於任何狀態更新,每個節點最多只執行一次,並且執行時不會出現故障。透過無故障,開發人員向庫提供的程式碼永遠不會觀察到中間或過時狀態。 考慮: ``` let a = state(1); const b = memo(() => a + 1); const c = memo(() => a + 1); const d = memo(() => c + 1); const e = memo(() => b + d); effect(() => console.log(e)); ``` 或作為圖表 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kg9w4yehyeqhgry1wkvk.png) 不同的系統運作方式不同,但在所有情況下,我們期望初始執行產生值為 5 的「e」。 同樣清楚的是,某些狀態依賴其他狀態。當我們更新“a = 2”時,無論機制如何,如果我們只想執行每個節點一次,“c”必須在“d”之前解析,“d”必須在“e”之前解析。 ---------------- ## 推與拉 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1004yrongpx1usdsxe0x.jpg) 那我們要如何處理這個問題呢?它通常從以下兩個想法之一開始。調度(拉)和事件(推)。讓我們使用上一節中的範例來分別了解。 ### 拉動(調度) 這個想法是從副作用(目標)開始,然後詢問遇到的值。 React 通常被認為具有基於「拉」的反應性。在此系統中,當狀態更新時,它會安排檢查以查看是否需要執行任何工作。 但它檢查什麼?天真地,也許一切都改變了,因為它不知道發生了什麼變化。然而,許多 UI 庫都處理元件。如果狀態由元件擁有,那麼這可以作為起點。當元件狀態更新時,安排此元件運作。 基於拉動的系統是粗粒度的。也就是說,他們依賴自上而下地重播所有內容,因為他們不知道發生了什麼變化。如果我們想像一個更細粒度的「拉動」系統,它就無法知道任何變化,直到它追溯到變化的源頭,而變化的源頭可能存在於其依賴項中,也可能不存在。當最終需要向下執行時,額外的遍歷只是額外的工作。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kg9w4yehyeqhgry1wkvk.png) 在我們的範例中,圖片中我們首先執行要求“e”的效果。如果不在之前執行“b”或“d”,我們不知道“e”是否已更改。明確依賴項(如 React 的依賴項陣列)可以在不執行節點的情況下給出向上的路徑。所以我們可以回溯`e`、`b`、`a`,然後執行`b`,然後回溯`d`、`c`、`a`,然後執行`c`、`d`、 ` e` 在最終執行我們的效果之前。但考慮到我們無論如何都在執行整個範圍(元件),即使其中一部分沒有改變,這都是不必要的。 記憶(通常以推導的形式)允許提前退出,有助於優化這種情況,但這種方法雖然一致,但從根本上來說效率很低。 ### 推送(事件) 這個想法是更新從已更改的來源狀態向外傳播。 RxJS 是基於「推送」的反應性的常見範例。它將讓每個節點訂閱其依賴項中的更改事件,然後在收到通知時執行並在其值發生更改時通知其觀察者。 考慮深度優先傳播,因為它反映了最初建立時執行的方式。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kg9w4yehyeqhgry1wkvk.png) `a` 更新,通知 `b` 和 `c`。然後“b”執行並通知“e”。然後“e”執行並看到“b”的更新值,但隨後它遇到了“d”,它尚未執行並且具有舊值... 廣度優先也有類似的問題,因為「d」和「e」與來源「a」的距離相同,再次導致過時的值。它會嘗試執行“b”、“c”,然後執行“e”、“d”,結果發現“d”在“e”之前沒有被計算。 基於「推送」的系統很難確保我們有效地尋求保證。進行排序插入可以工作。但即使最後沒有任何效果器在監聽,它仍然可以工作。它確切地知道傳播時發生了什麼變化,但不知道該變化會產生什麼影響。 ### 推拉 第三種選擇是結合這兩種技術。訊號是事實上的「推拉」反應系統。訂閱和通知的製作方式類似於“推”,但工作的安排類似於基於“拉”的系統。透過這種方式,只安排會改變的事情,並且保持一致。 在我們更新“a”的範例中,“b”和“c”被通知它們可能會發生更改,進而通知“e”和“d”。最後,監聽「e」的效果被排隊。然後,我們的效果首先執行,在觸及值時拉低值,類似於我們上面描述的假設的細粒度「拉」系統。只不過這次只有可能受影響的效果才會排隊。 它知道發生了什麼變化以及這些變化的影響,確保我們只做所需的工作。 如果您對推拉演算法如何在各種訊號庫中工作的更多細節感興趣,請查看: {% 連結 https://dev.to/modderme123/super-charging-fine-grained-reactive-performance-47ph %} ---------------- ## 可以推導的應該推導 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kxmqpzohmk1az3k92anp.png) 我不是 100% 確定這句話最初來自哪裡,但我第一次聽到這句話來自 MobX 的建立者 Michel Westrate。這些都是我們賴以生存的話語。 不言而喻,我們所期望的函式庫和框架的一致性僅靠狀態和效果是不可能實現的。當效果寫入狀態時,您不再可以遍歷依賴關係圖來了解需要計算的內容。依賴性消失了。這不僅僅是低效。這是很容易出錯的。 這是一個很深奧的話題。就這麼多,我只觸及了表面。 「推」與「拉」還有其他含義,即使在查看屬於同一類別的系統時也有很多細節。下一次,我們將研究惰性派生與急切派生以及處理非同步的潛力。 -------------- 特別感謝 Atila Fassina、Fabio Spampinato 和 Daniel Afonso 的審閱。 --- 原文出處:https://dev.to/this-is-learning/derivations-in-reactivity-4fo1

📈 RAG 檢索增強生成:5 個適合初學者的開源程式庫 🚀

#RAG簡介 作為開發人員,您今天可以學到的最有價值的技能之一是學習如何使用大型語言模型 (LLM) 建立檢索增強生成 (RAG) 應用程式。 ## 為什麼? 因為世界上有超過 64 ZB 的資料,這甚至不包括書籍或實體文件等實體資料。 (供您參考,1澤字節是一兆千兆位元組。) 不僅如此,全球90%的資料都是在過去兩年建立的,而且資料量每兩年就會翻倍。基本上,公司都在海量的資料中游泳,而且這些資料每天都在變得越來越大。 公司將如何存取和使用所有這些資料? 現在每個人都聽說過使用檢索增強生成(RAG)來透過人工智慧尋找資訊。能夠存取和使用不斷增長的資料量是每個公司都需要的關鍵技能。 即使您知道 RAG 基本上是描述將文件或知識連結到 LLM 的工作流程的簡寫方式,許多開發人員自己(還)還沒有嘗試或試驗過這一點。 網路上充滿了圖書館列表,但如何開始呢? 以下是幫助您開始使用 RAG 的最佳庫的簡短清單。 --- # 1. [LLMWare](https://github.com/llmware-ai/llmware) 在LLMWare中,您可以上傳文件,並透過幾行程式碼開始檢索資訊。它處理 RAG 所需的整個過程:文件攝取、解析、分塊、索引、嵌入、儲存到向量資料庫以及連結到 LLM 以檢索答案。 LLMWare 被設計為整合和端到端,因此所有這些步驟都可以開箱即用。它組裝了所有部件,因此您無需這樣做。 LLMWare 使其非常簡單且易於上手: - 只需幾行程式碼即可透過端到端範例實現 RAG 工作流程 - 建立庫並無縫載入文件 - 輕鬆產生嵌入 - 輕鬆進行語意搜尋 - 利用任何 Hugging Face 模型或 GPT-4 等封閉源模型來回答資料中的問題 - 範例包括無需 GPU 的 RAG 模型 https://github.com/llmware-ai/llmware ![LLMWARE](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dy22hfga9az7uol150ar.png) --- # 2. [MongoDB](https://github.com/mongodb/mongo) MongoDB 是一種廣泛使用的開源 NoSQL 資料庫程式。它屬於以文件為導向的資料庫類別,這意味著它以類似於 JSON 文件的格式儲存和組織資料。 MongoDB 的設計具有靈活性和可擴展性,使其適合各種應用程式和行業。 資料庫(如 MongoDB)是 RAG 中非常重要的一步,因為它們在嵌入之前儲存從文件或知識庫中提取的訊息,包括重要的元資料。 https://github.com/mongodb/mongo ![MongodbVector](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ii6vl3tu41gfo6v3zt5g.png) --- # 3. [Milvus 向量資料庫](https://github.com/milvus-io/milvus) Milvus 是一個開源向量資料庫,旨在為嵌入相似性搜尋和人工智慧應用程式提供支援。 Milvus 讓非結構化資料搜尋更容易存取,無論部署環境如何,都可以提供一致的使用者體驗。 Milvus DB,或類似的向量 DB,是 RAG 中至關重要的一步。它是存儲向量嵌入以進行相似性搜尋的地方。該資料庫允許人們用自然語言提出問題並檢索相關結果。如果沒有良好的嵌入和向量資料庫,LLM 模型將無法接收正確的文字區塊來讀取。 https://github.com/milvus-io/milvus ![Milvus DB](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l5t6jyfaidyfvxwd8nb7.png) --- # 4. [擁抱臉](https://github.com/huggingface) 如果你還沒去過 Hugging Face,你真的應該去看看。這是所有開源模型的去處,並且可以單槍匹馬地將世界從人工智慧壟斷中拯救出來。就像 Github 用於開源專案一樣,Hugging Face 用於開源模型。有超過 450,000 個模型,所有模型都免費供任何想要使用它們的人使用。 Hugging Face 的 Transformers 庫是首選庫 提供數千個預訓練模型來執行不同模式(例如文字、視覺和音訊)的任務。 這些模型可應用於: - 文本,用於文本分類、資訊提取、問答、摘要、翻譯和文本生成等任務,支援 100 多種語言。 - 影像,用於影像分類、物件偵測和分割等任務。 - 音頻,用於語音辨識和音頻分類等任務。 Transformer 模型還可以組合執行多種模式的任務,例如表格問答、光學字元辨識、從掃描文件中提取資訊、視訊分類和視覺問答。 https://github.com/huggingface ![擁抱臉](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pn47bs3bd97eu4gulkzb.png) --- #5. [Llama.cpp](https://github.com/ggerganov/llama.cpp) 沒有GPU?沒問題! Llama.cpp 來救援! llama.cpp 的主要目標是在 MacBook 上使用 4 位元整數化來執行 LLaMA 模型。 * 無依賴的純 C/C++ 實現 * Apple Silicon 一等公民 - 透過 ARM NEON、Accelerate 和 Metal 框架進行最佳化 * 對 x86 架構的 AVX、AVX2 和 AVX512 支持 * 混合F16/F32精度 * 支援2位、3位、4位、5位、6位和8位整數化 * CUDA、Metal 和 OpenCL GPU 後端支持 一旦量化,更大的模型就可以在 CPU 上執行,而效能損失很小。尋找 GGUF 版本的模型來嘗試使用 LLMWare 或其他 RAG 工作流程。 https://github.com/ggerganov/llama.cpp ![Llama.cpp](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vev1gzen7oolvnug4vfl.png) --- 這是幫助您開始使用 RAG 的非常基本的概述。如果您想要一個讓所有這些庫無縫協作的一站式整合解決方案,請造訪 LLMWare 的 GitHub 庫,找到 50 多個優秀範例來幫助您入門。 [在不和諧中找到我們](https://discord.gg/fCztJQeV7J) - 我們很樂意聽到您的來信! --- 原文出處:https://dev.to/llmware/top-5-beginner-friendly-open-source-libraries-for-rag-1mhb

SQL 查詢優化 23 倍!!!

所以我現在已經進入 Web 開發大約 3 年了,專業也有一年多了,這是我處理一個與資料庫查詢最佳化相關的問題的時候,我不是 SQL 專家,我可以得到這份工作完成。沒有花哨的查詢、觸發器、預存程序等。無論如何,我不得不穀歌搜尋最後一個。 長話短說..我們的 ORM (TypeORM) 把我們搞砸了.. ## 免責聲明: 這並不是要誹謗 TypeORM 或任何 ORM。它們是為其建置目的而設計的特殊工具。我在最後附加了一些參考連結,這些連結是人們面臨類似問題的公開討論。無論如何,讓我們繼續這篇文章。 ## 問題! 我們的提交表有超過 70 萬筆記錄,表現非常糟糕。從表中取得資料的最長時間超過 6 秒。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l5dqlrbtn491upu8lwxs.png) 查詢相當簡單。我們所擁有的只是 4 個連接、幾個 where 子句(大約 4 個)、排序(在created_at time 字段上的 DESC)、限制和跳過。 ## 根本原因分析.. 導致我們的提交表大幅放緩的幾個因素如下:- - **索引** - 對用於連接表的欄位進行不正確的索引或未進行索引。 - **不必要的連接** - 我們的查詢中有一些不必要的連接,可以將其刪除以獲得更多效能。 - **空字串錯誤** - 我們程式碼中的一個錯誤,如果沒有為這些列提供使用者輸入,我們將與作為查詢的 where 條件一部分的所有列的空字串 (“”) 進行比較。 - **ORM** - ORM 正在執行一個超級愚蠢的查詢來獲取資料。 這些是我在檢查程式碼和資料庫模式以及分析正在執行以獲取所需資料的查詢時發現的精確點。 ## 對提到的每個問題進行分析和測試。 ###<u>原因 1:索引</u> 在進行了一些谷歌搜尋並閱讀了人們的類似問題後,我發現我們的問題並不是那麼大。人們正在為數百萬行而苦苦掙扎,而我們的只是其中的一小部分,所以一定是我們做錯了什麼。 早期解決這些問題的社區提出了許多建議。我發現進行適當的索引會有很大幫助。 因此,為了進行測試,我從 beta 資料庫中獲取了提交內容,該資料庫擁有大約超過 **100k 記錄**。 在沒有任何最佳化的情況下,執行整個過程平均需要 **2.3 秒**。 (當然,這個時間不僅包括在資料庫上執行查詢的時間,還包括透過網路傳播資料的時間) ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2mgewrjv4khpzrst86nb.png) 在向列加入索引後,我確實發現它縮短了幾毫秒的時間,但這還不夠。它仍然在 **2 秒** 左右,而且往往不止於此。 所以有點令人失望!無論如何,繼續下一個目標。 ### <u>原因 2:空字串錯誤</u> 因此,我們的時間從 **2.3** 秒縮短到了大約 2 秒,這對於索引來說並不算多。但後來我在我們的程式碼中發現了一個小錯誤,假設有四個輸入欄位供使用者根據四個不同的列鍵入和過濾結果。如果使用者沒有在任何輸入上鍵入任何內容(主要是在頁面首次載入時),且 API 呼叫會直接取得最新資料,而不進行任何過濾,僅進行連接和排序。 因此,在那一刻,我們為資料庫中的所有列傳遞了“”字串,這似乎無害,但實際上發生的情況是,資料庫正在對所有四列進行查找,您猜對了“”字串。所以進行了大量的查找,實際上什麼都沒有。 因此,當我將其更改為空(如empty/null)時(相當於從查詢中刪除where子句),查詢時間從**2.3秒變為1.3秒**。 如果您想知道使用使用者提供的實際輸入進行過濾需要多長時間。大約**500ms**(這是可以接受的)。 結論 - 即使您的資料庫使用所有可搜尋列進行索引,“”字串也不能很好地發揮作用。 好的,我們正朝著正確的方向前進。我們整整縮短了 1 秒,但我們仍然必須將其控制在 **200/150ms** 以下,所以還有很長的路要走。 ### <u>原因 3:不必要的連接</u> 在查詢提交時,我們正在與不需要的比賽和課程表進行連接。因此,當所有內容都加入到程式碼中時,我們只是刪除了它,但這表明審閱者並沒有給予太多關注(我是其中之一)。 ### <u>原因 4:ORM</u> 這是造成最多的問題.. 好.. 問題!!. 所以有一種叫做 **主動記錄模式** 的東西,TypeORM 為我們提供了使用類似 JSON 的物件產生 SQL 查詢的東西,一個例子就是。 ``` model.find({ select: { userName : true, firstName : true }, where: { userName : “SomeUsername” }, relations: { user : true, contest: true, problem: true }, order: { created_at : “ASC/DESC” , skip: 0, take: 10, }) ``` 因此,這使得開發變得快速、簡單,對於不擅長編寫原始 SQL 查詢的開發人員來說,感覺非常直觀,因為這是最抽象的版本,您實際上是在建立 JSON 物件來產生 SQL 查詢。 這種方法看起來不錯,而且大多數時候都有效,但在我們的例子中,它做了一些非常愚蠢的事情,我不會輸入它在做什麼,這樣你就可以自己看到查詢。 簡而言之,它正在執行兩個查詢,首先對於這種情況根本不需要,它可以通過我稍後編寫並測試的一個簡單的單個查詢輕鬆完成。 它不僅執行兩個單獨的查詢(原因尚不清楚,因為這是一個已知問題,有時在使用typeorm 的活動記錄模式時發生),它還將四個表連接兩次,每個查詢一次,然後還排序兩次各一次。 (這實際上沒有任何意義) 這也是表演受到最大打擊的地方。自己看看下面的查詢。 ``` SELECT DISTINCT `distinctAlias`.`Submission_id` AS `ids_Submission_id`, `distinctAlias`.`Submission_created_at` FROM (SELECT `Submission`.`id` AS `Submission_id`, ... more selects FROM `submission` `Submission` LEFT JOIN `problem` `SubmissionSubmission_problem` ON `SubmissionSubmission_problem`.`id`=`Submission`.`problemId`  LEFT JOIN `user` `SubmissionSubmission_user` ON `Submission_Submission_user`.`id`=`Submission`.`userId`) `distinctAlias` ORDER BY `distinctAlias`.`Submission_created_at` DESC, `Submission_id` ASC LIMIT 10 ``` ``` SELECT `Submission`.`id` AS `Submission_id`, `Submission`.`language` AS `Submission_language`, `Submission`.`verdictCode` AS `Submission_verdictCode`, `Submission`.`tokens` ... shit ton of selects FROM `submission` `Submission` LEFT JOIN `problem` `SubmissionSubmission_problem` ON `SubmissionSubmission_problem`.`id`=`Submission`.`problemId`  LEFT JOIN `user` `SubmissionSubmission_user` ON `Submission_Submission_user`.`id`=`Submission`.`userId` WHERE `Submission`.`id` IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ORDER BY `Submission`.`created_at` DESC ``` 所以這兩個查詢是問題的主要原因,也是主要原因之一。 因此,我編寫了一個簡單的原始 SQL 查詢來執行與它嘗試使用 2 個單獨的查詢執行的完全相同的操作,查詢如下:- ``` SELECT   Submission.id,   Submission.language,   Submission.verdictCode, ... FROM   submission AS Submission   LEFT JOIN problem ...   LEFT JOIN user ... ORDER BY   Submission.created_at DESC LIMIT 10 ``` 當我們執行這個查詢時,它的執行時間僅為 **100ms!!!** 因此,我們現在從 **1.3** 秒移至 **100ms**,總體從 **2.3** 秒移至 **100ms** 效能提升超過 **23 倍。** 之後我就去睡覺了。仍然需要做更多的測試,並嘗試找出邊緣情況(如果有),並提出為此編寫查詢的最佳方法。目前,我正在考慮使用 TypeORM 提供的儲存庫模式或查詢建構器模式。 第二天: 又來了.. ### <u>全文索引</u> **全文索引**可以提高從這些索引列中搜尋單字和短語的效率,我們也可以嘗試一下。 (這是我的同事 Jay 提出的一個非常好的觀點,它進一步提高了表現)。 ###<u>發現了一些更重要的點。</u> 在 MySQL 中最佳化具有唯一索引的資料列上的「LIKE」查詢時,可以採用一些策略來提高效能。以下是一些建議: 1. **索引優化:** - **使用全文索引:** 如果您的「LIKE」查詢涉及在列中搜尋單字或片語,請考慮使用全文索引而不是常規唯一索引。全文索引是專門為基於文字的搜尋而設計的,可以提供更快、更準確的結果。 - **使用排序規則:** 確保列的排序規則不區分大小寫和重音。這可以透過使用「utf8_general_ci」或「utf8mb4_general_ci」等排序規則來實現。它允許更有效地利用索引,因為搜尋變得不區分大小寫和重音。 2. **查詢最佳化:** - **前綴搜尋:**如果您的`LIKE`查詢在末尾使用通配符(例如,`column LIKE 'prefix%'`),索引仍然可以有效地使用。但是,如果通配符位於開頭(例如“column LIKE '%suffix'”),則不會使用索引。在這種情況下,請考慮使用替代技術,例如全文搜尋或儲存列的反向值以實現高效的後綴搜尋。 - **最小化通配符:** 模式開頭的通配符(`'%suffix'`)會使查詢速度明顯變慢。如果可能,請嘗試建立查詢,使通配符僅出現在模式的末尾(「前綴%」)。 - **參數綁定:** 如果您從應用程式內執行「LIKE」查詢,請使用參數綁定或準備好的語句,而不是直接連接查詢字串。這有助於防止SQL注入並允許資料庫更有效地快取執行計劃。 3. **快取和查詢結果:** - **快取查詢結果:** 如果`LIKE`查詢結果相對靜態或不需要即時,可以考慮實作像memcached或Redis這樣的快取機制。快取可以透過直接從記憶體提供結果來顯著縮短反應時間。 - **物化視圖:** 如果經常執行「LIKE」查詢且資料列的資料相對靜態,請考慮建立物化視圖來預先計算並儲存「LIKE」查詢的結果。如果查詢物化視圖所帶來的效能提升超過了額外的儲存和維護需求,則此方法可能會很有用。 值得注意的是,這些優化策略的有效性可能會根據您的特定用例而有所不同。 ### 經過所有測試後建議的改進點。 1. 修正將空字串傳遞到 where/過濾條件的問題。 2. 在效能至關重要的讀取操作中,轉而使用查詢建構器而不是活動記錄模式。 3. 在用於搜尋和過濾的欄位中新增索引。另外,在不唯一且用於搜尋的列上新增全文索引。 4. 刪除/避免不必要的連線。如果可能的話,重組架構以在必要時複製資料。 5. 使用 LIKE 運算子搜尋時,使用「prefix%」模式,而不是我們使用的預設模式「%suff+pref%」。使用前綴模式有助於資料庫使用索引並提供更好的結果。 儘管如此,我們成功地將查詢時間從 **7 秒** 降低到 **<=150 毫秒**,這樣做後感覺很好,因為這是我第一次涉足性能和優化並尋找從我們已有的資源中榨取更多資源的方法。 特別感謝[Mitesh Sir](https://www.linkedin.com/in/miteshskj/) 在這次調查期間指出了潛在的原因並引導我走向正確的方向,並一遍又一遍地重新啟動測試伺服器😂因為由於記憶體限制,在多次執行測試後,資料庫會變得非常慢。 如果您想更多地談論與這一切相關的內容,請在 X 上關注我,https://twitter.com/RishiNavneet ### 參考 1. https://github.com/typeorm/typeorm/issues/3857#issuecomment-714758799 2. https://github.com/typeorm/typeorm/issues/3857 3. https://stackoverflow.com/questions/714950/mysql-performance-optimization-order-by-datetime-field 4. https://stackoverflow.com/questions/22411979/mysql-select-millions-of-rows 5. https://dba.stackexchange.com/questions/20335/can-mysql-reasonously-perform-queries-on-billions-of-rows 6. https://stackoverflow.com/questions/38346613/mysql-and-a-table-with-100-millions-of-rows 7. https://github.com/typeorm/typeorm/issues/3191 PS - 這些改進很久以前就完成了,我只是懶得發布它😬。 --- 原文出處:https://dev.to/navneet7716/optimizing-sql-queries-h9j