CesiumJS 2022^ 源碼解讀[0] - 文章目錄與源碼工程結構
- 2022 年 7 月 4 日
- 筆記
- 源碼, 工程, 源程式碼, Cesium, 解析, 開源GIS/Cesium源碼, 圖形/Cesium中階
很高興你能在浮躁的年代裡還有興趣閱讀源程式碼,CesiumJS 至今已有十年以上,程式碼量也積累了三十多萬行(未壓縮狀態)。
我也很榮幸自己的文章能被讀者看到,如果對你有幫助、有啟發,點個贊就是對我最大的鼓勵,感激不盡。本系列文章寫於 2022 年,梳理的是 CesiumJS 前端庫中的主要源碼結構,不涉及著色器原理、WebGL 效果原理剖析等內容較為專一、可以獨立出文的內容。
如果想看文章目錄,直接拉到本文最後一節即可。
1. 源程式碼工程目錄詳解
前置說明
- 當我在說「xx指令」時,指的是
package.json下的 node-script(即scripts列表中的某一個),可以使用 npm、yarn 或者 pnpm 運行; - 當我在說「開發者頁面」時,指的是你將源碼工程的依賴下載下來,啟動
start指令,啟動本地開發伺服器,打開的那個主頁; CesiumJS指的是Source文件夾下的前端庫源程式碼 + 測試程式碼 + 前端靜態資源 + 構建與源程式碼開發工具的統稱,前端庫即Cesium.js只是CesiumJS的主要構建產物。
① 根目錄下
gulpfile.cjs:gulp 的配置文件,有好幾個 node-script 是與裡面的 gulp 任務關聯的;CONTRIBUTORS.md:所有參與過 CesiumJS 項目的貢獻者名單;CHANGES.md:發布日誌;index.html&server.cjs:CesiumJS 這個工程使用了express這個庫,允許你使用start這個 node-script 啟動本地 express 伺服器,默認埠是 8080,打開開發者頁面,也就是 index.html;CONTRIBUTING.md:如何參與貢獻,也就是開發者或者 bug 發現者的指導書;.husky:CesiumJS 使用 husky + lint-staged + prettier 來管理程式碼風格;
② Source 目錄
CesiumJS 的前端庫部分,主要就是在 Source 目錄下的。目前,Source 目錄下的程式碼文件絕大多數已完成 ESModule 改造,含少量 css 文件。
雖然幾乎所有的源碼都是 ESModule 的,但是這個 Source 目錄並沒有 node 包經典的索引文件 index.js;Source 目錄的入口索引文件,是要運行 build 指令後才會出現的,文件名是 Cesium.js;這個入口索引文件也沒什麼東西,主要是導出源碼中的所有模組,無論公開私有,以及著色器字元串,以及當前 CesiumJS 的版本號。
下面對 Source 目錄的各個子文件夾作說明:

- Assets,一些靜態資源,例如默認天空盒、離線兩級世界影像(TMS)等;
- Core,數學 API、
Geometry API、高頻輔助函數、資源與請求 API、Terrain API等; - DataSources,基於 Scene 模組中較為底層的三維 API 再次封裝出來的上層 API,包括
Entity API、Property API和DataSource API,旨在更易接入人類友好型數據格式,例如 Gpx、KML、GeoJson 以及 CesiumJS 官方設計的 Czml,熟讀之後可以自行創建,這三個 API 要結合Viewer使用,單獨的 Scene 模組無法運行; - Renderer,籠統地稱這個文件夾下的程式碼為 Renderer 模組,封裝並擴展了 WebGL 原生介面,例如
Framebuffer對應WebGLFramebuffer等; - Scene,場景模組,基於 Core 模組和 Renderer 模組,CesiumJS 的三維世界由此模組創建,包括
Primitive API、Model API、Globe/QuadtreePrimitive API、GPUPicking API、3DTiles API等重要 API,通常稱之為 Scene 模組,是 CesiumJS 的基石;含ModelExperimental新架構和GltfPipeline子模組; - Shaders,後綴名是
.glsl的著色器程式碼文件,build指令運行後生成同名的 ESModule js 模組文件,導出著色器程式碼的字元串; - ThirdParty,第三方庫,例如 draco 解碼庫以及相關的 worker 等;
- Widgets,帶 UI 的一些功能型類,例如大家熟悉的
Viewer、Timeline、BaseLayerPicker,樣式文件也在此目錄下; - Worker & WorkerES6,WebWorker 文件,後者是源碼,前者是根據後者在運行
build指令後生成的 requirejs 版本。
③ Specs 目錄
這個是測試程式碼目錄。子目錄結構與 Source 下的基本一樣,要測試某個模組,則測試文件以那個模組的文件名 + Spec 尾綴,例如想測試 Core/Matrix4.js 模組下的四階方陣類,那麼就創建一個 Specs/Core/Matrix4Spec.js(官方有了,你可以打開學習)。
測試框架是 jasmine-core。
④ App 目錄
使用 Source 目錄下的源碼直接創建出來的現成應用程式,包括我們熟悉的 Sandcastle(沙盒)程式,還有兩個簡單的,有興趣自行打開查看(使用 start 這個命令啟動開發伺服器,從主頁進)。含少量測試數據。
⑤ [構建後] Build 目錄
運行 build/combine/minify 等指令,這個文件夾才會出現。它主要是發布出來 CesiumJS 的 iife 庫版本,以及附帶必須要用的四大靜態資源文件夾 - Assets、ThirdParty、Widgets、Workers。
根據指令的不同,發布的 iife 庫版本不一樣,也影響是不是有 TypeScript 類型定義文件、SourceMap 映射文件。
combine 指令發布的是 CesiumUnminified 未壓縮版本,也就是主庫文件有 37 萬行的版本;minify 指令發布的是 Cesium 文件夾下的壓縮版本,程式碼經過簡化。
如下圖所示:

