通常前端代碼崔主要是爲了在瀏覽器環境運行,
在有服務端渲染的需求的時候, 也會兼容一下代碼的加載,
好比同一個 React 組件, 一樣能夠用於服務端渲染,
而其中涉及到瀏覽器 API 的代碼, 能夠選擇不執行, 經典的:前端
if (typeof window != undefined) { // do something }
若是是 ClojureScript 當中遇到此類的代碼, 也相似:node
(if (exists? js/window) (comment "do soemthing"))
這一次是我引用了一個 https://alertifyjs.org/ 的模塊,
這個 js 模塊沒有處理好. 對, 我是從 ClojureScript 引用了 js 模塊,
而後, 在 shadow-cljs 打包完成運行的時候遇到了這樣的問題,瀏覽器
ReferenceError: document is not defined
若是是 js, 我在 require("alertify.js")
的寫法前面加 if
就行了.
雖然對於 import
語法不能用 if
, 可是打包工具通常都支持 CommonJS 的.
而在 ClojureScript 當中問題比較明顯, 由於 ns
是個 Macro,
意味着代碼在執行以前會被代碼再進行處理, 我是不能隨便加 if
的,app
(ns app.main (:require ["alertify.js" :as alertify]))
至少在我沒搞清楚 ns
到底展開稱爲何樣的代碼的狀況下..工具
因而我想到說用 shadow-cljs 對 js 模塊作重定向的功能的作法,
我在打包 :node-script
這個執行腳本的時候, 不要使用 alertify.js
的代碼了,
轉而使用一個空的 js 文件, 這樣就不會去訪問 document
而後出錯.
參考文檔上的用法, 應該是這樣寫的:ui
:page {:target :node-script :output-to "target/page.js" :js-options {:resolve {"alertify.js" {:target :file :file "entry/alert-ssr.js"}}} :main app.page/main! :devtools {:after-load app.page/main!}}}}
:js-options
是生效的地方, 我把模塊指向了一個本地的文件.ssr
不過實際使用遇到的問題, 問了做者, 他在 :node-script
這個環境沒開這個選項,
https://clojureverse.org/t/ho...
而後升級到了 2.3.22
版本就支持了, 因此就搞定了.code