1

Light Table 0.7.2 running a "live" browser repl with clojurescript.

I'm just documenting a solution to a problem that was blocking me from using Light Table. I couldn't find any suitable answers, and it took a while for me to find a workaround. Hopefully, this will help anyone else experiencing a similar problem.

When editing a scratch file that is not the core cljs source file for the project (as specified in project.clj:cljsbuild:builds:source-paths), I was getting the following when defining a namespace:

(ns foo)
ReferenceError: goog is not defined

In attempting to use something like dommy, I would get:

(ns foo.bar-2
  (:require
    [dommy.core :as dc]
    [domina.xpath :as dx]))
 Error: goog.require could not find: dommy.core

I found similar problems here [Clojurescript libraries - goog.require could not find

and here https://groups.google.com/forum/#!searchin/light-table-discussion/goog$20/light-table-discussion/D4xjfDnA2Co/7iaqewIPzGUJ

However, in the first case, the solution did not work. In the second case I was unable to understand what the user meant by "just not live evaling clojurescript namespaces in LightTable and relying on the browser/DOM behavior for feedback" as a workaround.

The reason for me not using the main file of the project is I want to do some quick one-offs in a separate repl. This is something I am able to do under emacs. Normally, under emacs, I will have the main cljs file, and then the ncider repl. I will put both into the same namespace, so I can update the shared context from either buffer.

Community
  • 1
  • 1
vt5491
  • 2,254
  • 2
  • 22
  • 34

1 Answers1

1

Assumptions: I assume you know already know how to bring up the two servers needed by Light Table: the clojure repl, and the browser.

Basically, this link: http://grokbase.com/t/gg/clojure/142rsp4rc8/om-trouble-with-goog-reference

tipped me off to the solution.

It appears that any file that is not under the project src dir, is totally dependent on the browser "repl" to find any libraries it needs. So the solution is to add tags to your index.html for any js libraries you want to include in the ns:

<html>
    <head>
      <script type='text/javascript' id='lt_ws' src='http://localhost:54792/socket.io/lighttable/ws.js'></script>
      <script src="out/goog/base.js" type="text/javascript"></script> <!-- add this -->
    </head>
    <body>
        hello from mies-test
        <script src="out/mies_test.js" type="text/javascript"></script>
    </body>
</html>

You must then do the following:

1) Make sure you have any js libraries (other than 'goog') under your project.clj dependencies:

 :dependencies [[org.clojure/clojure "1.6.0"]
                [org.clojure/clojurescript "0.0-2755"]
                [domina "1.0.3"]
                [prismatic/dommy "1.0.0"]
                [enfocus "2.1.1"]

2) run "lein cljsbuild once". You need to make sure you have goog/base.js and cljs/core.js under your output dir:

@HP_LAPTOP_ENVY /c/vtstuff/clojure_stuff/projects/mies2/out
$ ls *
cljs_deps.js  mies_test.js

cljs:
core.cljs  core.cljs.cache.edn  core.js  core.js.map

clojure:
browser

goog:
array    base.js  disposable  functions  iter  log        mochikit  promise  structs  uri
asserts  debug    dom         html       json  math       net       reflect  testing  useragent
async    deps.js  events      i18n       labs  messaging  object    string   timer

mies2:
core.cljs  core.cljs.cache.edn  core.js  core.js.map

If you do a "lein clean" it will delete the "out" dir. Doing a "lein cljsbuild once" will then rebuild it. Do this if you want a clean start.

3) Refresh your browser url e.g

file:///C:/vtstuff/clojure_stuff/projects/mies2/index.html

4) Now when I ran (ns foo) I got:

Error: goog.require could not find: cljs.core
    at Error (<anonymous>)
    at Object.goog.require (file:///C:/vtstuff/clojure_stuff/projects/mies2/out/goog/base.js:470:13)

-> This seems to be an inconsistent problem. I was able to get another project to work without adding cljs/core.js to index.html. You can basically see here how any scratch buffer is entirely dependent on what the browser repl knows about. The main clojure repl is automatically aware of any dependencies, but here again I seem to need to add it to index.html:

<head>
   <script type='text/javascript' id='lt_ws' src='http://localhost:61756/socket.io/lighttable/ws.js'></script>
   <script src="out/goog/base.js" type="text/javascript"></script>
   <script src="out/cljs/core.js" type="text/javascript"></script> <!-- add this -->
</head>

5) Refresh the browser again, and now evaluations in scratch.cljs work:

(+ 1 1 ) 2

(ns foo) nil

(namespace ::x) "foo"

6) if you want to add dommy to your ns:

(ns foo-2
 (:require [dommy.core :as dommy]))
    #<Error: goog.require could not find: dommy.core>
Error: goog.require could not find: dommy.core

You're going to have cause dommy/core.js to be created under the "out" dir. You'll have to extract the .cljs files from the dommy jar (in your maven ".m2" repos) and then add them to your src dir. Then do a "cljsbuild once" to generate dommy/core.js, then add a reference to index.html, like we did for 'goog' and 'cljs'. I did this and it worked. However, I now realize it's just best to have your scratch repl pull in the "main" cljs, and then just reference the artifacts from your scratch file (or just do everything in the main cljs, which is what I think the prior person was talking about when he said "avoiding 'live evaling'") :

(ns foo-3
(:require [mies2.core]))

mies2.core/abc 7

7) Unfortunately, you can't put the scratch file into the same ns as the main

cljs:

(ns  mies2.core)

#<Error: Namespace "mies2.core" already declared.>
Error: Namespace "mies2.core" already declared.

Anyway, after figuring all this out, I was able to run a three.js cube demo. Maybe this will all seem obvious once I gain more familiarity with live browser "repling", but it certainly cause me a lot of confusion in the beginning.

Happy coding.

vt5491
  • 2,254
  • 2
  • 22
  • 34