Fork me on GitHub
#clojurescript
<
2020-01-17
>
Michael14:01:17

Hi. I’m trying to build a project that uses Reagent/re-frame on node.js. Everything seems to work fine so far, but I don’t seem to be able to get a final self-contained bundle. Here’s the relevant part of my project.clj:

:dependencies [[org.clojure/clojure "1.10.1"]
                 [org.clojure/clojurescript "1.10.597"
                  :exclusions [org.apache.ant/ant]]
                 [reagent "0.8.1"]
                 [re-frame "0.10.9"]]

  :plugins [[lein-cljsbuild "1.1.7"]
            [lein-doo "0.1.10"]]
  :target-path "build/cljs/%s/"
  :cljsbuild {
    :builds [{:id "dev"
              :source-paths ["src/clj"]
              :compiler {:output-to "app.js"
                         :optimizations :advanced
                         :target :nodejs
                         :hashbang false
                         :main myapp.core
                         :npm-deps {:react "16.9.0"
                                    :react-dom "16.9.0"}
                         }}]}
The bundle seems to contain both react and react-dom, and it looks like they were just copied over verbatim from their minified bundles. But it still contains require("react") calls (once in the react-dom code and twice in a long line between the react and the react-dom code). These requires cannot be resolved by node.js when react is not available as an external file. Any idea on how can I get rid of them?

Michael15:01:48

Okay, I just noticed that the :npm-deps part doesn’t seem to have any effect. If I leave it out the result is exactly the same. Also, the react and react-dom versions in the bundle differ from the ones I specified.

borkdude15:01:56

I have:

(deftype FnBodyImpl [body params fixed-arity var-arg? fn-name])
in one namespace and:
(:require [sci.impl.types :as t]
            [sci.impl.analyzer])
  (:import [sci.impl.analyzer FnBodyImpl])
in another. However, the compiler says:
No such namespace: sci.impl.analyzer.FnBodyImpl, could not locate sci/impl/analyzer/FnBodyImpl.cljs, sci/impl/analyzer/FnBodyImpl.cljc

borkdude15:01:20

I can just elide the import since I'm only using it for a type hint in clj

Alex Miller (Clojure team)15:01:16

why are you importing? (maybe my cljs knowledge is poor here, but you would require it in Clojure?)

☝️ 4
lilactown18:01:43

is it possible to have a macro initialize a CLJ namespace and def a new macro in that namespace?

lilactown18:01:41

ah I guess this is a no-brainer since I want to be able to require the macro ns in another ns, which means it needs to be available before evaluating the cljs ns

borkdude18:01:28

@alexmiller would I require + refer a deftype when I want to use it as a type hint? :thinking_face:

Alex Miller (Clojure team)19:01:50

Ah, yes there, but in what case would you need that?

borkdude19:01:53

to call the fields directly with (.-foo ^MyDefType x)

borkdude19:01:42

without reflection

Alex Miller (Clojure team)20:01:38

in records, the fields are accessible via the map api

Alex Miller (Clojure team)20:01:45

in types, the fields are private

Alex Miller (Clojure team)20:01:08

or maybe the non-mutable ones are public, but you still shouldn't do that

Alex Miller (Clojure team)20:01:00

the "opinionated" part of deftype (https://clojure.org/reference/datatypes#_datatypes_and_protocols_are_opinionated) is that "You should always program to protocols or interfaces"

borkdude18:01:48

I even took this from your blog. Although it was about defrecords, I figured the same approach would work: https://puredanger.github.io/tech.puredanger.com/2010/06/30/using-records-from-a-different-namespace-in-clojure/

borkdude18:01:03

anyway, never mind. I was trying a deftype to see if it did anything for performance (for Clojure, in cljc), but in this case, it didn't matter, so I reverted it to a map again

Alex Miller (Clojure team)19:01:00

That blog was from right after records/types came out and some things did change after that