該貼文系列已在 NgateSystems.com 上建立索引。您還可以在那裡找到超級有用的關鍵字搜尋工具。
最後評論:24 年 11 月
一、簡介
大多數網路應用程式的存在純粹是為了創建和存取共享資訊。考慮一下亞馬遜的 https://www.amazon.co.uk/ 網站。該系統的基本目的是讓您瀏覽產品詳細資訊的集中集合、下訂單並監控交付進度。為了實現這一目標,亞馬遜必須:
- 將此資訊保存在可透過網路存取的地方
- 建置和管理它以確保近乎即時的存取和完全完整性。
這篇文章是關於用於實現這些目標的「資料庫」技術。
警告 - 這是一篇長帖子,因為 Svelte 中的資料庫讀寫會無情地吸引您使用 SvelteKit 的客戶端-伺服器架構。以前,您的程式碼僅在 Web 瀏覽器中「客戶端」運行。現在,您還將在由 npm run dev 啟動的本機伺服器上執行程式碼。這會產生後果...
我已經研究過分割貼文的方法,但它們不起作用。更糟的是,您將使用的 Javascript 包含許多新功能。所以,我很抱歉 - 你只能忍耐了。
但也要往好的方面看。一旦你經歷了這一切,事情就會開始變得更容易。慢慢來。如果您覺得我沒有解釋清楚,請使用 chatGPT。當您需要有關 JavaScript 語法的建議時,您會發現該機器人特別有用。放鬆。這會很有趣!
2. 設定您的專案以使用 Google 的 Firestore
在網路上儲存共享資料的方法有無數種。本系列文章使用 Google 的 Firestore 系統,因為它適合初學者。它需要最少的設置,並且非常適合 Svelte Web 應用程式的結構。
您需要執行四個初步步驟:
- 取得 Google 帳戶
- 在此帳戶下建立 Firebase 專案
- 註冊您的「網頁應用程式」
- 為您的 Firebase 專案初始化 Firestore 資料庫
Firebase 是 Google 的總稱,涵蓋了許多不同的服務,您可以使用這些服務在網路上安裝簡單的項目。給定帳戶的服務透過 Google 的「Firebase 控制台」(網址為 https://console.firebase.google.com/)進行管理。它們包括允許您將檔案上傳到 Google Cloud 的「儲存」服務和「Firestore 資料庫」服務。資料庫與文件的不同之處在於它具有可配置的結構。它使您能夠存取和更新已配置資料集的離散元素。
2.1 取得Google帳戶
如果您有 Gmail 位址,那麼您就已經受到保護,因為這會自動算是 Google 帳戶。如果沒有,請按照建立 Google 帳戶中的說明取得一個。
2.2 為您的程式碼建立 Firebase 項目
啟動 Google Firebase 控制台並使用您的 Google 帳戶登入(請注意,如果您使用此帳戶登入 Gmail,則您也已經登入 Firebase 控制台)。現在點擊“建立專案”框來啟動該過程。
Google 會要求您為您的專案提供一個名稱(我建議您使用您在 VSCode 中使用的專案名稱),並會提出一個擴展,使其成為 Firebase 世界中唯一的「專案識別碼」。例如,本系列文章中使用的我的版本的「Svelte-dev」項目在 Google 中稱為「Svelte-dev-afbaf」。
順便說一句,由於專案識別碼最終將構成您的網路應用程式的預設即時URL 的一部分,並且由於Google 允許您編輯其最初的「唯一性擴展」提案,因此您可能會嘗試更改此設定去做一些有意義的事情。不過,我建議你忘記這個想法。首先,您會發現很難選擇適合雙方的識別碼。其次,根據我的經驗,這些「預設網址」從未被 Google 索引過。以最低成本購買並在上線時連結到預設 URL 的「自訂 URL」是迄今為止獲得令人難忘的 URL 的最佳方式。
現在點選「繼續」即可顯示「Google Analytics」註冊頁面。您可以在此處安全地忽略它,因為它僅與即時應用程式的效能問題相關。使用滑桿拒絕它,然後點擊“建立專案”按鈕繼續。
當 Google 註冊您的專案時,燈光現在變暗了一點。最後,一旦您再點擊一個「繼續」按鈕,您就會發現自己位於專案的 Firebase 控制台視窗中。以下是「svelte-dev」專案的 Firestore 標籤的螢幕截圖:
值得給自己一點時間來熟悉這個頁面,因為它有點複雜。基本結構由左側的「工具選單」組成,它決定右側主面板中顯示的內容。問題在於選單是「自適應」的,並維護一個「專案快捷方式」部分來記住您去過的地方。因此,每次打開控制台時,選單看起來都不同!然而,一旦掌握了這個功能,事情就會進展順利。請注意,完整的工具集隱藏在其父「產品類別」選單項目的「建置」、「運行」和「分析」子選單中。 「建造」套裝包含您目前所需的一切。
在繼續操作之前,請注意以下事項:
- 螢幕頂部的資訊確認 svelte-test 專案目前已在「Spark」計劃中註冊。這意味著您目前所做的一切都是免費的。最終,在本系列文章中,您將需要開始向 Google 付費,並且需要將您的專案升級到「Blaze」費率。但不用擔心 - 這還有很長的路要走,您不需要支付太多費用,並且您可以建立每月預算來限制 Google 可能向您收取的費用。
- 點擊工具列頂部的「項目概述」按鈕即可顯示項目詳細資訊。此處提供的詳細資訊包括項目標識符的提醒和刪除項目的按鈕。如果一切都出了問題,你總是可以用它來消除混亂並重新開始。這不會花費您任何費用
2.3 註冊您的網路應用程式
Firebase 需要知道您的網路應用程式的名稱:
- 點擊> 「開始」訊息下方的圖標,並根據要求提供暱稱。我建議您在這裡再次使用您的專案名稱(例如“svelte-dev”)。
- 忽略「為此應用程式設定 Firebase 託管」的提示,因為當我們最終進行部署時,您的所有託管需求都將由 App Engine 處理。
- 最後,點選「註冊」和「繼續控制台」返回初始控制台畫面。
2.4 - 初始化 Firestore 資料庫
從工具選單的「Build」堆疊中選擇「Firestore Database」以獲得如下所示的 Firebase 控制台視圖:
點擊「建立資料庫」按鈕後,控制台將要求您:
設定您的資料庫「名稱和位置」。 「名稱」是資料庫的標識符,僅當您計劃在專案中建立多個不同的資料庫時才相關。現在將其留空,以便 Google 使用其「預設」設定。 “位置”指定資料庫的實體位置。此處提供的選項下拉清單可能是您對 Google Cloud 服務規模的第一印象。其伺服器場遍布全球。您可能需要選擇靠近您所在位置的伺服器。例如,我通常使用“europe-west2 : Heathro”,因為我住在英國。 Google Cloud 控制台中其他頁面可讓您指定效能和可用性特徵,但您現在不需要查看這些。
使用「規則」來保護您的資料庫。這裡的畫面為您提供了設定初始「生產」和「測試」「規則」之間的選擇。當然,這只有在你首先知道「規則」是什麼的情況下才有意義——而現在不是我解釋它們的合適時機。除非您更了解,否則我希望您檢查此處的“測試模式”選項。請放心,稍後當我談論“授權”時我會回到這個話題(天哪,還有很多東西要談!)。
完成這兩個階段後,Cloud Firestore 頁面將會在 Firebase 控制台中開啟。現在怎麼辦?
3. 使用 Firestore 資料庫
本節旨在回答以下問題:
- 什麼是資料庫?
- Firestore 資料庫是什麼樣的?
- 如何在 Firestore 控制台中初始化資料庫?
- 如何使用 Javascript 存取 Firestore 資料庫?
- 如何取得 Svelte page.svelte 檔案來從 Firestore 資料庫載入資料?
- 如何取得 Svelte page.svelte 檔案以將資料新增至 Firestore 資料庫?
3.1 什麼是資料庫?
就我們的直接目的而言,資料庫是一組表,其中包含命名資料「欄位」的值行。因此,例如,「客戶訂單」資料庫可能包含
- 包含「客戶 ID」和「客戶地址詳細資料」欄位值的「客戶」表
- 包含「產品編號」和「產品詳細資料」欄位的「產品」表格
- 「客戶訂單」表,其中包含「客戶 ID」所下的「產品編號」訂單的詳細資訊
重要的是這樣的安排結構化資料內容的命名和格式具有一致的標準
3.2 Firestore 資料庫是什麼樣的?
在 Firestore 中,表格稱為“集合”,其中的行稱為“文件”。集合中儲存的文件並不都需要具有相同的字段,但字段名稱和內容應在整個集合中遵循一致的模式。
Firestore 文件的一個重要特徵是它應該有一個唯一的識別碼或「密鑰」。有時,每個文件中都會有一個字段,例如“電子郵件地址”,您可以使用它來提供“自然”唯一密鑰。如果沒有,Firestore 可能會被要求自動建立一個人工金鑰。
資料庫設計可能是系統開發中最具挑戰性的部分,我將再次迴避這一點,因為只有當您擁有一些實務經驗時,所涉及的問題才會變得清晰。不過,如果您有時間,您會發現查看 Cloud Firestore 資料模型頁面很有用。
3.3 如何在 Firestore 控制台中初始化資料庫?
在這篇文章中,我打算向您展示如何在預設 Firestore 資料庫中建立單一產品集合。這將包含簡單的文檔,其中包含產品編號欄位以及 Firestore 自動產生的金鑰。
在 Firebase 控制台的 Firestore 頁面上,按一下「開始收集」按鈕,然後在現在出現的彈出視窗的「集合 ID」欄位中輸入名稱「產品」。
現在使用資料輸入頁面建立一個測試產品文檔,其中包含數值為「1」的「productNumber」欄位和文字值為「Product 1」的「productDetails」欄位。
- 在“Field”輸入框中輸入“productNumber”設定欄位名稱,將“Type”方塊設為“number”,並在“Value”方塊中輸入“1”(不含引號字元)。
- 點擊“新增欄位”,在“欄位”輸入框中輸入“productDetails”設定欄位名稱,將“類型”方塊保留預設的“字串”設置,然後輸入“產品1”(不含引號字符) )在「值」框中 。
現在,先點擊「自動 ID」按鈕,然後「儲存」來簽署文檔,控制台現在應如下所示:
如果您想添加更多文檔,此時您可以單擊“添加文檔”,但在本例中沒有必要 - 您只需要一個文檔來演示您的 Web 應用程式讀取它的能力。
您現在已經完成了,但請注意,控制台的「面板視圖」可讓您編輯或刪除剛剛建立的文件。如果您的情況一團糟,您甚至可以刪除整個集合並重新開始。
3.4 如何使用 Javascript 存取 Firestore 資料庫?
事情開始變得真的有趣了!
Google 提供了一個 Javascript 函式庫,可讓您讀取和寫入 Firestore 文件。此類庫稱為“API”(應用程式介面)。看看下面的程式碼,它顯示瞭如何使用 firebase/firestore 庫來讀取 svelte-dev 產品集合中的所有文件:
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: "AIzaSyCE933 ... klfhFdwQg1IF1pWaR1iE", authDomain: "svelte-dev-afbaf.firebaseapp.com", projectId: "svelte-dev-afbaf", storageBucket: "svelte-devt-afbaf.appspot.com", messagingSenderId: "1027 ... 85697", appId: "1:1027546585697:web:27002bf ..... b0f088e820", }; const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp); const productsCollRef = collection(db, "products"); const productsQuery = query(productsCollRef, orderBy("productNumber", "asc")); const productsSnapshot = await getDocs(productsQuery); let currentProducts = []; productsSnapshot.forEach((product) => { currentProducts.push({productNumber: product.data().productNumber}); }); return { products: currentProducts } // accessed in +page.svelte as data.products
專注於以 const productsCollRef = collection(db, "products"); 開頭的部分。這使用 Firestore API 呼叫將產品集合中所有文件的排序副本載入到 State currentProducts 變數中。
首先,從 Firestore 用戶端 API 程式庫中提取的集合和查詢函數用於將 Firebase 指向產品集合並定義要在其上執行的查詢。然後透過 getDocs API 呼叫啟動查詢。
我不會嘗試描述這一系列 Firestore API 呼叫的機制。將它們視為一段「樣板程式碼」 - 程式碼 - 那種您寫一次,然後簡單複製的東西。由於您會發現需要一個完整的範本庫來涵蓋 Firestore「讀取」、「更新」和「刪除」操作的全部數組,因此您可能會發現查看 Post 10.1 - Firestore CRUD 命令範本很有用。如果您想查看 Google 自己的 API 描述,您可以在第 10.1 篇文章的末尾找到這些內容的連結。
這裡的「CRUD」是「建立」、「讀取」、「更新」和「刪除」的縮寫。
getDocs 結果作為文件數組傳回,通常稱為「快照」。但請注意,getDocs 函數呼叫前面有一個await 關鍵字。
這裡需要await關鍵字,因為預設情況下,在Javascript中,引用外部資料來源的指令可能需要不可預測的時間才能完成非同步處理。 「await」關鍵字本質上(儘管這是一個粗略的簡化)使您能夠覆蓋這種安排。當您有更多時間時,您可能會發現查看 Javascript fetch() API 和「await」關鍵字的簡單指南很有用
但現在,回到上面的程式碼片段,看看以 const firebaseConfig 語句開頭的部分。
firebaseConfig 聲明初始化一個對象,其中包含將 Web 應用連接到特定 Firebase 專案所需的設定詳細資訊。它包括 Firebase 用於定位和驗證您的應用程式的各種密鑰和標識符。您可以在 Firebase 控制台的「專案概覽/專案設定」中找到您的特定 Web 應用程式的設定。下面程式碼範例中的 firebaseConfig 設定已被“混淆”,因為它們是 我的 專案所特有的,並且不能輕易傳遞(稍後將詳細介紹這一點)。嘗試下面的範例程式碼時,您需要從您自己的專案複製 firebaseConfig 設定。
初始化 firebaseConfig 後,Web 應用程式可以初始化查詢的 const productsCollRef = collection(db, "products"); 所需的 db 變數。聲明:
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: "AIzaSyCE933 ... klfhFdwQg1IF1pWaR1iE", authDomain: "svelte-dev-afbaf.firebaseapp.com", projectId: "svelte-dev-afbaf", storageBucket: "svelte-devt-afbaf.appspot.com", messagingSenderId: "1027 ... 85697", appId: "1:1027546585697:web:27002bf ..... b0f088e820", }; const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp); const productsCollRef = collection(db, "products"); const productsQuery = query(productsCollRef, orderBy("productNumber", "asc")); const productsSnapshot = await getDocs(productsQuery); let currentProducts = []; productsSnapshot.forEach((product) => { currentProducts.push({productNumber: product.data().productNumber}); }); return { products: currentProducts } // accessed in +page.svelte as data.products
最後,您可能想知道這些 API 函數從何而來。答案是它們是透過程式碼區塊頂部的三個語句從專案中的位置導入的:
const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp);
這裡正在訪問“模組化庫”來為您的程式碼提供函數。從父模組中提取命名函數(例如集合),以滿足程式碼中稍後所需的參考。
但這又引出了一個問題「模組化庫首先如何進入我的專案?」答案當然是你必須把它們放在那裡,而你用來執行此操作的工具是忠實的舊 npm。
返回 VSCode svelte-test 終端會話(如有必要,透過幾個 ctrl-C 按鍵終止開發伺服器)並執行以下指令'
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: "AIzaSyCE933 ... klfhFdwQg1IF1pWaR1iE", authDomain: "svelte-dev-afbaf.firebaseapp.com", projectId: "svelte-dev-afbaf", storageBucket: "svelte-devt-afbaf.appspot.com", messagingSenderId: "1027 ... 85697", appId: "1:1027546585697:web:27002bf ..... b0f088e820", }; const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp); const productsCollRef = collection(db, "products"); const productsQuery = query(productsCollRef, orderBy("productNumber", "asc")); const productsSnapshot = await getDocs(productsQuery); let currentProducts = []; productsSnapshot.forEach((product) => { currentProducts.push({productNumber: product.data().productNumber}); }); return { products: currentProducts } // accessed in +page.svelte as data.products
一兩分鐘後(安裝涉及大量下載),您將準備好執行下載 Firestore 資料庫集合的程式碼。但是,您仍然不知道如何將其嵌入到 Svelte Web 應用程式中。那麼,進入下一個問題...
3.5 如何取得 Svelte page.svelte 檔案以從 Firestore 資料庫載入資料?
這是一個漫長的過程,但是,堅持下去,你就快完成了。
目前,在<script>中在 src/routes/ page.svelte 檔案的部分,您有以下語句:<br> </script>
const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp);
如您所知,這會將您的產品欄位聲明為狀態變數並將其初始化為空數組。現在您要做的是將「空」替換為 Firestore 產品集合的內容。
不幸的是,正如您所看到的,這涉及非同步操作。這讓事情變得有些複雜,因為 Svelte 不希望任何東西減慢頁面的初始加載速度 - 它很高興看到稍後添加的信息,但是,用戶的第一印象應該是即時響應。 Svelte 有一個將初始資料載入到 page.svelte 檔案中的標準安排。事情是這樣的:
首先,建立一個新的 src/routes/ page.server.js 文件,將所有非同步程式碼包裝在 load() 函數(強制名稱)內,並將其結果作為物件傳回。
這是程式碼
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore";
上面的 load 函數傳回一個具有單一 products 屬性的對象,其值是由 Firestore API 呼叫建構的 currentProducts 陣列。
這一切都很好,但是如何將其傳達給 page.svelte 中的產品狀態變數呢?
第一步是將新資料(強制名稱)狀態變數廣告為page.svelte 的prop(「property」的縮寫),您可以透過使用匯出關鍵字聲明它來實現此目的,因此:
npm install firebase
在您到達本系列的第 3.1 篇文章並了解「組件」之前,本系列不會介紹 Props。現在,將您的 page.svelte 檔案視為一個以資料作為參數的函數。
當您現在執行 page.svelte 檔案時,SvelteKit 框架會看到帶有保留資料關鍵字的匯出 let 資料聲明,並認為:「啊,我需要執行與此頁面關聯的 load() 函數」。產品資料及時返回 page.svelte 的 data 屬性中,現在,由於這是一個反應變量,因此頁面被刷新。
要讓現有的「範本」程式碼適用於新的安排,您所需要做的就是用 data.products 取代產品參考
page.server.js 檔案是您在 Svelte 中第一次看到的「伺服器端」程式碼 - 即在伺服器中執行的程式碼。到目前為止,您所看到的所有 page.svelte 程式碼都在瀏覽器中「客戶端」運行。相較之下,page.server.js 檔案要麼在 npm run dev 啟動的本機伺服器中運行,要麼在部署後在 App Engine 伺服器的 Node.js 環境中運行。伺服器端程式碼比客戶端程式碼運行速度更快且安全。唯一可以查看或更改它的人是您 - 它的所有者。
以下是 Post 2.2 中 page.svelte 檔案修改版本的完整程式碼:
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: "AIzaSyCE933 ... klfhFdwQg1IF1pWaR1iE", authDomain: "svelte-dev-afbaf.firebaseapp.com", projectId: "svelte-dev-afbaf", storageBucket: "svelte-devt-afbaf.appspot.com", messagingSenderId: "1027 ... 85697", appId: "1:1027546585697:web:27002bf ..... b0f088e820", }; const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp); const productsCollRef = collection(db, "products"); const productsQuery = query(productsCollRef, orderBy("productNumber", "asc")); const productsSnapshot = await getDocs(productsQuery); let currentProducts = []; productsSnapshot.forEach((product) => { currentProducts.push({productNumber: product.data().productNumber}); }); return { products: currentProducts } // accessed in +page.svelte as data.products
此程式碼應該位於哪裡?目前,「新增另一個產品」
以上是NgSysV.使用 Googles Firestore 建立一個簡單的 Svelte 資訊系統的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Atom編輯器mac版下載
最受歡迎的的開源編輯器