CesiumJS 2022^ 源碼解讀[0] - 文章目錄與源碼工程結構

很高興你能在浮躁的年代裏還有興趣閱讀源代碼,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.jsSource 目錄的入口索引文件,是要運行 build 指令後纔會出現的,文件名是 Cesium.js;這個入口索引文件也沒什麼東西,主要是導出源碼中的所有模塊,無論公開私有,以及着色器字符串,以及當前 CesiumJS 的版本號。

下面對 Source 目錄的各個子文件夾作說明:

image

  • Assets,一些靜態資源,例如默認天空盒、離線兩級世界影像(TMS)等;
  • Core,數學 API、Geometry API、高頻輔助函數、資源與請求 API、Terrain API 等;
  • DataSources,基於 Scene 模塊中較爲底層的三維 API 再次封裝出來的上層 API,包括 Entity APIProperty APIDataSource API,旨在更易接入人類友好型數據格式,例如 Gpx、KML、GeoJson 以及 CesiumJS 官方設計的 Czml,熟讀之後可以自行創建,這三個 API 要結合 Viewer 使用,單獨的 Scene 模塊無法運行;
  • Renderer,籠統地稱這個文件夾下的代碼爲 Renderer 模塊,封裝並擴展了 WebGL 原生接口,例如 Framebuffer 對應 WebGLFramebuffer 等;
  • Scene,場景模塊,基於 Core 模塊和 Renderer 模塊,CesiumJS 的三維世界由此模塊創建,包括 Primitive APIModel APIGlobe/QuadtreePrimitive APIGPUPicking API3DTiles API 等重要 API,通常稱之爲 Scene 模塊,是 CesiumJS 的基石;含 ModelExperimental 新架構和 GltfPipeline 子模塊;
  • Shaders,後綴名是 .glsl 的着色器代碼文件,build 指令運行後生成同名的 ESModule js 模塊文件,導出着色器代碼的字符串;
  • ThirdParty,第三方庫,例如 draco 解碼庫以及相關的 worker 等;
  • Widgets,帶 UI 的一些功能型類,例如大家熟悉的 ViewerTimelineBaseLayerPicker,樣式文件也在此目錄下;
  • 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 庫版本,以及附帶必須要用的四大靜態資源文件夾 - AssetsThirdPartyWidgetsWorkers

根據指令的不同,發佈的 iife 庫版本不一樣,也影響是不是有 TypeScript 類型定義文件、SourceMap 映射文件。

combine 指令發佈的是 CesiumUnminified 未壓縮版本,也就是主庫文件有 37 萬行的版本;minify 指令發佈的是 Cesium 文件夾下的壓縮版本,代碼經過簡化。

如下圖所示:

image

⑥ 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 文件;另外,只有這個指令運行後在沙盒中才能看到開發者示例代碼;
  • startstartPublic,啓動開發服務器,後者允許公開訪問本機,默認 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 等指令生成的產出文件,恢復未構建時的乾淨工程狀態

然後是其它可能用到的:

  • prettierprettier-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. 文章目錄

本篇即源碼工程結構。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章