⑥ Documentation 目錄
文檔目錄,使用 generateDocumentation 指令生成的 API 手冊,從開發者主頁可以進去。
⑦ ThirdParty 目錄
第三方依賴庫,CesiumJS 不希望安裝在 node-package-dependencies 列表中的就放在這裡,手動升級,並將依賴列表寫入根目錄下的 ThirdParty.extra.json 文件內。
每當執行 prepare 這個 node-script 後,gulp 就會把這個目錄裡面的一些資源(測試框架、Draco 庫等)複製到指定位置。
⑧ Tools 目錄
gulp 部分任務需要用到的工具庫或配置,例如 rollup 額外配置、jsdoc 配置等。
未來可能的改進
官方論壇中有討論過 monorepo 技術的接入,也就是一工程多子庫的結構,見:Is there interest in a compact Cesium math library?
但是我認為在 3DTiles 1.1 推廣完畢、構建工具大換血之前,這個可能並不會有什麼實質性的推動,畢竟 CesiumJS 已經是 ESModule 格式的了,而且內部各種邏輯隨時可能按需求變動會改進,把 CesiumJS 本身拆成 monorepo 可能不太現實。
2. 構建命令
既然 CesiumJS 是作為一個 NodeJS 包存在的,那麼它就支援 node-script,也就是 package.json 里的 「scripts」列表。
先介紹如果用到源碼開發用到的常用指令:
prepare,在你安裝依賴(npm install)後會自動拉起的一個命令,會執行 gulp 同名任務,並安裝 husky 庫;build,最初始的一個指令,將Source下的源程式碼合併出一個Source/Cesium.js,也就是 CesiumJS 源碼的 ESModule 入口文件,同時會把Source/Shaders下所有 glsl 文件複製並改寫成導出著色器字元串的 js 文件;另外,只有這個指令運行後在沙盒中才能看到開發者示例程式碼;start和startPublic,啟動開發伺服器,後者允許公開訪問本機,默認 8080 埠release,一個複合指令,先後運行 build → build-ts → combine → minifyRelease → generateDocumentation 指令;generateDocumentation,使用 jsdoc 根據 Source 下的源碼注釋生成 API 幫助文檔;makeZipFile,一個複合指令,先運行 release 指令後將指定的文件壓縮成一個 zip 文件,也就是每個月月初你在 GitHub 發布頁面下載的那一個稍大的壓縮包;combine,也是工程中 gulp 的默認任務,它會連著 build 指令一起執行,將Source下的源碼使用 rollup 轉譯成 iife 庫,輸出到Build/CesiumUnminified目錄下,是未壓縮版本庫,37萬行,主文件 12.3 MB;combienRelease不輸出 sourcemap 文件;minify,與combine目的一樣,只不過告訴 rollup 要生成壓縮版本的庫,輸出到Build/Cesium目錄下;也有minifyRelease姐妹命令;clean,清理 build/release/combine 等指令生成的產出文件,恢復未構建時的乾淨工程狀態
然後是其它可能用到的:
prettier和prettier-check,統一程式碼風格test等一系列 test 指令:運行Specs目錄下的測試程式碼
最後有一個隱藏的指令,這個允許你把 jsdoc 注釋為私有的 API,即 @private 注釋的,也在開發者文檔中展示出來,但是這個指令並沒有在 node-script 列表中。
npm run generateDocumentation -- --private
這個功能來自 PR CesiumGS/cesium#10261
未來可能的改進
官方正在內測使用 esbuild 改進 gulp 和 rollup 的構建性能和品質,參考:CesiumGS/cesium#10399,目前已知使用 esbuild 構建後的主庫體積、SourceMap 文件體積都有明顯的下降。
筆者也在官方論壇發起這項議題時參與了討論:CesiumJS Build Tooling Revamp
希望在不久的將來能用上文件體積更小的庫。
3. 文章目錄
本篇即源碼工程結構。
- 篇1 - 使用 requestAnimationFrame 循環觸發幀動畫
- 篇2 - 渲染架構之 Primitive - 創建並執行指令
- 篇3 - 渲染原理之從 Entity 看 DataSource 架構 - 生成 Primitive 的過程
- 篇4 - 最複雜的的確批發 影像與地形的渲染與下載過程
- 篇5 - 著色器的封裝設計 - Renderer 模組
- 篇6 - 三維模型(ModelExperimental)新架構
- 篇7 - 3DTiles 的請求載入處理與調度
- 篇8 - 資源封裝與多執行緒

