2

我正在尝试确定是否可以在 Node.js 上使用 Om 来生成 HTML。我已经能够让ClojureScript 在 Node.js 上运行,并且显然React 可以在 Node.js 上运行。我按照基本指南创建了一个 Leiningen 项目

lein new figwheel om-tut -- --om

修改project.clj文件启动如下

(defproject om-tut "0.1.0-SNAPSHOT"
  :description "FIXME: write this!"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}

  :dependencies [[org.clojure/clojure "1.6.0"]
                 [org.clojure/clojurescript "0.0-2850"]
                 [figwheel "0.2.5-SNAPSHOT"]
                 [org.clojure/core.async "0.1.346.0-17112a-alpha"]
                 [sablono "0.3.4"]
                 [org.omcljs/om "0.8.8"]]

  :plugins [[lein-cljsbuild "1.0.4"]
            [lein-figwheel "0.2.5-SNAPSHOT"]
            [lein-npm "0.4.0"]]

  :source-paths ["src"]

  :clean-targets ^{:protect false} ["resources/public/js/compiled" "out/server" "out/server/om_tut.js"]

  :cljsbuild {
    :builds [{:id "dev"
              :source-paths ["src" "dev_src"]
              :compiler {:output-to "resources/public/js/compiled/om_tut.js"
                         :output-dir "resources/public/js/compiled/out"
                         :optimizations :none
                         :main om-tut.dev
                         :asset-path "js/compiled/out"
                         :source-map true
                         :source-map-timestamp true
                         :cache-analysis true }}
             {:id "min"
              :source-paths ["src"]
              :compiler {:output-to "resources/public/js/compiled/om_tut.js"
                         :main om-tut.core                         
                         :optimizations :advanced
                         :pretty-print false}}
             {:id "server"
              :source-paths ["src"]
              :compiler {
                :main pow.core
                :output-to "out/server/om_tut.js"
                :output-dir "out/server"
                :optimizations :simple
                :target :nodejs
                :cache-analysis true
                :source-map "out/server/om_tut.js.map"}}]}

并将 core.cljs 更改为

(ns ^:figwheel-always om-tut.core
    (:require[om.core :as om :include-macros true]
              [om.dom :as dom :include-macros true]))

(enable-console-print!)

(println "Edits to this text should show up in your developer console.")

;; define your app data so that it doesn't get over-written on reload

(defonce app-state (atom {:text "Hello world!"}))

(defn render [data owner]
  (reify om/IRender
    (render [_]
      (dom/h1 nil (:text data)))))

(om/root
  render
  app-state
  {:target (. js/document (getElementById "app"))})

(defn -main []
  om.dom/render-to-str (render app-state nil))

(set! *main-cli-fn* -main)

项目使用以下命令编译成功

lein cljsbuild once server

但是当我尝试从 Windows cmd shell 运行生成输出时

node out\server\om_tut.js

我明白了

    ...\om-tut\out\server\om_tut.js:40237
om.dom.input = om.dom.wrap_form_element.call(null, React.DOM.input, "input");
                                                   ^
ReferenceError: React is not defined
    at Object.<anonymous> (...\om-tut\out\server\
om_tut.js:40237:52)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3

我认为未定义的 React 对象应该来自 ...\om-tut\out\react.inc.js 文件,该文件存在并且应该在生成的 om_tut.js 文件的第 37532 行加载

cljs.core.load_file("react.inc.js");

关于可能出了什么问题的任何想法?

4

3 回答 3

1

您需要在 中添加序言project.clj,例如:preamble ["include.js"]。序言隐含地引用/resources相对于 的目录project.clj。来源:https ://github.com/Sparrho/supper/blob/master/project.clj

include.js您将在其中提供对 React 的引用:

var React = require("react");

来源:https ://github.com/Sparrho/supper/blob/master/resources/include.js

作为参考,这是 project.clj 中的构建块:

{:id "server"
:source-paths ["src"]
:compiler {:main myapp.core-server
           :target :nodejs
           :output-to "deploy/index.js"
           :output-dir "out-server"
           :preamble ["include.js"] ;; Implicitly nested in /resources                       
           :optimizations :simple
           :language-in :ecmascript5
           :language-out :ecmascript5}}

我还读过它:preamble可以react.min.js直接引用,因为它被捆绑在 Om 依赖的 WebJar 中。来源:https ://groups.google.com/forum/#!topic/clojurescript/TL8Cv-jPkzM

于 2015-05-21T04:10:43.960 回答
1

您可以尝试:preamble ["include.js"]使用以下内容的解决方法:

module.exports = '';

但这仅适用于您只有一些cljsjs/包的情况(在这种情况下是cljsjs/react)。例如,包括 ofcljsjs/jquery 2.1.4将不起作用。


由于 React 定义而出现问题:

!function(e){
    if ("object" == typeof exports && "undefined" != typeof module) {
        module.exports = e();
    }
    else if ("function" == typeof define && define.amd) {
        define([],e);
    }
    else{
        var t;
        t= "undefined" != typeof window ? window
            : "undefined" != typeof global ? global
            : "undefined" != typeof self ? self
            : this,
            t.React = e()
    }
}(function(){/* React definition */})

环境在 NodeJS 中没有window对象,但它有modulemodule.exports. 我们通过重置module.exports为字符串来欺骗环境。

React = require('react')react在安装了模块的 NpmJS 环境中不起作用。


react在我看来,正确的解决方案是不将 React 的代码包含到模块中,而是在具有依赖关系的 NpmJS 环境下使用该模块。

在这种情况下,tyronep 的 回答很好。我们应该:

  1. 使用以下:preamble

    global.React = require('react')
    
  2. 不包括cljsjs/react依赖项

  3. 需要react在 NpmJS 依赖项中。

不幸的是,如果我们要使用omthencljsjs/react 必须包含(即冗余包含)

于 2015-08-16T18:34:31.887 回答
0

你当前的问题是关于加载 React 模块,我相信你会解决调整你的配置,但你不能om.core/root在 Node.js 上调用。om.core/root将你的 React 组件安装在 Node 所缺乏的 DOM 中。您想要的是定义您的组件,将您的静态数据传递给它们,然后调用React.renderToStringhttps://facebook.github.io/react/docs/top-level-api.html#react.rendertostring)。Om 用render-to-str.

(def static-data {:text "Hello world!"})

(defn title-component [data owner]
  (reify om/IRender
    (render [_]
      (dom/h1 nil (:text data)))))

(def component-html-as-string
  (dom/render-to-str (title-component static-data)))

Om 的大部分价值来自于它们的状态处理能力,服务器端渲染不需要这些能力(这就是我省略的原因atom)。如果你想要的是 ClojureScript 中的 React 模板,我建议你看看Sablono,它有一个静态 html 函数和一个比om.dom.

另外,要在 Node 上开发,最好从mies-node开始

于 2015-05-12T17:32:03.280 回答