关于在 ClojureScript 当中引入依赖 document 对象的包(笔记)

通常前端代码崔主要是为了在浏览器环境运行,
在有服务端渲染的需求的时候, 也会兼容一下代码的加载,
好比同一个 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

相关文章
相关标签/搜索