目錄
- 1 問題起因
- 2 尋找解決方案
- 2.1. 歷史原因
- 2.2. 增加匯出
- 2.3. 耍個花招
- 3 型別提示是哪來的
1 問題起因
我使用 vite2 + vanillajs 模板創建 CesiumJS 專案,其中,main.js 是這樣的:
import { Viewer } from 'cesium'
import './style.css'
import 'cesium/Source/Widgets/widgets.css'
let viewer
const main = () => {
const dom = document.getElementById('app')
viewer = new Viewer(dom)
}
document.addEventListener('DOMContentLoaded', () => {
main()
})
看起來邏輯完美,思路清晰,沒什么特別的疑問點,于是我就吭哧吭哧地運行起 npm script:
pnpm dev
可是,Vite 在控制臺給我報了個錯:
[vite] Internal server error: Missing "./Source/Widgets/widgets.css" export in "cesium" package
這個問題貌似在各前端框架的模板中是不會出現的,我不確定,也有人在 Webpack 中遇到了這個類似的情況,究其原因,我認為還是 cesium 包的匯出有些不完備,見下面第二節的分析,
簡單點說,就是 Vite 的內置預構建工具 esbuild 在搜索依賴樹時,沒有找到 "cesium" 包匯出的一個路徑為 "./Source/Widgets/widgets.css" 檔案,
2 尋找解決方案
可是,當我打開 node_modules/cesium/Source/Widgets/ 目錄,widgets.css 檔案的確就在那里放著,
于是我打開了谷歌,果不其然找到了類似的 issue:github.com/CesiumGS/cesium issue#9212,我在 2021 年 8 月也跟帖回復了我的情況,
我當時并沒有找到解決方案,就暫時跳過了,
后來,有外國朋友跟帖回復,大致原因找到了:
cesium 包的 package.json 沒有匯出樣式檔案,主要是 package.json 中的 exports 屬性,
于是,我打開官方原始碼的 package.json,找到對應的部分:
{
"exports": {
"./package.json": "./package.json",
".": {
"require": "./index.cjs",
"import": "./Source/Cesium.js"
}
}
}
2.1. 歷史原因
眾所周知,NodeJS 最先使用的模塊化機制是 CommonJS,后來才支持的 ESModule,現在 NodeJS 仍然默認新建的包是 CommonJS 模塊的,
外國佬在 NodeJS 的包中允許雙模塊化,這就容易存在兼容性問題,我們看看最開始是怎么實作雙模塊化的,這里以默認 ESModule 為模塊化方式:
- 設定
package.json的"type": "module",這樣所有的.js檔案都是 ESM 了 - 設定
package.json的"module": "./dist/esm/index.js",這個意思是使用 import 語法匯入時,ESM 模塊將從哪里尋找主檔案 - 設定
package.json的"main": "./index.cjs",這個意思是使用 require 函式匯入模塊時,CommonJS 的主檔案是哪個
后來,隨著 ESModule 成為主流標準,NodeJS 改進了上面的配置方式,你仍可以設定 "type": "module" 令當前包的模塊化是 ESM,但是對包的多模塊化機制的配置則改用了 "exports" 欄位,正如上面 cesium 的配置,
我檢查了我的 NodeJS 版本:
> node -v
> v16.14.0
顯然比較新,那么它應該就是從 "exports" 中讀取的匯出資訊,
2.2. 增加匯出
于是,我增加了 "exports" 的匯出欄位,讓打包工具在識別 cesium 包的匯出時,可以正確識別 widgets.css 檔案,
{
"exports": {
"./package.json": "./package.json",
".": {
"require": "./index.cjs",
"import": "./Source/Cesium.js"
},
+ "./Source/Widgets/widgets.css": "./Source/Widgets/widgets.css"
}
}
這樣,下面兩個匯入陳述句:
import { Viewer } from 'cesium'
import 'cesium/Source/Widgets/widgets.css'
實際上就是:
import { Viewer } from 'cesium/Source/Cesium.js'
import 'cesium/Source/Widgets/widgets.css'
2.3. 耍個花招
我覺得這樣匯入 css 檔案還是太長,不妨在 "exports" 中給它改個名:
{
"exports": {
"./package.json": "./package.json",
".": {
"require": "./index.cjs",
"import": "./Source/Cesium.js"
},
+ "./index.css": "./Source/Widgets/widgets.css"
}
}
然后就可以愉快地使用短路徑匯入了:
import { Viewer } from 'cesium'
import 'cesium/index.css'
事實上,package.json 中的這個 exports 屬性,就起到類似匯出別名的作用,其中 "." 就相當于包的根路徑,
3 型別提示是哪來的
考慮這樣匯入 cesium 各個 API:
import {
Viewer,
Cartesian3,
Camera
} from 'cesium'
當你使用這些類的時候,會得到不錯的型別提示,回顧前面的內容,其實從 "cesium" 匯入子模塊,實際上是從 "cesium/Source/Cesium.js" 檔案匯入的,而這個檔案的旁邊就有一個 "Cesium.d.ts" 檔案,它就起型別提示的作用,
這個型別宣告檔案是 Cesium 使用 gulp 打包時輸出的,
說了這么多,根本原因還是 JavaScript 的歷史包袱導致的各種問題,而且官方也暫時沒有修改 package.json 中 exports 的計劃,如果你有報這個錯誤,那么你僅僅需要按我上面的方式稍作修改即可,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/434430.html
標籤:其他
