🔍 搜尋結果:1

🔍 搜尋結果:1

BEAM VM 的好、壞、醜陋

`BEAM`是一個最近隨著[gleam](https://gleam.run)和[riot](https://riot.ml/)等新技術的出現而被廣泛討論的虛擬機,使用它作為編譯目標,甚至重新建立它的一些功能。最酷的部分是,這個虛擬機器非常古老,是由[愛立信](https://www.erlang.org/about)於**1986 年**為[Erlang](https://www.erlang.org/)語言建立的,這些技術是電信環境中應用程式的主要主角,每秒以可靠和高效能的方式處理無數的請求。 幾十年後, [José Valim](https://github.com/josevalim)首次考慮將此 VM 用於 Web,他於 2011 年年中建立了[Elixir](https://elixir-lang.org/)語言,以現代語言充分利用`BEAM`的強大功能,並專注於開發體驗。這種語言也促進了虛擬機器的普及,如果不是它,您可能不會閱讀本文,不是嗎? 👀 但畢竟…為什麼要建立這個虛擬機器呢?它的優勢、力量是什麼,最重要的是:它的秘密是什麼?在這篇文章中我們將簡單探討這個VM的細節,來吧! 目錄 -- - [什麼是梁](#o-que-é-a-beam) - [堆疊機與暫存器機](#stack-machine-vs-register-machine) - [預設並發是什麼意思](#o-que-significa-ser-simultâneo-por-padrão) - [使節點透過網路互動的一個有趣的案例](#um-caso-interessante-para-fazer-nodes-interagirem-pela-rede) - [結論](#conclusão) 什麼是梁 ---- `BEAM`是構成[OTP](https://en.wikipedia.org/wiki/Open_Telecom_Platform)系統的部分之一,其作用類似於 Java 的 JVM,其主要目標是效能、並發性、容錯性以及使用輕量級執行緒來盡可能並發地執行運算。 與此虛擬機器的互動可以透過兩種主要方式完成: - 1. 編譯`*.beam` - 2. 直接將X語言編譯為`*.beam`字節碼(與elixir的情況相同) 儘管經常被稱為最後一層執行,但`BEAM`只是構成 Erlang/Elixir/Gleam 應用程式整個執行過程的元件之一。 ![Erlang 的 ERTS 堆疊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ko71tgwqnxzx2zo14jls.png) 正如您所看到的,BEAM 在 Erlang 執行時 (ERTS) 內執行,因此我們所有的應用程式程式碼都作為虛擬機器中的獨立`node*`執行。 > node\*可以簡單理解為作業系統執行緒。每個節點可以同時執行數千個進程,這些進程是模仿本機作業系統行為的輕量級線程,具有以下功能:透過訊號相互通訊、執行計算和啟動其他進程。 堆疊機與暫存器機 -------- 好吧,我可以簡單地告訴您,BEAM 是一台具有堆疊機功能的錄音機,但這不是很有用,對吧?那麼讓我們回到開頭並理解每件事是什麼: ### 什麼是堆疊機 我們可以說堆疊機是建立解釋器最常見的方式,正是因為它有一個簡單的心理模型來理解,並且因為最終生成的程式碼非常容易被人類理解,可以將此模型視為一個 FIFO 隊列,其中我們有兩個主要行動: - 1. `push` :將一個值插入佇列 - 2. `pop` :從佇列中刪除一個值 但僅此而已?**是的!**有了這個概念,我們可以將範例表達式`2 + 2`翻譯為堆疊機👇: ``` push 2 push 2 add ``` 我知道,那裡有一個詞`add` ,對嗎?但它與堆疊概念完全一致,不用擔心,在這種情況下`add`表示對函數的呼叫,它所做的就是從堆疊中刪除參數(使用`pop` ),然後將操作結果加回排隊(使用`push` ),下面我們可以更詳細地看到這個過程: ``` push 2 #=> Adiciona 2 a stack push 2 #=> Adiciona 2 a stack add #=> detalhe da execução abaixo pop #=> Remove argumento da stack pop #=> Remove argumento da stack push 4 #=> Adiciona o resultado 4 a stack ``` ### 什麼是收銀機 與堆疊機不同,暫存器使用暫存器來儲存參數值及其結果,並且這些值都不會被刪除,因為它能夠使用多個暫存器來儲存不同的內容(BEAM 使用`X0`暫存器來儲存計算結果)。 透過具有使用更多暫存器的能力,暫存器機具有更多的操作運算符,例如`move` 、 `swap`以及以特定方式存取暫存器值的方法,如下所示: ``` {function, add, 2, 2}. {label,1}. {line,[{location,"add.erl",4}]}. {func_info,{atom,add},{atom,add},2}. {label,2}. {allocate,1,2}. #=> Prepara um lugar na memoria para eventualmente armazenar os valores {move,{x,1},{y,0}}. #=> Copia o argumento da função (salvo automaticamente no registrador x) para um registrador temporario y {call,1,{f,4}}. {swap,{y,0},{x,0}}. #=> Inverte os valores de cada registrador {call,1,{f,4}}. {gc_bif,'+',{f,0},1,[{y,0},{x,0}],{x,0}}. #=> Soma os numeros nos registradores x e y, sobrescrevendo então o registrador x com o resultado {deallocate,1}. return. ``` > PS:本文的目的並不是要確切地教您寄存器(更不用說彙編)如何運作(因為即使我對此也不太了解😅),而是要概述該模型的行為方式。 ### 那麼 BEAM 到底是什麼呢? 現在我相信我們可以理解開頭的句子了吧? BEAM 是一個暫存器機,在特定暫存器(在本例中為`Y` )中具有堆疊,因為這使得傳輸參數值變得更簡單。 預設並發是什麼意思 --------- 如果您對 Elixir 或生態系統中的任何其他語言有足夠的了解,您就會聽說 BEAM 預設是同步的,但這意味著什麼?簡而言之,這意味著BEAM語言提供了處理並發運算的原生且智慧的方法。 正如我們之前所看到的,我們的整個應用程式執行在其中一個 VM 節點上,並且該節點可以有數千個進程(也稱為輕量級進程)同時執行計算。這些進程是我們在應用程式期間保證並發性的主要方式,我們本身俱有諸如`spawn`類的函數來啟動新進程,並且使用這個主要函數,我們擁有完整的抽象,例如`GenServer`和`Task` ,它們允許在特定上下文中使用進程。 並發應用程式的存在不僅僅是透過啟動新進程,對嗎? BEAM 語言也提供原生建構子來處理透過郵箱的進程間訊息交換。這些郵箱是像`switch case`一樣工作的區塊,每個分支都可以使用如下所示的模式進行匹配: **靈丹妙藥** ``` iex(1)> defmodule Listener do ...(1)> def call do ...(1)> receive do ...(1)> {:hello, msg} -> IO.puts("Received inside the mail: #{msg}") ...(1)> end ...(1)> end ...(1)> end {:module, Listener, <<70, 79, 82, 49, 0, 0, 6, 116, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 240, 0, 0, 0, 25, 15, 69, 108, 105, 120, 105, 114, 46, 76, 105, 115, 116, 101, 110, 101, 114, 8, 95, 95, 105, 110, 102, 111, ...>>, {:call, 0}} iex(2)> pid = spawn(&Listener.call/0) #PID<0.115.0> iex(3)> send(pid, {:hello, "Hello World"}) Received inside the mail: Hello World {:hello, "Hello World"} iex(4)> ``` **得到它** ``` 1> c("mailbox.erl"). {ok,mailbox} 2> mailbox:module_info(). [{module,mailbox}, {exports,[{call,0},{module_info,0},{module_info,1}]}, {attributes,[{vsn,[330096396114390727100476047769825248960]}]}, {compile,[{version,"8.4.3"}, {options,[]}, {source,"/private/tmp/NKI90h/mailbox.erl"}]}, {md5,<<248,86,64,221,149,120,150,9,30,225,159,226,217, 253,6,192>>}] 3> Pid = spawn(fun mailbox:call/0). <0.93.0> 4> Pid ! {hello, "Hello World"}. Received inside the mail: "Hello World" {hello,"Hello World"} 5> ``` 有了這個,我們就有了所有必要的工具來理解 BEAM 語言如何默認提供並發性,只需從一開始就同時定義它們的抽象,很酷吧? > 額外提示:我有一系列文章討論 Elixir 語言中的這些抽象:https://dev.to/cherryramatis/handling-state- Between-multiple-instances-with-elixir-4jm1 使節點透過網路互動的一個有趣的案例 ----------------- 讓我們記住一些很酷的事情,首先我們知道當我們啟動一個新的Erlang/Elixir 應用程式時,它在BEAM 節點上執行,其次我們知道我們有本地語言構造函數來操縱在該節點內執行的進程,並且可以透過訊息進行通訊交換對嗎? 現在如果我告訴你節點也可以通訊怎麼辦?這是正確的! BEAM 確實是分散式軟體的完美技術,在著名的[蜜罐](https://www.youtube.com/@Honeypotio)影片 José Valim 中解釋了我將在下面描述的這種交互,該影片可以在: [https://www.youtube.com/watch?v = lxYFOM3UJzo](https://www.youtube.com/watch?v=lxYFOM3UJzo)從分鐘開始`4:41` > 為了公正地對待 José Valim,我們將按照他在影片中的方式在 Elixir 中執行範例,但也可以使用 Erlang 以相同的方式執行此範例。 要在 BEAM 節點上啟動 Elixir 系統,我們將使用主機名稱啟動互動式 REPL,並定義一個在螢幕上列印「Hello world」的範例模組: ``` 🍒 iex --name cherry Erlang/OTP 26 [erts-14.2.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace] Interactive Elixir (1.17.0-dev) - press Ctrl+C to exit (type h() ENTER for help) iex([email protected])1> defmodule Hello do ...([email protected])1> def world do ...([email protected])1> IO.puts("Hello World") ...([email protected])1> end ...([email protected])1> end {:module, Hello, <<70, 79, 82, 49, 0, 0, 5, 72, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 184, 0, 0, 0, 19, 12, 69, 108, 105, 120, 105, 114, 46, 72, 101, 108, 108, 111, 8, 95, 95, 105, 110, 102, 111, 95, 95, 10, ...>>, {:world, 0}} iex([email protected])2> Hello.world Hello World :ok iex([email protected])3> ``` 在另一個終端中,讓我們使用另一個名稱啟動一個**新的 REPL** ,並嘗試執行上面實例中定義的模組: ``` 🍒 iex --name kalane Erlang/OTP 26 [erts-14.2.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace] Interactive Elixir (1.17.0-dev) - press Ctrl+C to exit (type h() ENTER for help) iex([email protected])1> Hello.world ** (UndefinedFunctionError) function Hello.world/0 is undefined (module Hello is not available) Hello.world() iex:1: (file) iex([email protected])1> ``` 嗯...沒有那麼簡單,對吧?事實上,我們需要使用`Node`模組來使這種通訊成為可能,現在讓我們在與之前相同的 REPL 中執行以下行: ``` iex([email protected])1> Node.spawn(:"[email protected]", fn -> Hello.world() end) Hello World #PID<13525.123.0> iex([email protected])2> ``` 你的頭爆炸了嗎?我希望如此,因為這意味著我們正在同一網路中以完全語言原生的方式通訊兩個獨立的 Elixir 實例(因此 Kubernetes /j)。 借助這項技術,我們可以建立整個發布訂閱和通知系統,而無需依賴專用的 SaaS,只需使用 VM 已提供的功能即可。 結論 -- 在這篇文章中,我盡力回顧了我對 BEAM 的最新研究,特別是回顧了我的熱情和發現時刻,因為在我閱讀和研究時,這無疑是一系列持續的「精神打擊」。 我的研究主要涉及嘗試從虛構的語言重新建立`.beam`文件,該語言僅定義返回靜態值的函數,該專案在 elixir 中有一個初始 rust 版本和一個 WIP 版本,可以在連結中找到: [https ://github 。](https://github.com/cherryramatisdev/beam_studies) 參考 -- - [光束書](https://blog.stenmans.org/theBeamBook) - [Elixir 編譯階段](https://elixirforum.com/t/getting-each-stage-of-elixirs-compilation-all-the-way-to-the-beam-bytecode/1873) - [Tsoding:我創造了一種新的程式語言](https://www.youtube.com/watch?v=6k_sR6yCvps) - [萬能藥:紀錄片](https://www.youtube.com/watch?v=lxYFOM3UJzo) - [OpenErlang:在 BEAM 上實作語言](https://www.youtube.com/watch?v=0MTiqI9v-ck) 願原力與你同在🍒 --- 原文出處:https://dev.to/cherryramatis/beam-vm-the-good-the-bad-and-the-ugly-9d6

使用 matcha.css 讓你的新網站瞬間變漂亮!

您是否曾經想過在開始一個新的網路專案時從「空白頁」開始是多麼的簡單? ![空白頁](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/syhnfxnz7i2cs3exqhf4.png) *請注意缺少任何樣式或自訂屬性*。 ``` <html> <body> <h1>Hello world!</h1> <p> This is my new project, and it's still under construction. Please be indulgent 😊 </p> <p> Also, check out my work on <a href="https://github.com/octocat">GitHub</a>! </p> <blockquote> <p> Imagination is more important than knowledge </p> <cite>Albert Einstein</cite> </blockquote> <menu> <li>Home</li> <li> About me <menu> <li>My works</li> <li>My passions</li> </menu> </li> <li>Contact</li> </menu> <form> <h2>Contact me</h2> <label> Your email: <input type="email" name="email" placeholder="Your email" required> </label> <label> Your message: <small>255 characters max</small> <textarea name="message" placeholder="Your message" required></textarea> </label> <button type="submit">Send</button> </form> </body> </html> ``` 哎喲!如果你向你的朋友展示這一點,同時聲稱你是網頁開發人員,他們會開始質疑你到底在做什麼... 預設瀏覽器樣式表通常非常簡單,當您製作應用程式原型、生成靜態 HTML 頁面、Markdown 生成的文件等並且不想深入研究時,如果沒有“視覺上不錯”的東西,可能會令人沮喪過早地接觸CSS 的複雜性。 好訊息!我有一些適合你的東西: [matcha.css](https://matcha.mizu.sh) ! 只需將以下內容加入到您的文件中即可看到奇蹟發生: ``` <link rel="stylesheet" href="https://matcha.mizu.sh/matcha.css"> ``` ![抹茶頁面](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2duw5mfvuxcf0s56w7f.png) 沒有真正做任何事情,我們就得到了一個尊重用戶對淺色/深色模式的偏好、漂亮的字體和適當的間距的頁面,我們的`<menu>`實際上看起來像一個菜單,而且我們的`<form>`甚至還有「必填欄位」也相當不錯所需投入的指標。 所有這些都無需任何建置步驟、JavaScript、配置或重構。 這是因為[matcha.css](https://matcha.mizu.sh)使用語意樣式。例如,它假設嵌套在另一個`<menu>`中的`<menu>`應產生一個子選單,而`<label><input required></label>`應向使用者澄清輸入是強制性的。 還有一些「嵌入式」CSS 庫,但我相信這是最完整的一個,因為它提供了額外的開箱即用的現代樣式,如語法突出顯示、簡單佈局、實用程式類別等。 ![抹茶](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cuq2b9axcybs26lbkple.png) [matcha.css](https://matcha.mizu.sh)也很容易自訂(它沒有任何`!important`規則,甚至提供了建立自訂建置的幫助器),同時也是可逆的(如果您決定遷移出去,只需刪除樣式表)。 最後但並非最不重要的一點是,它是完全免費和開源的! https://github.com/lowlighter/matcha 請參閱[matcha.mizu.sh](https://matcha.mizu.sh)了解完整概述! --- 原文出處:https://dev.to/lowlighter/make-naked-websites-look-great-with-matchacss-4ng7

快速建造 WhatsApp 機器人 ⚡

--- 標題:快速建造 WhatsApp 機器人 ⚡ 發表:真實 描述:建立一個將 WikiPedia 摘要發送到 WhatsApp 的🤖 標籤: twilio、replit、whatsapp、聊天機器人 封面圖片:https://i.imgur.com/XQ4FhRA.png --- 幾個月前,我開始在[Telegram](https://t.me)上製作聊天機器人 - 我看到了 WhatsApp 的一些 API,但它們是非官方的,並且您的號碼有可能被封鎖 📱 ❌ 不久前,我看到[Twilio](https://twilio.com)有一個官方的 WhatsApp API。 30 分鐘後,我[在 WhatsApp 上製作了一個維基百科機器人](https://wikibot.4ty2.fun)👇 ![](https://wikibot.surge.sh/Untitled-b9da3f92-94c0-4f97-8afb-787110d8a9d3.png) 本教學可協助您在 WhatsApp 上建立自己的聊天機器人 - 這些機器人可立即供超過 20 億用戶使用,並且有很多事情是可能的 🎓 我迫不及待想看看你做了什麼!現在,讓我們開始吧🏃‍♂️ 🔑 帳戶和金鑰 ------- 首先,註冊[Twilio](https://www.twilio.com/try-twilio) - 它是免費的,您不需要信用卡 💳 ![](https://wikibot.surge.sh/screely-1535885763017-fc654067-9557-4bf7-98b5-4337911ff4ba.png) 驗證完電話號碼後,選擇“Procuts”&gt;“Programmable SMS”,然後繼續為您的專案命名。 ![](https://wikibot.surge.sh/screely-1535885937977-c5a924ec-8cc3-4430-9345-9b5e1dc74ef3.png) 您可以隨意跳過新增隊友的步驟 - 您現在不需要這樣做。 現在您必須記下建造 WhatsApp 機器人所需的一些驗證金鑰 👇 ![](https://wikibot.surge.sh/screely-1535886250966-f68b6cfb-c104-4adf-80e7-4e3f9bd15b5b.png) 最後一步 -[在此](https://www.twilio.com/console/sms/whatsapp/sandbox)設定您的 WhatsApp 沙盒 - 選擇任意號碼,然後按照頁面上的指示加入您的沙盒。 ![](https://wikibot.surge.sh/screely-1535886798623-1dac1ba9-c362-4e49-87ab-7bbb6138e8c7.png) 啊啊啊,您已完成憑證設定!別擔心,這是本教學中最困難的部分😛 🚀 開始使用 ------ 為了避免在設定上花費太多時間,我建立了一個可以在瀏覽器中使用的環境(使用[repl.it](https://repl.it) !)。前往[這裡](https://repl.it/@jajoosam/wikibot-start),等待幾秒鐘來分叉它。 接下來,[建立一個`.env`檔](https://repl.it/site/docs/repls/secret-keys)- 並在`1`行和`2`行輸入您的帳戶 SID 和驗證令牌 ``` SID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # Account SID KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # Auth Token ``` 您可以看到,此環境已經安裝了依賴項,並設定了`express`伺服器。不過,我們仍然需要為 Twilio 提供一個用於發送傳入訊息的 URL 🔗 讓我們回到[WhatsApp Sandbox](https://www.twilio.com/console/sms/whatsapp/sandbox) ,並為傳入訊息輸入一個 Webhook URL。 ![](https://wikibot.surge.sh/Untitled-3ed5263b-c6d8-492b-ba08-b4644ab502cf.png) 此 URL 必須是您在[repl.it](http://repl.it)專案的預覽面板上看到的 URL + `/incoming` ![](https://wikibot.surge.sh/Untitled-1779b21f-9100-4942-b732-320dc48c5f76.png) 現在我們終於可以讀取發送給機器人的訊息了。導航到`index.js` ,然後在您的 webhook 處理程序中加入一個簡單的`console.log()` 👇 ``` app.post('/incoming', (req, res) => { console.log(req.body) }); ``` 當您向機器人發送訊息時,您應該能夠在 repl 控制台中看到類似的內容 👨‍💻 ![](https://wikibot.surge.sh/Untitled-163eb09e-e6ab-4910-badb-d8aa0aa789f7.png) 建造一個 echo 機器人看起來像這樣,使用`twiml`編寫訊息👇 ``` app.post('/incoming', (req, res) => { const twiml = new MessagingResponse(); twiml.message(req.body.Body); res.writeHead(200, {'Content-Type': 'text/xml'}); res.end(twiml.toString()); }); ``` 但是,由於我們實際上正在嘗試建立一個有用的機器人 - 讓我們使用資訊豐富的 API! 🌐 獲取訊息 ------ DuckDuckGo 有一個令人驚嘆的、免費的即時應答 API。它接受查詢並返回來自維基百科等的摘要。 一些例子 👉 [維基百科](https://api.duckduckgo.com/?skip_disambig=1&format=json&pretty=1&q=WikiPedia)、 [Macbook Air](https://api.duckduckgo.com/?skip_disambig=1&format=json&pretty=1&q=MacBook%20Air) 、 [Twilio](https://api.duckduckgo.com/?skip_disambig=1&format=json&pretty=1&q=Twilio) 我花了一些時間建立一個像樣的解析器,它通常會從此 API 傳回資訊。嘗試將此程式碼貼到您的[repl.it](http://repl.it)專案中,您的[控制台](https://dsh.re/f7477c)中應該包含有關川普的內容 😛 ``` var base = 'https://api.duckduckgo.com/?skip_disambig=1&format=json&pretty=1&q='; var query = 'Donald Trump'; request(base + query, function (error, response, body) { body = JSON.parse(body) if(body["Abstract"] == ""){ body["Abstract"]= body["RelatedTopics"][0]["Text"] } var msg = body["Heading"]+"\n\n"+body["Abstract"]; console.log(msg) }); ``` 很簡單,對吧? 😄 🛠️ 將所有內容放在一起 ------------ 為了製作我們的實際機器人,我們需要做的就是從我們的請求中獲取查詢 - 我們可以將其作為`req.body.Body`獲取 - 並使用`twmil`發送我們在`msg`中收集的資料 ``` app.post('/incoming', (req, res) => { const twiml = new MessagingResponse(); var base = 'https://api.duckduckgo.com/?skip_disambig=1&format=json&pretty=1&q='; var query = req.body.Body; request(base + query, function (error, response, body) { body = JSON.parse(body) if(body["Abstract"] == ""){ body["Abstract"]= body["RelatedTopics"][0]["Text"] } var msg = twiml.message(body["Heading"]+"\n\n"+body["Abstract"]); res.writeHead(200, {'Content-Type': 'text/xml'}); res.end(twiml.toString()); }); }); ``` 您現在擁有一個功能齊全的 WhatsApp 機器人!發送您想了解的有關您的機器人的任何訊息 🤖,您應該會看到它的響應速度超快 💬 ⚡ 加入歡迎訊息和一些格式設定非常簡單,請查看最終的[repl](https://repl.it/@jajoosam/wikibot) ,看看我是如何做到的👨‍💻 {%回覆@wikibot%} 🔗 分享機器人 ------- 對於其他人使用此機器人,他們需要先加入您的沙箱 - 並發送一條訊息,就像您之前所做的那樣 👉 `join <two-words>` 您也可以使用此文字建立連結 - 例如此連結可讓您加入我的機器人👇 ``` https://wa.me/14155238886?text=join ultramarine-tapir ``` `14155238886`是我的機器人號碼,而`ultramarine-tapir`是沙盒短語。 ⚡ 接下來是什麼? --------- 既然您已經知道如何在 WhatsApp 上建立機器人,請嘗試向自己發送通知,並建立更多有用的工具! Twilio 還有大量[其他媒體](https://www.twilio.com/channels)可用於傳遞訊息! 我的 WikiBot 的所有程式碼都在[Github](https://github.com/jajoosam/wikibot)上 ⬇️ {%github github/wikibot%} 我是一名 15 歲的創客 👨‍💻 想要製作更多酷炫的東西並了解我的進展,請訂閱[我的時事通訊 📧](https://buttondown.email/jajoosam) --- 原文出處:https://dev.to/jajoosam/build-a-whatsapp-bot-fast--2hdc

試玩 Twill CMS 的 Block Editor 功能

回頭看之前跳過的教材 https://twillcms.com/guides/page-builder-with-blade/configuring-the-page-module.html 我先跳過圖片設定的段落,直接在 PageController 加入以下內容 試試看會不會壞掉? ``` $form->add( BlockEditor::make() ); ``` 打開 Pages 的編輯頁面,會看到下面出現 `Add content` 以及 `Open in editor` 按鈕 不論選哪種,都是 Image 跟 Body text 兩種 block 可以加入 我先使用 Add content 按鈕,新增了一個文字、一個圖片、再一個文字、再一個圖片 直接按下 Update,會發現儲存成功! 來觀察一下資料庫,觀察一下這種資料是怎麼存的 (我只記錄主要欄位 額外欄位我先省略) --- ## twill_blocks | id | blockable_id | blockable_type | position | content | type | |----|--------------|-----------------|----------|---------------------|-------| | 1 | 1 | App\Models\Page | 1 | json with html attr | text | | 2 | 1 | App\Models\Page | 2 | {} | image | | 3 | 1 | App\Models\Page | 3 | json with html attr | text | | 4 | 1 | App\Models\Page | 4 | {} | image | 這邊看起來很單純,就是 Laravel 原生 Many to Many (Polymorphic) 功能的結構 只不過 laravel 官方慣例會叫 `blockables` 而這邊命名為 `blocks` 而已 比較奇怪的是圖片那兩行都是 `{}`,那圖片的資料存在哪呢? --- ## twill_medias | id | uuid | filename | |----|---------------------------------------------------|--------------| | 1 | 30463fbb-aaef-43cb-936a-2deb53bd9973/01-doge.jpeg | 01-doge.jpeg | | 2 | b1ea0fb5-6f57-45fb-9903-d22049c5eb60/02-shiba.png | 02-shiba.png | 找到圖片的資訊了,這邊的 uuid 欄位我不太喜歡,因為 `/` 後面的部份跟 filename 重複了,不知這樣設計的考量是? 接著來找檔案在哪裡 ``` ➜ twill-play git:(main) ✗ tree storage/app/public/ ``` ``` storage/app/public/ └── uploads ├── 30463fbb-aaef-43cb-936a-2deb53bd9973 │   └── 01-doge.jpeg └── b1ea0fb5-6f57-45fb-9903-d22049c5eb60 └── 02-shiba.png ``` 還滿讚的,既保留了檔案名稱,也用 uuid 資料夾保證了檔案路徑的唯一性! 但是 twill_blocks 跟 twill_medias 的資料又是怎麼對應的? --- ## twill_mediables | id | mediable_id | mediable_type | media_id | |----|-------------|---------------|----------| | 1 | 2 | blocks | 1 | | 2 | 2 | blocks | 1 | | 3 | 2 | blocks | 1 | | 4 | 4 | blocks | 2 | | 5 | 4 | blocks | 2 | | 6 | 4 | blocks | 2 | 原來在這裡,又用到了 Laravel 原生 Many to Many (Polymorphic) 功能的結構 而且這次就是按照慣例叫做 mediables 囉,我這邊省略了一些欄位,是有關圖片寬度、高度的 每張圖片分別 crop 成 Desktop Tablet Mobile 三種尺寸 --- 現在知道 Block Editor 背後資料怎麼存的 感覺安心不少 也學到很多 來試試看 GUI 吧,也就是點擊 Open in editor 按鈕 ![](https://i.imgur.com/A5X6ANt.png) 呵呵悲劇囉,看來還缺少 `site.blocks.text` 以及 `site.blocks.image` 兩種 view 模板 乖乖繼續跑下一章節吧 https://twillcms.com/guides/page-builder-with-blade/creating-a-block.html 先按照說明 Disable default blocks 然後開始輸入指令 ``` php artisan twill:make:block text ``` 會出現兩個檔案,按照教材把內容放入 `resources/views/twill/blocks/text.blade.php` 這個是 editor 內的 input UI `resources/views/site/blocks/text.blade.php` 這個是實際顯示的模板檔案 ``` php artisan twill:make:block image ``` 一樣出現兩個檔案,把教材內容放入 `resources/views/twill/blocks/image.blade.php` `resources/views/site/blocks/image.blade.php` 這樣就可以了!Open in editor 就不會看到錯誤訊息了 但是,剛剛輸入的文字跟圖片,都沒有顯示 估計是因為資料結構有變吧! 通通刪掉,重新輸入一次 然後更新 `config/twill.php` 放進教材提供的 crops 內容 這樣就可以了!Block editor 就可以使用了! ref commit: https://github.com/howtomakeaturn/twill-play/commit/3dbac8d2b78fdf5da06ffd12039ffb7245bb0a46

在 Twill CMS 建立模組之間的關聯

繼續研究比較進階的功能吧 假設客戶是一間設計顧問公司好了 在台北、台中、高雄都有辦公室,存在 offices 模組 然後官網有許多 pages 要展示,每個 page 是由不同的辦公室設計 要如何建立這種關聯呢?又該如何在前台存取關聯模組呢?操作起來就跟 laravel 原生功能一樣嗎? --- 參考官網文件 https://twillcms.com/docs/relations/one-to-many.html ``` php artisan make:migration add_office_id_to_pages_table ``` 把 `office_id` 欄位加好之後,直接進 mysql 把 pages 加上 office_id 試試看! 接著在 Office.php 加入 hasMany 然後在 Page.php 加入 belongsTo 再來試試看在 page.blade.php 加入 ``` <hr /> by office: {{ $item->office->title }} ``` 然後在 office.blade.php 加入 ``` <hr /> pages count: {{ $item->pages->count() }} ``` 打開頁面會發現...成功運作! 也就是關聯操作完全跟 laravel 原生語法一模一樣,真是太棒了 ref commit: https://github.com/howtomakeaturn/twill-play/commit/d5b211a69661a2f456f874e8aac5fd51603fc4a8 --- 最後,不能真的叫客戶開 mysql 進去修改資料。來更新管理面板,給客戶 GUI 使用吧! 這邊一樣文件有點不足,參閱了幾份文件&原始碼 https://twillcms.com/docs/relations/one-to-many.html https://twillcms.com/docs/form-fields/select.html PageController 加入這段 ``` $form->add( Select::make()->name('office_id')->label('Office') ->options(Office::all()->map(function (Office $office) { return [ 'value' => $office->id, 'label' => $office->title, ]; })->toArray()) ); ``` 然後在 App\Models\Page 的 `$fillable` 陣列加入 'office_id' 打開管理面板,大功告成! 這段程式碼修改,依然跟原生 laravel 操作完全相容 實在是強大、開發者友善的 CMS 架構啊! re commit: https://github.com/howtomakeaturn/twill-play/commit/be1365f9a166ff28c12bd6936d7b7968fbdaa3d9

建立多個 Twill CMS 模組,並且整理後台導覽列

再來新增一個模組試試看,假設官網要顯示各地辦公室的資訊 來建立辦公室模組,這次選「不用支援多語」 ``` php artisan twill:make:module offices ``` 其餘參數都按照教材輸入 https://twillcms.com/guides/page-builder-with-blade/creating-the-page-module.html --- 完成之後,看一下 migration 檔案 會發現少了 `xxx_translations` 那張 table 然後 title 跟 description 出現在 offices 資料表,果然跟之前猜測的一樣! --- 同樣在 AppServiceProdiver 加入 ``` TwillNavigation::addLink( NavigationLink::make()->forModule('offices') ); ``` 就可以在後台管理檔案了 --- 接著修改 routes/web.php ``` Route::get('offices/{slug}', [\App\Http\Controllers\OfficeDisplayController::class, 'show'])->name('frontend.office'); ``` 並且新增控制器 ``` <?php namespace App\Http\Controllers; use App\Repositories\OfficeRepository; use Illuminate\Contracts\View\View; class OfficeDisplayController extends Controller { public function show(string $slug, OfficeRepository $officeRepository): View { $office = $officeRepository->forSlug($slug); if (! $office) { abort(404); } return view('site.office', ['item' => $office]); } } ``` 就可以在前台查看網頁囉! --- 目前後台的導覽列,有 `Pages` 跟 `Offices` 兩個項目 假設我們想整理一下後台導覽列,把 pages 跟 offices 都視為「About」的資訊,該怎麼做呢? https://twillcms.com/docs/getting-started/navigation.html 我先試試看只更新 routes,不更新 AppServiceProvider 這樣搞,應該會讓後台壞掉 ``` // TwillRoutes::module('pages'); // TwillRoutes::module('offices'); Route::group(['prefix' => 'about'], function () { TwillRoutes::module('pages'); TwillRoutes::module('offices'); }); ``` 結果打開後台面板,居然沒有故障! 倒是兩個模組,網址前面真的多了 `/about` 所以 `TwillRoutes` 不只是對應網址&控制器的功能 更是會根據 route group 前綴,去更新對應,太神奇了,不知道怎麼寫的? --- 現在後台導覽只有網址改變,導覽列 UI 結構沒變,還沒完成 我要讓導覽列只剩下 About,然後有次級導覽列 About -> Pages About -> Offices 我在官網找不到設定方法 https://twillcms.com/docs/getting-started/navigation.html 但是翻閱原始碼之後 https://github.com/area17/twill/blob/3.x/src/View/Components/Navigation/NavigationLink.php 會發現這樣寫即可 ``` public function boot(): void { // TwillNavigation::addLink( // NavigationLink::make()->forModule('pages') // ); // TwillNavigation::addLink( // NavigationLink::make()->forModule('offices') // ); TwillNavigation::addLink( NavigationLink::make()->forModule('pages') ->title('About') ->doNotAddSelfAsFirstChild() ->setChildren([ NavigationLink::make()->forModule('pages'), NavigationLink::make()->forModule('offices'), ]) ); } ``` 乍看之下,好像有點複雜,但實際測試一下相關函數的行為,會發現妙不可言! 這種設計給予了工程師極大的自由,可以把導覽列整理成各種樣子! 我真心認為寫出相關類別的工程師,具有非常深厚的功底、經驗! --- 相關 commit 1 https://github.com/howtomakeaturn/twill-play/commit/87849d8963b10412ccb7f3eaa46204f3202e6c08 相關 commit 2 https://github.com/howtomakeaturn/twill-play/commit/1e441eb81bb24642058d1826fc5b77a3d3873545

沒有人長大後想成為 DevOps 工程師

當我看到那些不像我一樣主要在線下成長的年輕一代時,我為他們感到有點遺憾。我已經三十多歲了,所以我知道在成長過程中盡快接入[撥號](https://en.wikipedia.org/wiki/Dial-up_Internet_access)網路(以避免長時間阻塞電話線)存取幾個維基百科頁面來完成我的任務是什麼感覺。什麼。透過親身經歷我們所有人口袋裡的個人電腦的崛起,我覺得自己並沒有免疫,但更有能力利用它來為自己謀利,而不是僅僅因為更加“ [互聯](https://www.newyorker.com/news/the-new-yorker-interview/jonathan-haidt-wants-you-to-take-away-your-kids-phone)”而成為其無限幸福和滿足的虛假承諾的受害者。 ![撥號](https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExamF3aXZ0NHZxYmo4NWVqa2FhcWwxM2lhYnYwaHowdmtpZGlhNTNiZiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/XreQmk7ETCak0/giphy.gif) 另一方面,還有另一場革命,**我沒有直接參與其中**,這場革命是在 2009 年 O'Reilly Velocity 會議上著名的[Flickr](https://www.youtube.com/watch?v=LdOe18KhtT4)演講之後,在 00 年代全世界的 IT 部門中發生的。事件讓`DevOps`聲名大噪,並展示了一個可以從孤立的、發展緩慢的基於[ITIL](https://en.wikipedia.org/wiki/ITIL)的組織轉向更好的組織的未來。 不到 5 年前,我最近從教學轉向了科技。我不知道在任何其他不實踐 Flickr 演講中所傳授的實踐的專業環境中工作會是什麼樣子。敏捷方法論和「DevOps」仍然[難以確定](https://www.reddit.com/r/devops/comments/812527/can_someone_explain_what_devops_is/)的定義是我從未質疑過的現狀。 **但我現在對此表示懷疑**。如果我認為,未來的世代缺乏基本的視角,並且可以從了解沒有智慧型手機的生活是什麼樣子中獲益匪淺。**我必須將同樣的邏輯應用在自己身上,並且齊心協力去理解 DevOps 到底是什麼?它是對什麼的回應?它最初的承諾是什麼?人們如何以及為何最終成為 DevOps 工程師?未來成為 DevOps 工程師意味著什麼?** DevOps 如何開始及其最初的承諾 ------------------ 我有時想知道,在開發人員必須填寫基礎設施配置請求表並等待數天或數週才能得到服務的日子裡,情況一定是什麼樣子。我聽說過那種文化中典型的運營人員的故事,他們總是互相指責,脾氣暴躁,最喜歡說的詞是`“NO“`和`“Where's my pager?“` 。 ![行動者](https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExdG03ZXE5d3dqNjgyYXV3NnowaGdoeDc5aTIxM3ZnMGlxdnVhbnVuNSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/hSKk6hx9OzomRvFRcJ/giphy.gif) John Allspaw 和 Paul Hammond 以及他們著名的速度演講[「每天 10+ 部署:Flickr 上的開發和運維合作」](https://www.youtube.com/watch?v=LdOe18KhtT4)的許多與會者不必懷疑,開發人員和維運團隊之間的常見摩擦一定是對他們來說一切都太生動了。 多年來,我多次觀看了這個演講,有幾件事對我來說很突出。首先,我沒有意識到當時的談話包含瞭**如此多的髒話**,或者也許只是奧爾斯帕先生。另一個是演講者提出的關鍵訊息,即開發和營運團隊實際上共享相同的目標。**為業務賦能。** ![動圖](https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExaHB6Z3Myd2tpaDc3eGE3eDZ2OTMwa2ZnazMydDVlNnVkOTczeGF3dSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/FspLvJQlQACXu/giphy.gif) 他們繼續討論組織可能希望採用的工具和文化特徵來實現一天的多次生產部署。他們談到了自動化基礎設施、功能標記、共享警報和監控,所有這些都圍繞著新的協作文化結合起來,這種文化重視信任以及對系統故障和避免指責的更健康的態度。 具有巨大影響力的[《DevOps 手冊》](https://itrevolution.com/product/the-devops-handbook-second-edition/)和[《站點可靠性工程》](https://sre.google/sre-book/table-of-contents/)書籍在很大程度上進一步明確了 DevOps 在接下來的幾年中的含義。 ![主要書籍](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yb33ik288tctk2v22jf6.png) 前者的開頭章節用幾句話描述了 DevOps 的做事方式渴望解鎖什麼 > *“\[多個團隊共同努力\]實現計劃工作快速進入生產(例如,每天執行數十、數百甚至數千次程式碼部署),同時實現世界一流的穩定性、可用性和安全性。”* 我們兌現了承諾嗎? --------- 當我想到 Flickr 演講中提出的想法時,我的腦海中浮現出一種走在巨人肩膀上的感覺。這些對許多人來說一定是革命性的想法是我所知道的唯一的職業現實。因此,無論是否可以對當前的 DevOps 方法、最佳實踐和工具進行改進,我都對迄今為止所取得的所有進展表示感謝。我問過 2009 年之前配置伺服器或進行駭客攻擊的人,他們都證實**現在的情況比那時好。** 話雖如此,大多數公司是否都在瘋狂地進行運輸,同時實現世界一流的穩定性、可用性和安全性?**很大程度上沒有。** DevOps 世界即使擁有[裝滿現代可用工具的龐大工具箱](https://landscape.cncf.io/),仍然執行該演講中提出的完全相同的框架。 用[亞當雅各](https://twitter.com/adamhjk)的話來說 > 「問題不在於我們沒有對系統的每個單獨部分進行足夠的最佳化。我們在每一步都建立了更有效率的工具。但是整個系統是如何組合在一起的呢?使用體驗如何?這與 2009 年的情況基本相同,這也是我們陷入困境的原因。 **孤島仍然存在,交接容易出錯,而且在許多情況下協作相當強迫和僵化。**任何擔任 DevOps 工程師一段時間的人都會有一長串他們認為自己的組織出錯的事情,並且通常對自己的組織解決問題的能力也同樣缺乏信心。 Adam 是一位經驗豐富的 DevOps 實踐者,他甚至呼籲[第二波 DevOps](https://www.systeminit.com/blog-second-wave-devops) ,它不僅僅是簡單地改進工具,而是邀請我們跳出框框思考,挑戰既定規則,看看另一面會發生什麼。 說到DevOps實踐者,這些人是誰?一個人如何以及為何成為一個人? 人們最初是如何進入 DevOps 的? ------------------- 在短短 15 年裡,科技業取得了長足的發展。 **DevOps 工程師、SRE 和平台工程師**等職位現在在招聘網站上很常見,也是技術招聘人員的熱門專案。然而,在 IT 世界之外,這些術語仍然鮮為人知。儘管發展迅速,DevOps 還不是一個人們渴望加入的職業;相反,許多人只是**“陷入其中”** 。 ![動圖](https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExMHlhdTVzdG9wNmNzOGp6ZDljN3RlenNhMTExMTJ5N3RoY3MyYjIydCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/SeTPXfY3RFPkQ/giphy.gif) 在與我表弟交談後,我偶然進入了 DevOps,在我獲得 CCNA 憑證後決定反對嚴格的網路工程路徑後,他建議我選擇 DevOps。我很好奇誰最終會進入 DevOps,以及未來的工程師是否會選擇它作為他們的第一個職業選擇,我詢問了[/devops](https://www.reddit.com/r/devops/comments/1c24rbg/will_people_ever_grow_up_wanting_to_be_a_devops/) Reddit 子版塊,並對各種不同的意見感到驚訝。 **我發現了一些「我剛剛陷入其中」的人:** ![陷入其中](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zaafmdejwi6k9aus874r.png) **其他人則適度看好新一代:** ![樂觀的 DevOps](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ouj4w92mly7j2jbi20m2.png) ![DevOps 選擇你](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/px309e69lvjygl8vnobz.png) **其他人則不那麼樂觀:** ![我希望不是](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnzjwtczbg9zl8wh9zru.png) ![孩子們的願望](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u3z44eoh0yqgsaqyh8mf.png) 儘管 DevOps 的定義仍然存在很大[爭議](https://www.reddit.com/r/devops/comments/vfxmxv/what_exactly_is_devops/),但它似乎不太可能將自己定位為學生在招聘會上聽到或永久加入到大學課程中的職業。這可能是因為我們傾向於想像自己在特定領域表現出色,相信專業化會增加我們成功的機會。 小時候,我夢想著成為一個著名樂團的主音吉他手,擁有神級的粉碎能力。我並沒有夢想能夠相當擅長演奏所有樂器。 **在 DevOps 中,沒有吉他獨奏。**為了脫穎而出,您需要熟悉一長串工具、語言、框架、超大規模器和流程。最優秀的 DevOps 工程師本質上都是通才。這種模組化、樂高式的工作和體驗性質可能會讓 DevOps 在 IT 部門之外不太受歡迎。 通才、修補匠的案例和膠水的概念 --------------- 不可能嘗試對 DevOps 從業者應該具備哪些特徵形成非主觀的描述,但根據我的短暫經驗以及我從與比我更有經驗的人的對話中學到的東西,出現了一些特徵。 ### 通才 您讀過「[如何在 DevOps 領域找到工作](https://www.simplilearn.com/tutorials/devops-tutorial/how-to-become-devops-engineer)」指南嗎?還記得知識要求部分嗎? Linux、Docker、CI/CD、Git、Hypersclaer、網路等。 如果您曾經面試過開發人員或產品設計等職位,您很可能需要在流程的某個階段展示自己的作品集。在 DevOps 面試中這種情況很少見。我想不出有誰定期組裝和更新 DevOps 組合? DevOps 角色的模組化和分散式系統建構性質並不適合在產品組合中進行精心策劃的展示。 作為一個厭倦了教高中英語七年的人,我自然而然地被 DevOps 所吸引,這個領域要求我學習許多工具和概念,並以協作方式將它們拼湊在一起。不深入專注於任何一個概念,而是提高快速學習新事物的技能,這就是我培養的癒傷組織。在這樣的環境中茁壯成長的多面手正好適合。 ### 修補匠 在 DevOps 方面表現出色的人可能會認為自己是[修補匠](https://www.reddit.com/r/devops/comments/1cr1ho6/hot_take_were_all_just_tinkerers/)。 ![修補匠](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odqy1j4yuwc1anaioe69.png) 我喜歡這個想法,它適合我遇到的許多 DevOps 工程師。僅僅為了了解事物的知識而對學習事物如何工作感興趣是我所遇到的 DevOps 導師的一個共同特徵。當然,花週末在家庭實驗室安裝更強大的開關或在 3D 列印機上渲染新的迷你雕像並不能直接展示 DevOps 技能,但這些背景知識比憑證更能表明 DevOps 的潛在成功。 ### 膠水 複雜系統中的許多工作可能會受到關注,因為很難規劃或預測。由於 DevOps 涉及將工具編織在一起來建造平台或交付系統,**因此需要大量的黏合劑**。 流程必須到位並自動化,以跟上技術堆疊中每個工具附帶的技術債務和維護工作。那些能夠自然而然地、常常吃力不討好的充當黏合劑,透過自動化、溝通或改進重複流程連接系統的不同部分的個人,對於組織的成功至關重要。這項技能不是您在履歷中列出的內容,但與修補匠的好奇心和通才的開放性相結合,它是一個強大的組合。 目前狀態:平台與 DevOps --------------- 這些討論中常出現[錯誤的二分法,](https://www.reddit.com/r/devops/comments/17lz167/devops_vs_platform_engineering_i_still_struggle/)通常是出於行銷原因:DevOps 已死,平台才是未來。平台工程師的目標是為開發人員提供對傳統 Ops 相關元件(k8s、IaC 元件、IAM)的自主權,而無需直接交互,使開發人員能夠自助服務並保持獨立。 精心設計的、針對特定環境的平台可以提高開發人員的速度。根據[2023 年 Puppet DevOps 狀況報告](https://www.puppet.com/resources/state-of-platform-engineering),超過三分之二 (68%) 的受訪者認為採用平台工程後開發**速度**提高了。然而,速度不應該是唯一的衡量標準。正如[georgouslyhumble](https://www.reddit.com/r/devops/comments/16ipm9h/comment/k0ly9uq/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button)在 Reddit 上指出的那樣,**有時目標是在滿足新的組織要求的同時保持現有的速度**。例如,日誌記錄 sidecar 可以在不改變開發人員速度的情況下標準化日誌收集,從而增強平台以滿足不斷成長的公司要求。 維運工作仍然複雜且動態,熟練的維運人員對於超過一定複雜性閾值至關重要。平台為開發人員提供支持,但請注意,它們不一定會減少孤島或更緊密地整合開發和營運團隊。 團隊在堆疊中新增工具時要謹慎,因為新工具通常會帶來快速累積的維護和維護開銷。像[Glasskube](https://github.com/glasskube/glasskube)這樣可以**減少營運開銷的工具是不可或缺的**。我們需要更多這些工具來為未來建立強大且高效的 DevOps 平台。 未來預測 ---- ![動圖](https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExdmQ3b2J1M3A1dWw3MHgwZTQyaWdobDdwM3BnZ3htY3drNWt0bXZicSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ZZkCo8zKWtt2ZgozfX/giphy.gif) ### 某種類型的平台將會勝出 **勝出的系統、平台或工作方法不必「教導」使用者如何一起工作和協作。**未來的系統只有在使團隊協作成為最簡單、最直觀、最自然的工作方式,同時抽像出開發人員和維運人員都無法完成的工作的情況下,才能在不影響安全性和穩定性的情況下提供無限軟體交付的難以置信的可能性。 為了創造它,我們必須跳脫框架思考。 ### 第二波 DevOps 可能是一種方式 值得慶幸的是,有許多不安分、不墨守成規的人為 DevOps 領域的方法、流程和工具的不斷改進做出了貢獻。 有人可能會說,重新思考 DevOps 的正式[運動](https://www.systeminit.com/blog-second-wave-devops)已經出現,這非常令人興奮。 ### 通才和修補匠越多越好 最有能力不斷連結拼圖、閉合回饋循環並重新思考糟糕想法的人是那些不怕用深度專業化換取專業通用化的人。那些敢於冒險並通過一路修修補補、測試和提出問題來快速學習的人將使這艘象徵性的船在越來越快地走向卓越工程的過程中保持漂浮。 如何找到足夠的這些人是另一個問題。 結論 -- 看起來我還不太明白為什麼人們長大後不想成為 DevOps 工程師,也許這是一個相對較新的領域,再加上通才通常不被認為是最酷的孩子這一事實的混合體。 展望下一波人才,無論他們是有意識地選擇還是偶然進入 DevOps 角色,有一件事是肯定的:了解該領域的歷史是關鍵。這是未來工程師能夠培養辨識當前狀態與理想未來之間差距的唯一方法。如果忽視這一差距,現狀就會佔上風,我們將注定陷入停滯的平庸。 不可否認,自 DevOps 時代之前以來,技術格局已得到極大改善,但同樣明顯的是, **DevOps 15 年來仍在站穩腳跟。** 經驗豐富的專業人士需要保持敏銳的眼光,辨識並鼓勵周圍的年輕修補匠、通才和“粘合者”,不要擔心追逐某些頭銜,而是幫助重新定義**DevOps 並將其發展為能夠實現2009 年最初願望的東西。** --- 如果您喜歡這類內容並希望看到更多內容,請考慮在 GitHub 上給我們一個 Star 來支持我們🙏 [![連小貓也喜歡送星星](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1h9v5nqc7pfp6u3h1kqd.jpeg)](https://github.com/glasskube/glasskube) --- 原文出處:https://dev.to/glasskube/why-nobody-grows-up-wanting-to-be-a-devops-engineer-2jli

如何在 2024 年找到一份 Web 開發人員工作(不死不休)🧑‍💻💀

嘿,我是文斯... ========= ![https://dev-to-uploads.s3.amazonaws.com/uploads/articles/az8xf61b2qxx1msfo4t5.png](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/az8xf61b2qxx1msfo4t5.png) 我是一名自學成才的開發人員,在新冠疫情期間改變了職業生涯。透過在空閒時間學習和建構、參加黑客馬拉松以及為開發人員建立教育內容,我能夠從教育轉向 Web 開發。 當我找到第一份開發工作時,儘管我決心成為高級工程師,但我還是從一個薪水非常低的「實習生」職位開始。雖然這並不理想,但它讓我在工作中學習並踏入了大門。 一年後,經過一番努力,我得到了一個更好的職位,薪水是以前的三倍! 🤯 ![https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sf1fhsgwuurkre9a7drq.png](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sf1fhsgwuurkre9a7drq.png) 如今,我目前擔任[Wasp](https://wasp-lang.dev)的創始開發人員關係工程師,負責建置[OpenSaaS.sh](http://opensaas.sh/)等內容,這是一個適用於 React 和 NodeJS 的免費開源 SaaS 入門模板,以及 Stripe、OpenAI 和 AWS S3 整合。它基於我從建立第一個盈利的 SaaS 應用程式[CoverLetterGPT.xyz](http://coverlettergpt.xyz/)中學到的知識,該應用程式目前擁有 100 多個客戶,每月收入約 500 美元!沒什麼瘋狂的,但我仍然感到自豪。 現在,我目前擔任開發人員的角色,社群中的人們經常向我詢問有關找到技術工作的建議。考慮到這一點,並結合我過去的經驗,我想我應該寫一篇綜合文章,分享我所學到的和認為最有效的方法。 享受! 2024 年開發人員目前就業市場 ================ 首先,讓我們快速了解一下目前軟體開發人員的就業市場。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7lmohbs24ds94kwxo9dt.png) 如果您花時間在 Reddit 或[X.com](http://X.com) (又名 Twitter)上,那麼您可能會看到人們抱怨當前的開發人員就業市場有多糟糕。 為了嘗試找到一些實際的統計資料來支持這些說法,我使用[Perplexity.ai](http://Perplexity.ai)來幫助我找到一些有關軟體開發人員當前需求的訊息,我對結果感到驚訝。 顯然,對軟體開發人員的需求仍然很高,事實上**,平均需求高於其他工作,並且[預計在未來幾年將增長更多](https://icts.io/2024/02/01/5-predictions-on-software-development-jobs-in-2024)**! 那麼,為什麼現在有些開發商感覺比平常更難找到工作呢? 嗯,那是因為它實際上*更難*,但前提是您是經驗不足的開發人員。 另一方面,如果您是一位經驗豐富的開發人員,擁有豐富的工作經驗,那麼還有更多的空缺職位可供您選擇。但如果您是剛起步的初級開發人員,競爭將比以往更加激烈。 原因如下: 1. **所需技能的複雜性**:軟體開發越來越複雜,需要廣泛的技能,這使得[許多候選人很難滿足工作要求](https://nxtide.com/the-global-shortage-of-software-developers-and-its-serious-implication-in-the-comming-years/)。 2. **遠距工作趨勢**:向遠距工作的轉變擾亂了入門級開發人員管道,[使公司更難找到和培訓新人才。](https://www.revelo.com/blog/software-developer-shortage-us) 3. **經濟因素**:疫情和隨後的經濟變化導致[招聘模式波動,在某些時期出現大量裁員,隨後需求激增](https://icts.io/2024/02/01/5-predictions-on-software-development-jobs-in-2024)。 基本上,儘管對經驗豐富的開發人員的需求很高,但對經驗不足的開發人員的需求相對較低。 因此,由於初級和中級工程師的供應相對較多,都在競爭相同的工作,您如何才能獲得經驗豐富的開發人員的技能並讓自己脫穎而出? 成為問題解決者,而不僅僅是編碼員 ================ 軟體開發職業意味著變化是永恆的。你必須隨時準備好學習新事物並走出你的舒適區,因為, 1. 工作需要它,並且 2. 該行業以極快的速度發展 在這樣的環境中,憑證、課程和學位(在某種程度上)就不那麼重要了,因為它們不能證明你具備適應和解決出現的新問題所需的技能。當然,它們證明您擁有一定數量的基礎知識,但這只是工作所需技能的一小部分。 您希望能夠透過以下方式證明您可以應對以前從未遇到過的挑戰: - 快速了解這個新主題, - 找到合適的方法來解決它,並且 - 快速執行該方法以實現您的目標 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2lbjy6ikx8iy9lb3ngx5.png)](https://www.tiktok.com/@techfren/video/7361777687158983943) 但不要只是從我這裡奪走它。 AJ,又名[TikTok 上的 Techfren](https://www.tiktok.com/@techfren/video/7361777687158983943) ,談論如何在後人工智慧世界中駕馭當前的工作環境。他在這裡提出了一些與本文相關的好觀點。例如: 1. 一般的編碼知識甚至不太相關,因為人工智慧擁有非常廣泛的編碼知識。作為一名工程師,你不再有價值,因為你知道如何編碼——人工智慧現在知道如何很好地編碼(並使用比你更多的程式語言)。**你的價值在於批判性思考、解決問題以及為這些問題建立解決方案。** 2. 企業將開始更多地尋找這些通才問題解決者來建立內部應用程式(即內部工具)作為付費服務的替代品,以節省資金並滿足其特定的業務需求,因為人工智慧使開發人員能夠提高工作效率。 因此,很明顯,解決問題的技能需求量很大,並且在未來將繼續變得更加重要。我們可以假設更有經驗、更受歡迎的開發人員擁有這些技能,那麼我們該如何自己建立它們呢? 解決自己的問題 ======= 好的。因此,您認為自己是一位充滿好奇心的開發人員,能夠快速適應和學習新事物,並即時解決問題。 但你要如何向未來的雇主證明這一點呢? 簡單的。只解決自己的問題!在實踐中 - 在 Web 開發領域 - 這意味著「處於舒適區的邊緣」並建立適合您和您的興趣的獨特 Web 應用程式。 [![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n06z1ktgs70g5c7cv2r7.png)](https://tiktok.com/@cameronblackwoodcode/video/7364455582981524768) 自學成才的工程師和內容創作者卡梅倫·布萊克伍德 (Cameron Blackwood) 在他的[TikTok 影片中完美地描述了這一點,為新開發人員提供如何提高技能的建議](https://tiktok.com/@cameronblackwoodcode/video/7364455582981524768)。他也擁有獨特的視角,因為他之前擔任過技術招募人員,他說: - 建立一個網頁應用程式來解決您日常生活中遇到的問題 - 嘗試與您目前在日常工作中學習/做的事情不同的事情。 - 在空閒時間繼續建構和嘗試新事物。 當然,您製作的這些應用程式不一定是完美的,但它們越獨特,就越能展示出對問題的創造性和良好實現的解決方案,就越好。 如果您在思考要建立的東西時遇到困難,有時只需嘗試新工具即可激發新想法。但無論你決定如何處理它,都取決於你自己,重要的是開始,所以開始吧! --- 順便說一句, [Wasp](https://wasp-lang.dev)是輕鬆建立解決您獨特問題的新應用程式的好方法。這也是在 React 和 NodeJS 中建立客製化全端應用程式的最快方法之一,而無需為身份驗證、路由、端到端類型安全性、部署等編寫一堆樣板程式碼。 作為示例,請觀看此影片,該影片向您展示了在整個應用程式中實施全端身份驗證是多麼容易。 https://www.youtube.com/watch?v=Qiro77q-ulI 做繁重的工作 ====== ![好的](https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExa2s1d3J6dmQ2ZHc3b2RsYXQxdnFhOWR5Z3licmhjajdxZ2N3anBsOCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/AYECTMLNS4o67dCoeY/giphy.gif) 當我寫這篇文章時,我很幸運地看到了[Jonathan Stern 的這條推文](https://x.com/jonathanrstern/status/1792220536837230723),他在推文中談到了他在開始第一份開發工作時發現非常有價值的建議。 在那份工作之前,Jonathan 給 Replit 的執行長[Amjad Masad](https://x.com/amasad)寫了一封電子郵件,並在開始他作為軟體開發人員的第一份工作時尋求建議。 阿姆賈德是這麼說的: > 證明自己並讓自己變得不可或缺的兩種方法: > > 1. 具有令人難以置信的生產力和創造力——這在剛開始時很難做到 > > 2. 做無人願意做的無聊工作 > > 2 適合每個人,它只需要努力和紀律,但沒有人做到,所以我建議這樣做。順便說一句,2 通常可以以有趣的方式導致 1。 現在,儘管這是針對已經有工作的開發人員的建議,但我認為這是許多正在尋找工作的經驗不足的開發人員應該聽到的建議。 從更廣泛的意義上來說,阿姆賈德的建議是先降低你的期望並努力工作。做沒有人願意做的無聊工作也可能意味著做你不熱衷的工作,但從長遠來看,這對你有利。 這也可能意味著接受一些不完全是你之前想要的工作,並做繁重的工作,以便成為任何雇主都希望在其團隊中擁有的「不可或缺」的開發人員。 做個好人 ==== 這個建議非常籠統,幾乎適用於任何工作(或任何事物),但成為一個好的共事者可能比大多數求職者想像的更有價值和被忽視。 一旦您滿足了工作要求,您對未來雇主的吸引力很大程度上取決於他們是否可以想像與您在團隊中工作。雖然從表面上看這似乎簡單明了,但實際上實施起來要困難得多。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3s990jfmwryfx8gk9xw5.gif) 想一想。 您將在一個具有許多不同個性的團隊中工作。任務可能會變得複雜,截止日期可能會很緊迫,而且工作可能會變得混亂。肯定會犯錯。 *你是那種在壓力下會失去幽默感的人嗎?* *當有人因為你不直接負責的錯誤而責備你時,你會如何反應?* *您是否與您的團隊進行公開且有效的溝通?* *努力工作一年卻沒有加薪,你還會保持謙虛和認真嗎?經過一年的努力工作、大量的讚揚和豐厚的加薪(這可能更難),你還會保持謙虛和認真嗎?* 誠實、開放、真誠是難以獲得的寶貴特質,人們往往可以立即看出你是否是這種人。正是這些類型的人,在與同樣滿足工作要求的其他候選人競爭時,最終獲得了工作機會。 投入更少的精力,送出更少的應徵信 =============== 我和許多其他雇主抱怨的一件事是,求職者在申請中幾乎沒有任何努力。最嚴重的冒犯是應徵信內容明顯是複製貼上的。 ![打字](https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExNW0wMm03N3IwaTdlcWdtcHd4MXpsZWV5ZDVkMXBzOGQ5ZWVlNG9vaCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/13GIgrGdslD9oQ/giphy.webp) 雇主討厭這一點,因為這是你將如何工作的明顯跡象。如果你的工作申請是懶惰地完成的,那麼你的工作很可能會表現得類似(或更糟!)。 這就是為什麼我認為最好將更多的精力投入到更少的工作申請中。 沒有神奇的數字,但每當我申請工作時,總會有 2 或 3 個讓我感到*非常*興奮。所以這些是我唯一申請的,我在這些申請中投入了很多思考和努力。 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kvjr8y8gcc4switxoga.png) 除了[為我的專案製作包含描述和學習目標的自己的作品集](https://vincanger.github.io/)之外,我還會建立某種形式的與工作申請相關的額外內容。在某些情況下,這是一個簡單的範例應用程式,或者在其他情況下是解釋影片或文章。 重要的是,這些額外的內容是嘗試解決工作描述中提出的問題或任務,以表明我可以做好這類工作,並且我渴望並願意*做繁重的工作。* 我的假設是,大多數其他申請者在申請時不會花這麼大的力氣,因此我的申請會從人群中脫穎而出,而且效果很好,因為即使我之前沒有很多經驗,我也被要求面試其中的許多職位! --- 順便一提… 我們在[Wasp](https://wasp-lang.dev/)正在努力建立這樣的內容,更不用說建立一個現代的開源 React/NodeJS 框架,讓您能夠快速行動! 如果您想看到更多這樣的內容,您可以[在 GitHub 上給我們一個星星,非常輕鬆地幫助我們!](https://www.github.com/wasp-lang/wasp) 。 ![https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgbmn45pia04bxt6zf83.gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgbmn45pia04bxt6zf83.gif) <https://www.github.com/wasp-lang/wasp> ⭐️ GitHub 上的 Star Wasp 🙏 現在得到那份工作...... ============== 軟體開發人員的就業市場正在改變。這是有道理的,因為軟體開發人員的角色也在不斷發展,而現在我們正在進入人工智慧時代,這些角色的發展速度更快。 這意味著,隨著雇主的適應,他們可能會繼續尋找能夠證明他們能夠跟上所有這些發展的開發人員,並利用手邊的工具來解決我們周圍世界面臨的問題。 因此,如果你能夠證明這一點,同時成為一個認真而謙虛的工人,那麼你可能不會很難找到你一直想要的那份甜蜜的技術工作。現在只需將注意力和精力放在正確的事情上,這有時可能很困難,這將使以後找工作的過程變得容易得多。 當然,這些建議是基於我的經驗和主觀觀點,所以如果您有不同意見,請在評論中告訴我們。或者你有自己的秘訣來幫助你找到工作嗎?如果是這樣,我們想聽聽看! 感謝您的閱讀,祝您求職愉快。 --- 原文出處:https://dev.to/wasp/how-to-get-a-web-developer-job-in-2024-without-dying-inside-eo8

ChatGPT - 給開發人員的提示

了解 ChatGPT: ----------- ChatGPT 是一種人工智慧 (AI) 聊天機器人,它使用自然語言處理來建立類人對話。這個語言模型可以回答問題並撰寫各種書面內容,包括文章、社交媒體貼文、論文、程式碼和電子郵件,這使其成為各個層級的程式設計師都興奮的工具。 > OpenAI(一家人工智慧研究公司)建立了ChatGPT,並於2022 年11 月推出了該工具。 什麼是即時工程以及為什麼它很重要? ----------------- 及時的工程設計使用戶可以輕鬆獲得相關結果。它還有助於減輕大型語言模型訓練資料中現有的人類偏見可能存在的偏見。此外,它還增強了用戶與人工智慧的交互,因此即使輸入很少,人工智慧也能理解用戶的意圖。 在製作提示時, - 記住要清晰簡潔。 - 具體:指定程式語言選擇並清楚描述您需要的功能。例如,提示可以是“編寫一個 JavaScript 函數來計算給定數字的總和”,而不是模糊的“編寫一個函數來計算總和”。 - 包括必要的背景和細節,但避免任何含糊或不必要的資訊。 - 定義輸入和輸出:如果您需要的函數或程式碼段需要特定的輸入或輸出格式,請在提示中包含此資訊。 ChatGPT 如何幫助開發者: ---------------- ChatGPT 是一種高階語言模型,可以透過多種方式幫助開發人員完成編碼之旅。讓我們來探討其中的一些。 **1. 編寫程式碼:**使用ChatGPT,您可以根據具體描述產生程式碼。例如,如果您需要 C# 函數來計算 2 個數字中的某些數字。您可以如下所示提示 ChatGPT,它將返回相應的程式碼。 提示範例: ``` "Write a C# function to calculate the sum of the 2 given numbers." ``` **2.重構程式碼:**借助ChatGPT的幫助,您可以重構程式碼,以提高程式碼效率,減少錯誤,並使其更易於將來修改或擴展。 提示範例: ``` I have a piece of code and I need you to refactor it: INSERT YOUR CODE HERE ``` **3. 程式碼審查和偵錯:**您可以使用 ChatGPT 審查程式碼片段並分享潛在的問題或錯誤。 提示範例: ``` "Here's a C# code snippet. The function is supposed to return the maximum value from the given list, but it's not returning the expected output. Can you identify the problem?". INSERT YOUR CODE HERE ``` **4. 新增編碼最佳實務或原則:** ChatGPT 可協助您根據風格指南重寫程式碼。 提示範例: ``` Rewrite the code below following the Google style guidelines for JavaScript. INSERT YOUR CODE HERE ``` **5. 解釋程式碼:** ChatGPT 可以幫助解釋舊的和複雜的程式碼片段的工作原理。要獲得特定程式碼段的解釋,請提供程式碼片段並詢問。 提示範例: ``` "Could you please explain how this C# function works?". INSERT YOUR CODE HERE ``` **6. 最佳化程式碼:** ChatGPT 可以幫助優化程式碼,以增強效能或可讀性,使您的程式碼精簡且有效率。 提示範例: ``` "Here’s a function I wrote in JavaScript that prints first n Fibonacci Numbers. Could you suggest any optimizations for better performance?" INSERT YOUR CODE HERE ``` **7. 建立單元測試:**您可以使用 ChatGPT 透過為您編寫測試案例來自動化單元測試。 提示範例: ``` Please write unit tests for the following code. INSERT YOUR CODE HERE ``` **8. 新增程式碼註釋:**如果您的程式碼不言自明但需要註釋,ChatGPT 可以立即為您完成。 提示範例: ``` Add comments to the following code: INSERT YOUR CODE HERE ``` **9. 建立樣板程式碼:** ChatGPT 可以幫助您產生樣板程式碼。 提示範例: ``` Write a boilerplate JavaScript function that will take a variable of type User, and validate whether the user has the right permissions or not. ``` **10. 建立正規表示式:**正規表示式幫助我們匹配、定位和管理文本,提供了一種快速且相對簡單的方法來操作資料,特別是在大型複雜程式中,ChatGPT 可以幫助我們編寫這些正則表達式。 提示範例: ``` Write a regular expression that matches: REQUEST ``` 這些是 ChatGPT 如何讓開發人員的生活變得輕鬆的一些例子。除此之外,ChatGPT 還可以幫助學習新概念、理解設計模式、程式碼重構、集思廣益、面試準備等等。 ChatGPT 提示編寫程式碼: ---------------- 我收集了 ChatGPT 提示,這些提示可以讓開發人員的生活變得輕鬆,因為他們可以更有效地利用強大的 AI 支援的 ChatGPT。 - [編寫和生成程式碼的提示](https://dev.to/techiesdiary/chatgpt-prompts-for-writing-and-generating-codes-59kf) --- 原文出處:https://dev.to/techiesdiary/chatgpt-prompts-for-developers-216d

2024 年 7 個最適合開發者的圖表庫 🤯

許多應用程式使用圖表或圖形進行資料視覺化,這可以使用庫或底層技術來實現。庫提供時間效率、各種圖表類型和自訂選項。 作為開發人員,了解這些選項至關重要。雖然有些專案可能選擇手動實施,但許多專案都受益於圖表庫的效率。使用這些庫可以節省時間,並可以存取各種圖表類型和樣式選項來滿足您的需求。 在本文中,我們將踏上旅程,了解七個令人驚嘆的圖表庫、它們的功能以及如何使用它們。讓我們來看看! ![https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2Fqk7c7favj05g2qjice9m.gif](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqk7c7favj05g2qjice9m.gif) --- 1. Latitude for React:將圖表整合到前端應用程式的完美伴侶 --------------------------------------- **網址: <https://docs.latitude.so/react/getting-started/introduction>** ![https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2Fy7z7ks2yp21vj6fah42o.png](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7z7ks2yp21vj6fah42o.png) *是的,那就是我們!* Latitude 是用於嵌入式分析的開源框架,可讓您快速將 SQL 查詢公開為 API 端點。他們的產品中包括`@latitude-data/react` ,這是一組原生 React 元件,用於輕鬆繪製來自 Latitude API 的資料。如果您選擇攜帶自己的資料,它還可以用作獨立的圖表庫。 ### Latitude for React 的主要特性 - **多種圖表類型**:提供多種圖表類型顯示。例如長條圖、圓餅圖、面積圖、分散圖、混合圖等。 - **高度可自訂的元件**:元件預先捆綁了一組可用主題,或者您可以選擇輕鬆建立自己的自訂主題。最重要的是,大多數元件都可以使用自訂 html 類別進行擴充。 - **自動執行查詢或提供您自己的資料**:Latitude 為每個圖表元件提供兩個版本。其中一個版本會自動執行您的緯度查詢。另一個版本期望接收資料作為道具,讓使用者負責取得它。 ### 如何使用 Latitude for React 👀 首先,在您的 React 專案中安裝 Latitude 的 React 套件: ``` npm install --save @latitude-data/react ``` 之後,匯入 Latitude 元件所使用的核心樣式: ``` import '@latitude-data/react/dist/index.css'; ``` **帶有緯度後端** 如果您要從 Latitude 後端取得資料,**請**在專案根目錄下使用 LatitudeProvider 包裝您的應用程式: ``` import { LatitudeProvider } from '@latitude-data/react'; function App() { return ( <LatitudeProviderapiConfig={{ host: <YOUR_LATITUDE_API_HOST> }}> {/* Your app content */} </LatitudeProvider>); } ``` 並使用 Latitude 的任何帶有`Query`前綴的圖表元件: ``` import { QueryLineChart } from '@latitude-data/react'; function MyComponent() { return ( <QueryLineChart queryPath='titles' params={{ start_year: 2012, end_year: 2014 }} x='release_year'y={[ { name: 'count_shows' }, { name: 'count_movies' } ]} xTitle='Year' yTitle='Titles'/> ); } ``` 在此範例中,queryPath 對應於 Latitude 後端中定義的查詢的路徑。 **作為獨立的圖表庫** 只需使用獨立元件,例如: ``` import { LineChart } from '@latitude-data/react'; function MyComponent() { const data = [ { release_year: 2010, count_shows: 10, count_movies: 2 } ] return ( <LineChart data={data} x='release_year' y={[ { name: 'count_shows' }, { name: 'count_movies' } ]} /> ); } ``` 請閱讀[文件](https://docs.latitude.so/react/getting-started/introduction),以取得有關如何使用緯度動態顯示資料的更深入指南。 您可以隨時在 GitHub 上為我們的專案做出貢獻,如果您能為我們的專案給我們一顆星,我們將不勝感激! **[🌟 GitHub 上 React 的 Star Latitude](https://github.com/latitude-dev/latitude)** --- 2. D3.js:用於資料視覺化的JavaScript函式庫 ------------------------------ **D3 的網站: [https://d3js.org](https://d3js.org/)** ![https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2F1xhnyf40jvg3v50c2ba8.jpeg](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xhnyf40jvg3v50c2ba8.jpeg) D3 是一個低階圖表庫,提供無與倫比的客製化和靈活性。代價是學習曲線陡峭,並且與 React 或 Svelte 等常見前端框架的整合更加困難。如果您有一些非常具體的圖表需求,d3.js 可能是您唯一的選擇,但是,如果您希望在應用程式中快速整合一些簡單的圖表,那麼其他地方還有更好的選擇。 ### D3.js 的主要特性 - **自訂和靈活性:** D3.js 提供對 SVG、HTML 和 CSS 的低階存取,允許對視覺元素進行細粒度控制。這使得它具有高度的靈活性和可自訂性。 - **模組化:** D3.js 高度模組化,各種模組可以單獨使用,也可以一起使用。這允許對捆綁包大小和效能最佳化進行更多控制。 - **強大的轉換和動畫:** D3.js 為轉換和動畫提供強大的支持,為資料更新提供流暢而複雜的動畫。 - **社區和生態系統:** D3.js 擁有一個龐大且活躍的社區,提供大量文件、範例和插件。這使得您可以更輕鬆地找到支援和資源。 ### 如何使用 D3.js 👀 在您的專案中安裝 d3 的 npm 套件: ``` npm install d3 ``` 以下是有關如何將圖表新增至 id 為`#chart`的 html 元件的範例程式碼: ``` import * as d3 from 'd3'; // Data for the bar chart const data = [ { name: 'A', value: 30 }, { name: 'B', value: 80 }, { name: 'C', value: 45 }, { name: 'D', value: 60 }, { name: 'E', value: 20 }, { name: 'F', value: 90 }, { name: 'G', value: 55 } ]; // Set the dimensions and margins of the graph const margin = { top: 20, right: 30, bottom: 40, left: 40 }; const width = 500 - margin.left - margin.right; const height = 300 - margin.top - margin.bottom; // Append the svg object to the body of the page const svg = d3.select("#chart") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", `translate(${margin.left},${margin.top})`); // X axis const x = d3.scaleBand() .range([0, width]) .domain(data.map(d => d.name)) .padding(0.1); svg.append("g") .attr("transform", `translate(0,${height})`) .call(d3.axisBottom(x)) .selectAll("text") .attr("class", "axis-label") .attr("transform", "translate(-10,0)rotate(-45)") .style("text-anchor", "end"); // Y axis const y = d3.scaleLinear() .domain([0, d3.max(data, d => d.value)]) .nice() .range([height, 0]); svg.append("g") .call(d3.axisLeft(y)) .selectAll("text") .attr("class", "axis-label"); // Bars svg.selectAll(".bar") .data(data) .enter() .append("rect") .attr("class", "bar") .attr("x", d => x(d.name)) .attr("y", d => y(d.value)) .attr("width", x.bandwidth()) .attr("height", d => height - y(d.value)); ``` 正如您所看到的,D3.js 通常比其他替代方案更冗長,但它使您可以最大程度地控制可視化的各個方面。 D3 是免費且開源的。如果您覺得該專案很有趣,請在 GitHub 上給他們一個 Star ⭐️!他們目前的星數超過 108k! **[在 GitHub 上關注 D3.js ⭐️](https://github.com/d3/d3)** --- 3. Chart.js:用於基於 HTML 的圖表的靈活 JavaScript 程式庫 ------------------------------------------- **網址: [https://www.chartjs.org](https://www.chartjs.org/)** ![https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2F0m8eb9o6t93wwf7cvq7x.png](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m8eb9o6t93wwf7cvq7x.png) 目前是業界最受歡迎的圖表庫之一,也是最容易使用的圖表庫之一。主要因其透過使用 Canvas 進行呈現而聞名,這與某些僅將資料呈現為 SVG 的圖表庫不同。 ### Chart.js 的主要特性 - **效能**:Chart.js 可以接受內部資料結構,從而減少解析和規範化的需要,從而提高效能。您還可以配置資料抽取,以在渲染資料集之前減少資料集的大小,從而加快渲染速度。 canvas的使用壓縮了DOM樹上的開銷;這有助於最大限度地減少捆綁包中 Chart.js 程式碼的大小,從而加快載入時間。 - **可存取性**:與大多數圖表庫相比,Chart.js 具有非常直接的方法,充分了解您所做的一切都在畫布上執行。您不需要複雜的自訂,因為它允許您使用其任何自訂選項來設定樣式、主題等。 - **出色的開發人員體驗**:除了擁有非常出色的社群影響力之外,Chart.js 還擁有簡單明了的文件,當出現新內容時,這些文件會經常更新。它還提供與您最喜歡的 JavaScript 框架的集成,例如 React、Svelte 等。 - **圖表響應能力**:預設情況下,Chart.js 提供響應式圖表。您可以自動將螢幕調整為不同的尺寸,並且它為圖表提供了可調整的尺寸。它確保您在所有裝置上都能獲得良好的資料視覺化效果。 ### 如何使用 Chart.js 👀 Chartjs 可以透過 npm 安裝或在執行時透過 CDN 直接下載: ``` <div> <canvas id="myChart"></canvas> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> const ctx = document.getElementById('myChart'); new Chart(ctx, { type: 'bar', data: { labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], datasets: [{ label: '# of Votes', data: [12, 19, 3, 5, 2, 3], borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: true } } } }); </script> ``` 如果你覺得這個專案很酷,你可以在GitHub上給它一個Star⭐️!他們目前的星數超過 63k。 **[GitHub 上的 Star Chart.js ⭐️](https://github.com/chartjs/Chart.js)** --- 4. Apache ECharts:用於快速建立圖表的JavaScript視覺化工具 ------------------------------------------ **網址: [https://echarts.apache.org](https://echarts.apache.org/)** ![https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2Fce12dq55x4le8e4ezhvm.png](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fce12dq55x4le8e4ezhvm.png) ECharts 是一個開源資料視覺化函式庫,最近越來越受歡迎。它由流行的[Apache](https://apache.org/)基金會建置,並依賴[ZRender](https://github.com/ecomfe/zrender)來呈現其圖形。與其他相比,它更複雜;它僅呈現動態資料並具有不同的顯示方式。 ![https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2Fnhnpwl5uuhhu7xxdp954.gif](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhnpwl5uuhhu7xxdp954.gif) ### ECharts的主要特點 - **廣泛的圖表類型**:ECharts 支援大量的圖表類型,實際上比大多數其他競爭對手更支援更多。其中包括長條圖、折線圖、圓餅圖、散佈圖、地圖、雷達圖、箱線圖、熱圖、平行座標、桑基圖等。這種多功能性允許用戶以多種格式視覺化資料。 - **互動性:** ECharts的突出特點之一是其豐富的互動性。它包括對互動式元素的內建支持,例如工具提示、縮放、平移和資料突出顯示。用戶可以與視覺化進行交互,以更深入地了解資料。 - **效能:** ECharts 專為高效能而設計,能夠有效處理大型資料集。它利用 Canvas 和 WebGL 進行渲染,這比傳統的基於 SVG 的渲染效能更高,適用於複雜的視覺化和大資料量。 ### 如何開始使用 Apache ECharts 👀 使用 npm 安裝 echarts: ``` npm install echarts ``` 以下程式碼片段在 id 為`#chart`的 DOM 元素中建立了一個簡單的長條圖: ``` // Import ECharts import * as echarts from 'echarts'; // Initialize the chart var chartDom = document.getElementById('chart'); var myChart = echarts.init(chartDom); var option; // Specify the chart configuration option = { title: { text: 'Simple Bar Chart' }, tooltip: {}, xAxis: { data: ['A', 'B', 'C', 'D', 'E', 'F'] }, yAxis: {}, series: [ { name: 'Value', type: 'bar', data: [5, 20, 36, 10, 10, 20] } ] }; // Use the specified chart configuration option && myChart.setOption(option); ``` 如果你覺得這個專案很有趣,可以在GitHub上給它一個Star⭐️,目前他們的Star數已經接近60k了! **[GitHub 上的 Star ECharts ⭐️](https://github.com/apache/echarts)** --- 5. Nivo:用於在 React 中建立圖表應用程式的庫 ----------------------------- **網址: [https://nivo.rocks](https://nivo.rocks/)** ![https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2F2k97ihdlfubm0zs5q1rm.png](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2k97ihdlfubm0zs5q1rm.png) Nivo 是一個高階開源 JavaScript 函式庫,用於建立資料視覺化,專門設計用於與 React 搭配使用。它建置在 D3 之上,提供廣泛的圖表類型,並具有內建主題、互動性和響應式設計。以下是一些關鍵功能和方面,使 Nivo 成為 React 應用程式中資料視覺化的熱門選擇: ### Nivo 的主要特點 - **易於使用:** Nivo 的設計比 D3.js 等替代方案更用戶友好且更易於使用。它提供了更高層次的抽象,使得無需深入了解 SVG 或 DOM 操作即可輕鬆建立複雜的圖表。 - **React 整合:** Nivo 專為 React 建置,使其成為在 React 生態系統中工作的開發人員的絕佳選擇。它利用 React 基於元件的架構來輕鬆整合和重複使用。 - **主題和響應性:** Nivo 包含對主題和響應式設計的內建支持,使您可以更輕鬆地建立在不同設備上看起來不錯並與應用程式的設計相匹配的圖表。 ### 如何開始使用 Nivo 👀 如果您是 React 開發人員,開始使用 Nivo 會很容易。安裝 nivo 核心套件以及您選擇的相關圖表特定庫。在本例中,我們正在實作一個長條圖: ``` yarn add @nivo/core @nivo/bar ``` 完成後,匯入相關圖表元件並在您的 React 環境中使用它: ``` import { Bar } from '@nivo/bar'; const MyBarChart = () => { const salesData = [ { "category": "Electronics", "value": 5000 }, { "category": "Clothing", "value": 3000 }, { "category": "Furniture", "value": 2500 } ]; return ( <Bar data={salesData} indexBy="category" maxValue={6000} keyBy="id"/> ); }; export default App; ``` Nivo 是開源的,您可以在 GitHub 上為他們的專案加註星標 - 目前它們的星標數量已超過 12k! **[⭐️ GitHub 上的 Star Nivo](https://github.com/plouc/nivo)** --- 6. Plotly:適用於不同技術堆疊的開源圖表庫 ------------------------- **網址: [https://plotly.com](https://plotly.com/)** ![https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2Fdxm6bnd8u9e4wxxjv3hh.png](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxm6bnd8u9e4wxxjv3hh.png) **Plotly**是一個開源資料視覺化函式庫,支援多種圖表類型和互動功能。它可用於多種程式語言,包括 Python、R 和 JavaScript。 Plotly.js 是該函式庫的 JavaScript 版本,建構在 D3 之上,廣泛用於建立基於 Web 的互動式視覺化。 ### Plotly 的主要特點 - **支援不同的程式語言**:Plotly 支援不同的語言,這與許多其他支援一種語言的圖表庫不同。它允許您使用任何您熟悉的語言將資料視覺化為圖表。這是[完整的清單](https://plotly.com/graphing-libraries/)。 - **複雜圖表類型:** Plotly 抽象化了 matplotlib、ggplot2 或 MATLAB 等軟體包中的統計和科學圖表類型。 - **可移植:** Plotly 圖表以 JSON 物件的形式進行聲明性描述。圖表的每個面向(例如顏色、網格線和圖例)都有一組對應的 JSON 屬性。這允許在所有不同的語言實作中使用相同的配置。 - **效能:** Plotly 的圖表主要使用 SVG,但它也可以利用 webGL 來渲染高效能視覺化。 ### 如何開始使用 Plotly 👀 如前所述,Plotly 可以與多種程式語言一起使用,但在本例中我們將專注於 Javascript。 首先,安裝相關的npm套件: ``` npm install plotly.js-dist ``` 然後,在 html 中建立一個空的 div 元素來繪製圖形: ``` <div id="tester" style="width:600px;height:250px;"></div> ``` 最後,編寫以下內容來繪製簡單的折線圖: ``` const TESTER = document.getElementById('tester'); Plotly.newPlot( TESTER, [{ x: [1, 2, 3, 4, 5], y: [1, 2, 4, 8, 16] }], { margin: { t: 0 } } ); ``` 如果您發現 Plotly 是一個很好的工具,您可以給它一顆星,並為他們在 GitHub 上的專案做出貢獻。 - **[GitHub 上的 Star Plotly Python 專案⭐️](https://github.com/plotly/plotly.py/)** --- 7.勝利:用於圖表和資料可視化的React元件 ----------------------- **網址: [https://commerce.nearform.com/open-source/victory](https://commerce.nearform.com/open-source/victory/)** ![https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3 .amazonaws.com%2Fuploads%2Farticles%2Fy1hhhtiq4cbkwnlzusin.png](https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1hhhtiq4cbkwnlzusin.png) **Victory**是一個適用於 React 和 React Native 的開源模組化圖表庫。它提供了一個簡單而優雅的 API,用於建立各種資料視覺化。與 Nivo 類似,Victory 利用了 React 的優勢,使其成為已經熟悉 React 生態系統的開發人員的自然選擇。 ### Victory JS 的主要特點 - **React 和 React Native 具有相同的 API** :Victory 專為 React 和 React Native 建置,允許無縫整合到 Web 和行動應用程式中。 - 易於使用:Victory 的聲明式、基於元件的 API 使得向 React 應用程式加入視覺化變得簡單,特別是與 D3 等其他命令式方法相比。 - **互動性**:Victory 提供開箱即用的工具提示、對事件和複雜動畫的支持,以使視覺化感覺更加生動。 ### 如何開始勝利 首先,安裝 npm 套件: ``` npm install victory ``` 然後,根據您的需求匯入您想要使用的相關元件。例如: ``` import React from 'react'; import { VictoryBar } from 'victory'; const data = [ {quarter: 1, earnings: 13000}, {quarter: 2, earnings: 16500}, {quarter: 3, earnings: 14250}, {quarter: 4, earnings: 19000} ] function App() { return ( <VictoryBar data={data} // data accessor for x values x="quarter" // data accessor for y values y="earnings" /> } ``` 如果您覺得 Victory 很酷,您可以繼續在 GitHub 上給該專案一顆星。目前他們的星數超過 10,000 **[GitHub 上的明星勝利 ⭐️](https://github.com/FormidableLabs/victory)** --- 結論 -- 恭喜您已經走到這一步了! 在本文中,我們介紹了今年要探索的 7 個圖表庫。我們已經超越了簡單的概述,而是發現了每個庫的工作原理、其底層架構以及用於建置它的技術。此外,我們還學習如何開始將這些庫合併到您的專案中。 在我們分道揚鑣之前,如果您認為本文有幫助,請考慮在[GitHub](https://github.com/latitude-dev/latitude)上給我們一顆星來表達您的支持。感謝您的閱讀,我期待您參與下一篇文章! 👋 --- 原文出處:https://dev.to/latitude/7-best-chart-libraries-for-developers-in-2024-25he

我建立了一個免費的開源專案管理器,可以幫助團隊將成本控制在每月 15 美元以下。

大家好,這裡是胡迪! 今天,我很高興與大家分享我的開源專案經理。我從頭開始建立此專案的目標是將營運成本保持在每月 15 美元以下。 在決定建造它之前,我嘗試過 Trello、Jira 和 Clickup。它們都是很棒的工具,但成本對我們來說是一個主要障礙。作為一家越南新創公司的 7 - 10 名成員的小團隊,我們根本沒有這些付費平台的預算。 您可能想知道為什麼我們不只使用免費套餐。事情是這樣的:我相信我可以建立一個專案管理器,提供我們所需的指定功能,例如報告、匯出功能、看板、日曆等。 此外,當時我有大量的空閒時間,這使得這是一個承擔這個專案的好機會。 我在 github 上開源了這個應用程式: <https://github.com/hudy9x/namviek>或您可以查看網站[namviek.com](https://namviek.com) 這是給誰的? ------ 這個專案非常適合具有開發技能、在有限的預算下運作一個小團隊的人,就像我一樣。 乍一看可能令人望而生畏,但請參閱下面的成本報告。我能夠將營運成本從每月 49 美元(7 美元 x 7 名會員)大幅降低到每月 10 美元以下。 ![亞馬遜成本](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/30fjxmx0fmmsuzc22cs7.png) 我是如何保持低成本的? ----------- 我利用各種免費平台來最大限度地降低營運成本。這是一個細分: - Vercel:用於前端(免費) - Aws Lightsail:用於後端(付費) - AWS S3:用於檔案儲存(付費) - Resend:發送電子郵件(免費) - Cloudflare:管理我的網域(免費) - Github Action:CD 自動化(免費) 我的技術堆疊 ------ 為了確保快速建置和部署,我在前端選擇了 Next.js,因為它與 Vercel 無縫整合。對於後端,我目前使用 Node.js,但我計劃在不久的將來將一些功能遷移到 Golang。 包含哪些功能? ------- 如前所述,該應用程式包含一些適合小型團隊的基本功能,例如: ### 清單顯示 一下子就看到了。在一個簡單的清單中確定任務的優先順序並管理您的任務。 ![清單顯示](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aj75jb3vu9gl3nsppdy0.png) ### 板視圖 可視化您的工作流程。在階段之間移動任務以進行清晰的進度追蹤。 ![板視圖](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8p40vkwmxhmvtsq8bj2y.png) ### 目標視圖 保持目標。一目了然地查看您的進度並慶祝里程碑。 ![目標視圖](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0uohpxfrshi5xwnhb1t.png) ### 日曆視圖 計劃你的日子。永遠不會錯過日曆上安排的任務的最後期限。 ![日曆視圖](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rsndq9r27qszq3mvwo03.png) ### 自訂視圖 按照你的方式工作。設計完美的視圖以滿足您的特定需求。 ![查看客製化](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zk24iwg5dzf43dgvg5t0.png) 如何使用它。 ------ 查看[設定指南](https://www.namviek.com/#download)。如果您在設定過程中遇到任何錯誤,您可以參考[此處的](https://docs.namviek.com/doc/installation)完整指南。 也許您更喜歡逐步影片指南?看看下面這個影片: https://www.youtube.com/embed/3CS0DB4\_2FU 貢獻您的功能或錯誤修復 ----------- 該應用程式仍在開發中,歡迎您為改進它做出貢獻!請隨意提交功能請求和錯誤修復。 想要建議更好的解決方案或程式碼庫重構嗎?只需建立一個拉取請求,我很樂意討論它。 結論 -- 最後,我希望這個開源專案可以幫助您和您的團隊降低營運成本,同時提供透過修復錯誤和建立功能來學習新技能的機會。它將永遠免費使用。 下一個開源應用程式見:D --- 原文出處:https://dev.to/hudy9x/i-built-a-free-open-source-project-manager-that-helps-teams-keep-costs-under-15month-3pmk

身為開發者,我的創業失敗、接案、以及自我成長經驗分享!

2020年,我剛關閉了之前的創業公司,厭倦了在專案公司的兼職工作。我曾經(現在仍然是)數位遊牧者並尋找遠距工作。 當時是新冠疫情之前,遠距工作並不像今天那麼重要。太多的開發人員(主要是自由工作者)尋找工作和一些職位。 我在那裡找不到工作,甚至連面試機會都沒有。憑藉我的技能,我知道我適合任何地方(我作為開發人員已經有 7 年多了。) ![拒絕](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hft38itzykdcozohfgs6.png) --- 做我自己的事 ------ 我創辦了另一家名為 Linvo 的新創公司,進展非常順利。我得到了客戶並賺了錢——但最終沒有成功。 那時候我每天都在共享辦公(早上9點到12點)簽失業金來拿政府的錢🙈 我在共享辦公空間的開放空間裡,所以我可以選擇與不同的創辦人進行個人聯繫——不是為了找工作,而是談論幾乎所有的事情。 但隨著談話的繼續,人們了解了我的技能。 ![你了解我](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rhaunmgwvor6o0zy7ina.gif) --- 在共享辦公空間閒逛 --------- 我想謙虛一些,但幾乎所有在開放空間工作的新創公司都向我提供了工作機會,完全遠程,幾乎可以以我想要的任何期限工作。就這樣,我開始在[Novu](https://novu.co/)工作了整整兩年。 ![我](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6as772lphqfoo7a9q7j.png) 現在,很明顯,當你與人建立個人聯繫時,找到工作會更容易(這就是新創公司參加活動來銷售他們的產品的原因)。但我想更深入地了解我是如何從 0 到 100 的。 我之前寫過一篇文章,內容是[為開源做出貢獻將使你找到新工作的機會增加 10 倍](https://dev.to/github20k/contributing-to-open-source-will-10x-your-chances-to-land-a-new-job-433f) 我堅持這一點。但還有更多。 生活中的一切都與風險有關 - 您越信任,有人僱用您/使用您的服務/向您購買軟體的機會就越大。 但信任是很難的。 當你編寫程式碼時如何才能獲得信任? --- 我所說的與我所是的 --------- 每當我尋找自由工作者(例如前端開發人員)時,我無法確定是否: - 他們有著極佳的個人契合度 - 他們實際上可以寫出好的程式碼 - 他們可以跳出框框思考。 因為我只能從他們那裡得到一些關於他們自己的話語。 作為一名企業家,我已將我的工作從開發人員轉移到開發人員成長(成長駭客),因為我認為這對企業的發展至關重要。 在 Novu 的第二年,我決定需要建立自己的知識庫,以便人們能夠了解有關我的一切資訊 - 贏得他們的信任並向他們展示我的個性。 因此,我建立了[Gitroom 電子報](https://gitroom.com)和[YouTube 頻道](https://www.youtube.com/@nevo-david),以便人們可以看到我的行銷技能,也建立了我的[Gitroom 開源專案](https://github.com/gitroomhq/gitroom/),以便他們可以看到我的開發技能。 我非常穩定(每天都出現)——目前,時事通訊已連續 46 週(幾乎一年)。 ![條紋](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8thomejgye2j11dm1a8q.png) 並分享有價值的資訊—這是至關重要的: - 我不教簡單的程式碼,例如演算法 - 我不教 CSS 和 HTML 我主要注重以資歷為基礎來獲得他們的信任。 今天,我有太多的客戶 - 我拒絕了很多工作,直到我學會瞭如何擴展或獲得一些缺失的技能。 --- 做這個 --- 由於閱讀本文的大多數人都是純粹的開發人員(而不是行銷人員/成長駭客),因此我會提出一些建議。 1. **為開源做出貢獻**——展示你的技能的最佳方式。沒有什麼比對大型程式碼庫的開源貢獻更重要的了,這是人們需要的大部分證據。 2. **擴大你的貢獻**-不是每個人都知道你的貢獻;在所有可能的社交媒體(X、Linkedin、Youtube、Daily.dev)上談論它,讓人們了解您所做的事情。 **專業提示:**標記您貢獻程式碼的公司;他們可能會重新發布您。 3. **想想你的受眾**- 我看到太多的「影響者」專注於初級開發人員,例如(你必須知道的10 個CSS 技巧和10 個HTML 標籤),雖然這會大大增加你的受眾規模,因為有更多的初級開發人員在世界上比前輩。你會建立錯誤的受眾。作為一名大三學生,你將與許多開源創始人一起打上自己的烙印。即使對於開發相關職位來說,這也可能是錯誤的,因為你建立的受眾永遠不會付錢。 ![做這個](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3h1py1um97u0w3l3xlq.png) --- 吉特魯姆 ---- 我將注入一些可以幫助你的自我推銷:) [Gitroom](https://github.com/gitroomhq/gitroom)是一個用於社群媒體排程的開源工具。 向 Gitroom 做出貢獻可以實現我討論的兩點。 1. 為大型程式碼庫做出貢獻 2. 透過安排社交媒體貼文來擴大您的貢獻。 但還有第三個,我想你會喜歡的。 Gitroom 是最大的開源創辦人社群;你實際上會和他們一起出去玩,他們不斷在世界各地尋找遠端員工。 這是獲得內部信任的好方法。 貢獻後,加入我們的 Discord 頻道。 所有開源創始人都在那裡。 ***如果可以的話請給 Gitroom 星標*** --- 糖霜 -- 本文不會為你粉飾它。 如果你想被錄用,你需要表現出色。 這不是一個「欺騙」人們僱用你的快速計劃。 它只是擴大您的知識和技能的工具。 如果您不能為大型程式碼庫做出貢獻,就不要指望被雇用。 這是我在上一篇文章的一段對話: ![程式碼庫](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hksdy5v7k8qpgbwo0f8x.png) 如果你還不夠好,那就努力提升你的技能。 當涉及到實際工作時,沒有任何魔術。 --- 原文出處:https://dev.to/github20k/i-am-suitable-for-the-job-but-unsure-why-i-cant-get-it-5eg4

在 Twill CMS 模組內,新增自訂欄位

已經可以在後台管理資料、也可以在前台顯示頁面了 接下來我想知道:如何替模組新增欄位呢?這是 CMS 的核心功能 目前的 pages 模組,編輯的後台有 title 與 description 兩個欄位(都是用 `<input type="text" />` 管理) 在 `resources/views/site/page.blade.php` 也可以輕易取得這兩個欄位的值 ``` {{ $item->title }} <br /> {{ $item->description }} ``` 這兩個值實際存在資料庫的哪裡呢? 會發現並不在 `pages` table 內,而是出現在 `page_translations` table 內 (我猜測,如果沒開啟多語功能,應該就是出現在 `pages` table 內了?) 除此之外,也會在 `page_revisions` 的 payload 看到這兩個欄位的值,但這應該是「歷史修改紀錄」 類似 log 的功能,主要是以 `page_translations` 欄位為主吧! 值得一提的是,title 與 description 是原生的預設欄位 上次輸入 `php artisan twill:make:module pages` 指令時,就自動在 migration 內出現這兩行了 ``` $table->string('title', 200)->nullable(); $table->text('description')->nullable(); ``` 這個設計顯然是 seo 考量,大家有把握的話,migration 內容隨意修改,我認為無所謂。 --- 假設我今天想要擴充這個模組,讓每個頁面下方可以顯示一段「備註」 我想增加 `notes` 欄位,並且希望在後台使用 `<textarea><textarea/>` 管理,該怎麼做呢? --- 首先,打開 Twill/PageController 檔案 會看到 getForm 那邊有 description 的定義 我直接這樣加一段試試看 ``` $form->add( Input::make()->name('notes')->label('Notes')->type('textarea')->translatable() ); ``` 參考資料:https://twillcms.com/docs/form-fields/input.html --- 打開後台看看,會看到真的出現了 Notes 欄位的文字區塊!這非常方便 目前我們還沒新增 migration 檔案,所以實際上資料庫存不了這欄位 但就硬著頭皮按下 Update 看看吧? 結果居然跳出 `Content saved. All good!` 查看資料庫,會看到 `page_revisions` 的 payload 有出現 notes 但我更新 page.blade.php ``` {{ $item->title }} <br /> {{ $item->description }} <br /> {{ $item->notes }} ``` 根本就沒有內容。所以這邊的設計有點小奇怪,按下 Update 應該跳出 error 比較好。 但是沒關係 瑕不掩瑜 --- 來正式修改資料表吧 ``` php artisan make:migration add_notes_to_pages_module ``` 內容就放 ``` public function up(): void { Schema::table('page_translations', function (Blueprint $table) { $table->text('notes')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('page_translations', function (Blueprint $table) { $table->dropColumn('notes'); }); } ``` 然後打開 Models/Page.php 在 `$fillable` 跟 `$translatedAttributes` 陣列加入 'notes' (我猜測,根據開啟多語功能與否,這兩個陣列其實擇一修改即可?沒關係先硬上) 這樣就大功告成囉! 打開網址 http://twill-play.local/pages/my-1st 會看到新的欄位正確顯示! 這次的 commit 內容可參考 https://github.com/howtomakeaturn/twill-play/commit/fef0e19a0e5d2ecaf3e87da683fb9690bda34976 --- 順帶一提,官方文件 https://twillcms.com/docs/form-fields/input.html 提到新增欄位是寫 ``` Schema::table('articles', function (Blueprint $table) { ... $table->string('subtitle', 100)->nullable(); ... }); // OR Schema::table('article_translations', function (Blueprint $table) { ... $table->string('subtitle', 250)->nullable(); ... }); ``` 注意那個 OR 這邊應該是看有否開啟多語設定 也就是只要更新一張 table 即可 --- ## 簡評 這流程真的非常棒,包含 wordpress 在內的許多 CMS,在新增欄位的時候,程式碼本身不需修改 欄位定義會出現在 database 內。雖然方便,但是後續很難以維護、擴充 反觀上述 twill 流程,幾乎就是平常 laravel 工程師的工作流程而已 後續就算交給一個只熟 laravel 而完全不會 twill 的人也沒關係,他可以自行在 `page.blade` 使用模組的資料 自由地開發他想要的頁面與樣式!

JavaScript 安全性:保護前端安全的簡單實踐

我不了解你,但我的職業生涯始於在小型機構擔任前端開發人員,那裡沒有人關心安全性。當我轉而在更大的公司從事更大的專案時,我一直不關心安全性,因為沒有人更好地教我,**這給我帶來了麻煩**。 了解如何保護您的 JavaScript 程式碼可以改變這種狀況,並幫助我們保護我們的應用程式和使用者。 --- 本文將探討一些不會傷害 JavaScript 開發人員的安全實踐,只要它們有意義,就可以實施。 --- **上面的一些主題是我在研究該主題時學到的,但是還有更多方法可以使您的程式碼安全。我只是分享一些簡單的方法來幫助您入門。** \*PS 是的,我向人工智慧提出了問題,並要求它幫助我舉例。 PS2 是的,IA 建立了封面圖片,因為我知道自己的弱點 LOL\* --- 1. 保持你的依賴項是最新的 -------------- 過時的庫可能會使您的應用程式面臨安全漏洞。保持所有內容都是最新的可以幫助您避免已經修復的已知問題。 - 使用套件管理器: **npm(節點套件管理器)**是一個很棒的工具,可以幫助您管理和更新庫。 - 定期檢查:執行 npm outdated 以查看哪些軟體包已過時。 - 定期更新:使用 npm update 將軟體套件升級到最新版本。 ``` - Automate Security Updates: Tools like npm audit identify and suggest fixes for security vulnerabilities. ``` --- {% cta https://github.com/webcrumbs-community/webcrumbs %} ⭐ 您可以考慮在 GitHub 上給我們一個 Star 嗎? {% 結束%} --- 2.使用簡單的安全標頭 ----------- 安全標頭告訴瀏覽器在處理網站內容時的行為方式,這有助於防止某些類型的攻擊,例如跨網站腳本和資料注入。 我們可以使用**內容安全策略 (CSP)** ,這是一種安全標頭,有助於阻止未經授權的腳本在您的網站上執行,從而防止許多攻擊。 從簡單開始:新增一個基本的 CSP 標頭,僅允許來自您網站的腳本。 ``` <!-- Add to the <head> section of your HTML --> <meta http-equiv="Content-Security-Policy" content="script-src 'self';"> ``` 此行意味著只能執行屬於您網站的腳本,而不能執行其他地方的腳本。 --- 3. 清理使用者輸入 ---------- 如果處理不當,用戶輸入可能會很危險。惡意使用者可能會嘗試輸入可能損害其他使用者或您的網站的資料。 **我們應該始終將輸入視為不可信的**,清理來自用戶的資料以確保其安全,然後再在應用程式中使用它。 當使用使用者輸入更新網頁時,請使用textContent 而不是innerHTML 以避免執行有害腳本。 ``` const userInput = document.querySelector('#user-input').value; document.getElementById('output').textContent = userInput; // Safely add user content to your page ``` --- 現在我們更安全了朋友們… ------------ 這三個步驟是保護 JavaScript 應用程式的一個很好的起點。 我希望您今天能花點時間回顧一下您的 JavaScript 專案。檢查是否有過時的庫,確保您使用安全標頭,並驗證所有使用者輸入是否已清理。 小步驟可以對您的 Web 應用程式的安全性產生很大影響。 說到前端... ------- 我們正在建立這個超酷的專案,它將改變您進行 Web 開發的方式😯 {% cta https://github.com/webcrumbs-community/webcrumbs %} ⭐ 您可以考慮在 GitHub 上給我們一個 Star 嗎? {% 結束%} **謝謝閱讀,** 帕奇💚 --- 原文出處:https://dev.to/buildwebcrumbs/javascript-security-simple-practices-to-secure-your-frontend-18ii

2024 年開發人員的副業想法

您是一名軟體工程師,渴望將自己的技能轉化為有利可圖的副業嗎? 網上賺錢的可能性是無限的,我有一些令人興奮的想法,可以讓 2024 年成為您迄今為止最偉大的一年。無論您是在尋找額外收入還是夢想創辦自己的企業,這些副業都旨在讓您充滿動力並提高技能,從而有可能增加您的收入。讓我們深入了解一下吧! 銷售數位產品和插件 --------- 根據 Statista 預測,到 2024 年,數位商務市場的交易額預計將達到 7.63 兆美元。這是您透過建立 Shopify 或 WordPress 外掛程式等數位資產來分得一杯羹的機會。 為什麼不使用您最喜歡的技術堆疊建立可重複使用的網站模板並在[Gumroad](https://gumroad.com/)或[Envato](https://themeforest.net/)等平台上出售它們?我將從在 Gumroad 上銷售網站範本開始,我讀過並發現它可以是一項高利潤的企業。 ![在線銷售數位產品](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zxf601pjbuq7i93ndab.jpg) App Store / Play 商店應用程式開發 ------------------------- 行動應用程式開發仍然蓬勃發展。截至 2023 年,Google Play 商店擁有約 371.8 萬個行動應用程式,Apple App Store 提供約 180.3 萬個 iPhone 應用程式。使用 React Native、Flutter 或 Ionic 等跨平台工具和框架,您無需學習 Java/Kotlin 或 Swift 等原生語言即可開發應用程式。 透過廣告、應用程式內購買或提供具有額外功能的高級無廣告版本,透過您的應用程式獲利。行動應用市場是一座金礦,等待著您的創新想法。 ![行動應用程式開發](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4up3n87qtm39m6txjyjd.png) SaaS 或微型 SaaS 產品 ---------------- 建立專門的、利基的 SaaS(軟體即服務)產品可以獲得令人難以置信的利潤。微型 SaaS 產品通常由獨立開發人員或小型團隊開發,專注於非常特定的市場或功能。 從 Raycast 中汲取靈感,Raycast 是一款生產力工具,可透過快速存取和自訂腳本簡化日常任務和工作流程。這個小團隊的基於訂閱的模式取得了巨大的成功。您獨特的 Micro-SaaS 產品可能會成為下一件大事! ![SaaS 或微型 SaaS 產品](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8u7h6b1ab9htrl6a5is1.png) 開源專案貢獻 ------ 為開源專案做出貢獻是展示您的技能、與其他開發人員合作以及建立聲譽的絕佳方式。這些貢獻可以帶來工作機會、諮詢工作或銷售自己的工具和服務的機會。 如果您啟動了一個獲得關注的開源專案,您可以透過贊助、捐贈或雙重許可來貨幣化它,提供免費社區版本和帶有附加功能或支援的付費商業版本。 ![開源](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p7lf8j3udkqvo2ovhlkq.png) 7. 科技博客 ------- 技術部落格是分享專業知識、回顧新技術和提供教學的有效方式。透過廣告、聯盟行銷、贊助內容或銷售電子書或課程等數位產品,最初的愛好可以成為一項利潤豐厚的職業。 建立一個利基市場,無論是網頁開發、人工智慧趨勢或小工具評論。透過提供有價值、準確且引人入勝的內容來擴大受眾群體。作為部落客,強大的個人品牌可以帶來演講、書籍交易和諮詢工作。 準備好將您的技能轉化為更多東西了嗎?這些副業想法是您通往美好 2024 年的門票。 ![科技部落格](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pbmsmhgnh5qe8ph8urfg.png) 客製化人工智慧解決方案 ----------- 人工智慧不僅僅是一個流行詞;這是一個蓬勃發展的市場。 2023 年,人工智慧的估值將超過 1,536 億美元,而且規模只會越來越大。每週都有新的人工智慧工具上市,為開發人員提供了無限的機會。 想像一下,使用[GPT](https://openai.com/index/gpt-4/) 、 [Llama](https://llama.meta.com/)或[PaLM 2](https://ai.google/discover/palm2/)等大型語言模型 (LLM) 來建立一個像 AgentGPT 這樣的人工智慧工具。這些工具將使用者定義的目標分解為可操作的任務並按順序執行它們。設計一個使用者友善的介面,讓使用者與人工智慧互動、定義目標、監控進度和接收輸出。透過訂閱模式將您的創作貨幣化,並隨著企業和個人為您節省時間的解決方案付費而利潤滾滾而來。 ![人工智慧驅動的解決方案](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qjlj7r1hmxdwh8dqfue3.png) 透過探索這些副業想法和其他想法,您可以發現有效利用您的技能並賺取可獲利收入的新方法。 請隨意點擊下面的連結來查看我的開源專案等。 \*\* [travislord.xyz](https://travislord.xyz/) [github.com/lilxyzz](https://github.com/lilxyzz) \*\* --- 原文出處:https://dev.to/lilxyzz/side-hustle-ideas-for-developers-in-2024-jh5

使用 Twill CMS 模組建立前台頁面

已經在後台建立資料了,我想要立刻做出前台頁面看看 所以官方教材我跳到 https://twillcms.com/guides/page-builder-with-blade/building-a-front-end.html 建立前台控制器 ``` php artisan make:controller PageDisplayController ``` 注意這是 laravel 原生指令喔 跟 twill 無關 在裡面放入 ``` <?php namespace App\Http\Controllers; use App\Repositories\PageRepository; use Illuminate\Contracts\View\View; class PageDisplayController extends Controller { public function show(string $slug, PageRepository $pageRepository): View { $page = $pageRepository->forSlug($slug); if (! $page) { abort(404); } return view('site.page', ['item' => $page]); } } ``` 然後在 routes/web.php 放入 ``` Route::get('pages/{slug}', [\App\Http\Controllers\PageDisplayController::class, 'show'])->name('frontend.page'); ``` 這時打開網址 http://twill-play.local/pages/my-1st 會看到顯示一個陽春的網頁了! 算是成功建立前台! 開發體驗也很好,基本上就是開發 laravel app 的感覺,只是用了 twill 核心在輔助! 而不是在開發 twill app,感覺好像在學一套新框架的感覺! --- 打開 twill 後台 會看到後台顯示網址依然是 http://twill-play.local/en/pages/my-1st 來把 i18n 先關掉吧 可以在 PageController 加入 ``` protected function setUpController(): void { $this->withoutLanguageInPermalink(); } ``` 即可修正這個問題! 這次的 commit 內容在這邊,可以看看 https://github.com/howtomakeaturn/twill-play/commit/989e5e357439e53092130dc2a4eed7befaa6c550 真的感覺就像在開發普通的 laravel app! --- 如果不希望前台網址有 `/pages/` 這樣的字串 可以在 routes/web.php 直接拿掉 後台的部份,可以在 PageController 加入 ``` $this->setPermalinkBase(''); ``` 來修正顯示網址的問題 真的很酷!

首次嘗試新增 Twill CMS 模組

繼續跑官方教材 https://twillcms.com/guides/page-builder-with-blade/creating-the-page-module.html 執行指令 ``` php artisan twill:make:module pages ``` 會建立 pages 模組 對應的檔案變化可以在這查看 https://github.com/howtomakeaturn/twill-play/commit/d18bd06d566b135353d4230ca8a97efbddaded6f 建立了很多檔案到 app 底下,可見背後的哲學是: > 接下來就當成是一般的 laravel app,自由開發吧! > 只是在建立 app 的時候 可以使用許多 twill 功能輔助開發! --- 然後新增的資料表如下 ``` pages page_revisions page_slugs page_translations ``` 通通都沒有 twill_ 這樣的 prefix,所以「模組」應該視為「專屬於你 app 的內容」 跟前面的「檔案都直接在 app 底下」相呼應 滿合理的設計! 那麼我可以在那個 migration 檔案 `database/migrations/2024_05_22_013232_create_pages_tables.php` 內新增我自己想加的欄位嗎? > This file will create the minimum required tables and columns that Twill uses to provide the CMS functionality. Later in the guide we may add some more fields to the database, but will will do that in a new migration. > Once you are more experienced with Twill, you may want to add fields at this moment, before you run the migrate command. That way, you do not have to immediately add a new migration file. 也就是說 官方歡迎你擴充這幾張 table 然後要新增一筆 migration 或者直接在這修改 都可以! --- 直接打開後台面板 並不會看到 pages 模組,twill 不會自動偵測你建立的模組 要在 `AppServiceProvider` 手動登記 ``` TwillNavigation::addLink( NavigationLink::make()->forModule('pages') ); ``` 接著,就可以在後台建立第一筆資料囉! 建好之後,會發現在四個資料表內,各自多了一筆資料 ``` pages page_revisions page_slugs page_translations ``` --- 我剛建了代號 `my-1st` 的資料,後台顯示一個網址 `http://twill-play.local/en/pages/my-1st` 打開會發現根本沒有頁面! 這表示 twill 目前主要是處理 CMS 與後台面板的東西 沒有前台頁面 那個要另外做! 所以 `app/Http/Controllers/Twill/PageController.php` 檔案是代表後台的模組管理 controller 然後 `routes/twill.php` 裡面登記的 ``` TwillRoutes::module('pages'); ``` 也是代表登記後台的模組管理相關 routes 所以是要你自己在 `routes/web.php` 處理你的前台 routes 吧! 其實,我覺得這樣的設計,真的很清楚很漂亮!只是對新手來說,會覺得工程較複雜、檔案很分散吧! 接著就來建前台頁面吧!

首次嘗試安裝 Twill CMS

在開始研究模組之前 先來安裝 twill 官方有一份簡易教材 https://twillcms.com/guides/page-builder-with-blade/index.html 安裝 twill 可以分成三步驟: - 安裝 laravel - 安裝 twill 套件 - 跑 twill 初始指令 我開了一個 githun repo 可以在前三個 commits 分別看到對應的檔案變化 https://github.com/howtomakeaturn/twill-play/commits/main/ --- 在本機裝好之後 twill admin 面板看到的是 紀錄 `All activity` `My activity` 的面板首頁 以及 `Media Library` 功能 僅此而已 可以說是非常乾淨 也就是在新增模組之前 admin 面板可說是啥都沒有 很好的極簡哲學 資料庫方面 初始會出現的資料表如下 ``` activity_log app_settings failed_jobs migrations password_reset_tokens personal_access_tokens twill_blocks twill_features twill_fileables twill_files twill_mediables twill_medias twill_password_resets twill_related twill_settings twill_setting_translations twill_tagged twill_tags twill_users users ``` 可以看到 twill 開頭的資料表 都是 twill 提供的 cms 功能 其餘都是 laravel 原生提供的功能 這邊我有些不懂的是 activity_log 與 app_settings 也是 twill 提供的 怎麼不加上 twill 開頭呢? 沒關係,瑕不掩瑜! 新增的檔案可以在這邊看到 https://github.com/howtomakeaturn/twill-play/commit/60d420d283aaa37e96ee29c72077292261b1383b 我認為切分得非常漂亮:屬於 twill 的都有獨立路徑 屬於你 app 的就用 laravel 慣例路徑 這樣在替客戶開發網站的時候 非常放心 客戶的 domain 與 twill 的 domain 不會混在一起! 接著來 看看怎麼新增模組吧!

  近期留言