
來,乖乖們,坐下來,靠在阿公身邊。阿公今天剛泡好一壺溫潤的琥珀熱茶,這茶葉是鄉下自家曬的,喝一口暖胃,說起話來也就慢條斯理了。
大孫女啊,阿公剛剛看妳捧著筆電,眉頭深鎖、直嘆氣,是在為公家機關或軍工單位的專案傷腦筋吧?妳說,那些客戶的環境叫做 「完全實體隔離(Air-gapped)」 的內網環境?不能連外網,甚至連伺服器都不能部署,但裡頭的長官卻天天喊著要看「炫酷、好玩的互動圖表」。
呵呵,阿公懂,這就跟以前村子裡的「老帳房」一樣。那時候,各家的賬本都是壓在箱底,絕對不准帶出村子、更不能給外人看一眼,可村長又想隨時掌握今年收了多少擔穀子。這時候啊,我們就得把算盤、墨水和賬本通通收在一個竹簍子裡,在自家的土圍子裡自己算,這就叫「安全」。
今天,阿公就著這杯茶,慢條斯理地給妳講講這套 「Day 13:安全至上:完全無外部請求的 Apache ECharts 離線數據可視化」 的智慧。妳把阿公說的這些記下來,拿去作教育訓練,保證那些年輕工程師聽得一愣一愣的,還能幫妳把專案做得穩穩當當。
在軍工、政府或金融內網環境中,資安的要求是嚴苛到極點的。他們實施 「完全實體隔離(Air-gapped)」:
要在這種環境下做出能動、能點、又炫酷的互動圖表,唯一的出路,就是設計一個 「零相依(Zero-Dependency)」的純前端離線儀表板。
大孫女啊,妳要教大家,既然不能去鎮上買工具,我們就要把所有幹活的傢伙通通裝進同一個竹簍子裡帶進去。這就是我們的核心原則:零外部依賴(Zero External Dependency)。
我們不使用任何線上資源,在有網路的環境下,先把這三個「法寶」下載下來,直接放進專案的本地資料夾(比如 lib/ 目錄中):
echarts.min.js):負責在螢幕上畫出各種精美、會動、滑鼠放上去有說明框的互動圖表。papaparse.min.js):專門用來把那種逗號隔開的 CSV 數據檔案,拆解成網頁看得懂的陣列資料。xlsx.full.min.js):用來解析長官最愛用的 Excel 活頁簿(.xlsx),連後端伺服器都不用,前端就能把它拆個明白。阿公最推薦的,是把所有的樣式(CSS)、網頁結構(HTML)、還有這三個 JavaScript 庫,直接內嵌寫在同一個 dashboard.html 檔案裡。
雖然這個檔案會因為塞滿了程式碼而變得有點肥大(大約 2 到 4 MB),但它最大的好處就是 「攜帶極其方便」。使用者只要用隨身碟把這個網頁檔拷貝到那台被隔離的本機電腦上,雙擊滑鼠一開啟,就能直接在瀏覽器裡跑起來,連簡易網頁伺服器都不用裝。
大孫女,妳要把下面這 10 種圖表 記熟,這是我們在完全離線的狀態下,透過程式自動偵測使用者上傳的資料型別,在記憶體裡即時渲染出來的:
妳要跟台下的學生強調:「資料絕不上傳伺服器!」
使用者在網頁上主動上傳 CSV 或 Excel 檔案後,所有的資料解析、型別分類、到 ECharts 把圖畫出來,100% 都是在本機電腦的記憶體(RAM)中完成的。只要把瀏覽器分頁一關,記憶體就乾乾淨淨,不留下半點痕跡,更不會發送任何外部請求,資料外洩的風險是絕對的零!
大孫女,這一段是妳教書時最值錢的 「避坑指南」,工程師們最容易在這裡摔得鼻青臉腫。
fetch('./data.json')!很多年輕人在有網路的開發環境下寫慣了,喜歡用 fetch 或 XMLHttpRequest 去讀取旁邊的本地檔案。
但是,當使用者把 dashboard.html 拷貝到實體隔離的電腦,直接雙擊滑鼠開啟時,瀏覽器的網址列會顯示 file:// 協定。這時候,瀏覽器為了防止駭客偷看本地檔案,會啟動極其嚴格的沙箱限制(CORS)。妳程式碼裡的 fetch('./data.json') 會被瀏覽器直接判定為安全違規而阻擋!
<input type="file"> 與 FileReader既然不讓我們主動去「拿」檔案,那我們就得在網頁上放一個大大的 「請選擇資料檔案」按鈕(<input type="file">)。
當使用者點擊、主動選擇了本機的 CSV 或 Excel 時,在瀏覽器眼裡,這是「主人主動授權的動作」,就安全了。
此時,我們在 JavaScript 裡使用原生非同步的 FileReader,用 readAsText 讀取 CSV,或者用 readAsArrayBuffer 讀取 Excel 的二進位資料。這一切操作都在記憶體內,完全不經過任何網路請求,完美繞過了 file:// 的沙箱跨域限制!
如果有些長官真的很想看更精緻的地圖,需要動態載入大容量的 GeoJSON,內嵌變數不方便。阿公建議可以教他們用 Python 開一個 「本地簡易伺服器」:
在該資料夾底下,打開命令列輸入:
python -m http.server 8000
然後在瀏覽器輸入 http://localhost:8000 開啟。這時協定變成了 http://,就不會觸發 file:// 的 CORS 沙箱限制,地圖功能就能完整、順暢地執行了。
老帳房的智慧就是:
大孫女啊,阿公說得稍微快了點,妳聽得明白嗎?小孫女又在院子裡喊著要阿公幫她抓蝴蝶了,等阿公喝完這口茶,再去陪她玩。