Fork me on GitHub

I’m not finding a build hook that’s working for me, looking for some advice. I need to run some code that generates a new routes file (details not really important) based on files in a directory. This should really run before shadow does anything, but there’s not really a hook for that. I’m trying to repurpose my function to run on the :configure step, and the :compile-prepare step, but that’s not working so swell


@thheller thanks for the project 🙂. Was running into issues getting react and some npm react components to play nice together, and noticed some funky javascript output with fighweel. switched to shadow-cljs and it fixed my issue.

👍 4

++ shadow is the gold standard @justtaft


@haywood if you want something to run before shadow-cljs does anything then run it separately 😛


I'm writing an override of require for node-test target how can I make sure it's added at the top of the js file


override how?


I'm assuming for all the custom mods we talked about last time?


you can't really override actual node require


    var Module = require('module');
    var originalRequire = Module.prototype.require;

    Module.prototype.require = function(){
        // if react-native module return mock
        return originalRequire.apply(this, arguments);


right. I would keep this totally separate probably.


and when you run node you run node --require=./your-require-override.js the-output.js


you can make it part of the build also but I prefer to keep hacks in a place I can easily experiment with 😛


but if I want to write it in cljs then I need to have a separate build config for it?


write what in CLJS? the override mechanism?


yeah I was thinking of giving it a shot since I already have all the mocks in cljs


hmm the issue is that its not easy to ensure that its actually loaded before require is first used


so I wouldn't recommend trying that


it is easier in development because you can abuse :preloads but there is no :preloads-that-also-apply-in-release


before I go further it seems like my first issue with the react-native modules in node is that they are using import

SyntaxError: Cannot use import statement outside a module


it looks like the issue is that I get a require when it should be an import shadow.js.shim.module$react_native_languages = require("react-native-languages");


yes. most react-native modules cannot be loaded in node. they are packaged with the assumption of going through metro first.


I thought that is why you are mocking them?


yes that is not a useful path to explore indeed, even if I manage to get them to run in node they will most likely yield odd results or errors


so, i removed my question because I found in the docs the environment variable part but actually it's not what I need, or at least only part of it. I still don't know how I can read the value of anything I pass to shadow-cljs inside my app. I am happy to use --config-merge or anything else, but that's just setting the value, what is the keyword to search for to find how to read what I set there?


@thheller looks like the solution with a separate js file works, on every error I mock the lib that fails and move to the next error. Since I already have the mocks in cljs and I find it more pleasant to write what would be the right approach? So far I have a frankenstein 😄 I put my mock cljs file in the path that is compiled by :test and I wrote an override.js that imports it, probably the worst possible way by copy pasting most of the shadow init code


(it does work though)


but in general I advise everyone against using environment variables in CLJS builds. just pass that data into your code at runtime instead


@thheller what do you mean pass code at runtime


pass the data


assuming you are following the recommendations of having a init fn that is called when your code is loaded




(defn init [the-data] ...)


can pass the data in as a regular JSON object


or edn encoded string


whatever you want really


how is going to help me to have different values for different builds


The problem I am trying to solve is that there are a number of servers I need to connect to depending on the environment


django runs on one port for me, another for others and definitely different port in production


then you adjust whatever generates <script>"with-the-data-you-need");</script>


my devenv is devcards, thats' one port but when my boss checks my work, he will use the development build which is served by django in development mode which of course has it's own dev config


so I need something that generates that, thanks


we just use static files at the moment


just have different html files ...


index.html index-dev.html index-boss.html etc


... that just exports the problem from shadow-cljs into django, I don't want to learn python 🙂


if that pattern doesn't fit then use the env+closure-defines


the thing is, no one wants to use cljs just me, if I have to commit code that changes everyone's codebase, there will be comments


I don't have a clue what you are doing so you are going to have to do something that works for you


I just realized something, I am not doing anything special, I created this project with create-cljs-app. There are no js files with init functions. I am trying to find how to pass data to my apps still, but so far only the closure-defines is the only thing that is somewhat similar, and even that I haven't yet been able to figure out how it actually expected to work. 🙂


I think this create-cljs-app thing uses clojurescript to do this init calling thing since I have something like a main function exported and called with render, and the main function is configured in :init-fn. So if I understand your previous suggestions correctly, I should just write my configuration inside my core.cljs and cards.cljs files that call the render functions


if the build config contains :init-fn some.ns/init then yes that calls init without args. you can will put the config into the html via <script>_CONFIG = "whatever";</script> and access it in into via (js/console.log js/MY_CONFIG)


this also makes sense now, in hindsight.


🙂 thanks for the help, I will figure out something


I'm getting a maximal call stack size exceeded when running my tests

SHADOW import error /home/yenda/status-react/target/test/cljs-runtime/shadow.module.main.append.js
function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {

RangeError: Maximum call stack size exceeded
    at compareByGeneratedPositionsDeflated (/home/yenda/status-react/node_modules/source-map/lib/util.js:343:45)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:88:11)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)


could it be because I have most of the SHADOW_IMPORT statements twice with my require override?


(let [react-dom-server (js/require "react-dom/server")]
      (.renderToStaticMarkup react-dom-server src))))
I’m just wondering, is this kind of approach something that Shadow’s npm module system supports?


I don't understand the question? shadow-cljs does not bundle js/require calls in browser builds. if this runs in an environment that has an actual js/require then it would work but shadow-cljs has no hand in that?


This is for a node build. I guess I’m wondering if in node builds the ns require is needed for the npm module to be included in release builds? I hope that question makes more sense, sorry 🙂


in node builds shadow-cljs doesn't include anything into the build


it literally just writes require("a-thing") if you (:require ["a-thing" :as x])


got it, thanks!


but yes ... if you want shadow-cljs to bundle things then it must be in the ns form. it does not pick up js/require calls in the code


it could pick up js/require calls but that might give people ideas of using it dynamically and so on which won't work


uhm. what’s the difference between “bundle” and “include anything into the build”?


in node builds in general it will create a regular .js file that still has require calls in the code


node will take care of those and provide the dependencies at runtime


in the browser we obviously can't do that so shadow-cljs does not generate require calls


and instead bundles all the required code into the output directly so it can be loaded at runtime


so a browser build would contain react and so on while a node build will not (by default)


Ok, I think that makes sense. Bundling isn’t really a (necessary) thing in node.


you can still enable it if needed but it is off by default since node can just provide it


I don't know what's with me and with clojre(script) tooling, but this continuous struggle of reading thousands of words with no results is really upsetting. I've given up for 8 years because of this, and I really feel like shadowcljs works, but to not be able to do something as simple as to set a build dependent variable for hours, despite getting help from the creator himself, is just upsetting^2. In js I know I have a bundler, browserify or webpack, I select the env plugin, use bash env variables in the terminal, then I can read them either through some module or on global/window. Not nice, but the whole process took less than 30 minutes the first time I had to do it. I've been trying to do this for 4 HOURS continously. I've read everything twice, I don't know what I missed but at this point I wish I could just quite and go fishing instead.


  {:target :browser
   :modules {:app {:entries []}}
   ;; to enable in development only
   :dev {:closure-defines { true}}
   ;; to enable always
   :closure-defines { true}
   ;; you may also enable it for release as well
   :release {:closure-defines { true}}


as I described it above, the problem for me here is that this is INPUT, and I would rather read the variable, not just write it


(ns )

(goog-define VERBOSE false)


think of that like (def VERBOSE false)


trying to (prn VERBOSE) I only got the value that I defined inline in the file, the config didn't overwrite it


so you use it like any other def


well how did you set it?


the way you see it in the file at the root of this thread


which one? those are multiple different examples rolled into one?


do you use project.clj or deps.edn instead of just shadow-cljs.edn? in that case you might have the wrong clojurescript/closure-library versions in which case closure-defines don't work properly


oh, i am so stupid


of course it didn't work


I tried to do two things at once. thanks again @thheller and @U11BV7MTK


Is there a known cause for these sort of maximal call stack size exceeded errors?

SHADOW import error /home/yenda/status-react/target/test/cljs-runtime/shadow.module.main.append.js

function strcmp(aStr1, aStr2) {
RangeError: Maximum call stack size exceeded
    at strcmp (/home/yenda/status-react/node_modules/source-map/lib/util.js:373:16)
    at compareByGeneratedPositionsDeflated (/home/yenda/status-react/node_modules/source-map/lib/util.js:354:9)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:88:11)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)
    at doQuickSort (/home/yenda/status-react/node_modules/source-map/lib/quick-sort.js:99:5)


I run the tests with yarn shadow-cljs compile mocks && yarn shadow-cljs compile test && node --require ./test-resources/override.js target/test/test.js override.js is here


this particular test didn't yield any error with the doo+lein stack. I also noticed that there was another test that was failing with the same kind of error, but in that case it was just a test that wasn't run with doo and was wrong, but instead of a proper assertion fail it was throwing this callstack error


source-map also modifies require I think so you might just get in its way?


try running against a release build. that won't include the source-map package (unless you do manually)


interesting start with a warning in release build:

Resource: mocks/js_dependencies.cljs:47:1
 constant ReactNative assigned a value more than once.
Original definition at externs.shadow.js:2


but yeah looks like it is related to sourcemap require because I see

ERROR in (add-received-message-test) (TypeError:NaN:NaN)
Uncaught exception, not in assertion.
expected: nil
  actual: #object[TypeError TypeError: lV.a is not a function]
DEBUG [status-im.native-module.core:259] - [native-module] is24Hour


so probably some function call that wasn't mocked


you can turn off source maps then it won't include that package


just makes debugging a bit annoying 😛


well it's tests anyway


easier to debug

ERROR in (add-received-message-test) (TypeError:NaN:NaN)
Uncaught exception, not in assertion.
expected: nil
  actual: #object[TypeError TypeError:$core$IFn$_invoke$arity$2 is not a function]
than random max call stack exceeded 😄


shadow-cljs release tests --debug also helps


what does it do? I just get an extra warning about tufte


it looks like it's because of the with-redefs in the test


if you need with-redefs when you should set :compiler-options {:static-fns false}


thanks! totally worked

Andrea Russo17:04:50

Did someone have success in importing react bootstrap in a shadow-cljs project?


should just be able to npm install it and start using it right?


reagent’s react interop is great, I’m using the EUI library just fine.

Andrea Russo17:04:53

npm installed react-bootstrap and I’m not able to do a simple (:require [“react-boostrap/Button” :default Button])


:as Button?

Andrea Russo17:04:58

it seems that the react-bootsrap npm module is written in TypeScript

Andrea Russo17:04:05

full of .ts files

Andrea Russo17:04:23

@haywood yes, tried that too


not to be overly pedantic, but I refer to this chart a lot


I think the ts files are just the source files, if you look in the package.json it’ll point to the package’s main directory


(in the node_modules folder)

Andrea Russo17:04:56

I’ve found the js files, in node_modules/react-bootstrap/esm

Andrea Russo17:04:29

but requiring [“react-boostrap/esm/Button” :as Button] doesn’t work

Andrea Russo17:04:01

Search in: /Users/arusso/Development/clojurescript/dias-web/node_modules You probably need to run: npm install react-boostrap/esm/Button

Andrea Russo17:04:39

maybe I can force the resolver by telling something like this?

Andrea Russo17:04:47

:js-options {:resolve {“react-bootstrap” {:target :npm :require “react-bootstrap/esm”}}}

Andrea Russo17:04:57

doesn’t work 😩


I wouldn't want to use esm modules yet if I could avoid it. Is that package published using exclusively those?

Andrea Russo18:04:12

I don’t know

Andrea Russo18:04:17

I nee to check that


in any case, the link above to the UserGuide explains how to load npm packages, the npm error saying that you have to iunstall react-bootstrap/esm/Button sounds wrong


have you tried just ["react-bootstrap/Button" :as Button]?

Andrea Russo18:04:29

yes I tried it also


and what was the error?

Andrea Russo18:04:57

always the same:

Andrea Russo18:04:58

Search in: /Users/arusso/Development/clojurescript/dias-web/node_modules You probably need to run: npm install react-boostrap/Button


I’m gonna try it locally, have me curious

Andrea Russo18:04:51

I’m using this template project:

Andrea Russo18:04:21

lein new re-frame <project-name> 

Andrea Russo18:04:50

just do a npm install react-bootstrap


eh I’m just installing into my project


this package is pretty weird though looking at the node_modules directory


yea just not working and I’m not sure why


the package.json points to main: cjs/index.js, and if you go to that file it’s exporting everything


["react-bootstrap" :refer (Button)]

Andrea Russo09:04:28

Did it work for you? I’m trying it but without success

Andrea Russo09:04:40

It works! Wonderful, I was sure I tried also that! Thank you very much @haywood


you can do [Button] too


I need to run a process that reads files from one of my apps directories, this process creates and writes a new clojurescript file to disk, which Shadow knob should I be using? It should run during startup and on changes.


I’m quite new to Clojurescript but have quite a bit of experience with Clojure. I’m interested in interacting with Excel using @microsoft/office-js``. I use the shadow-cljs re-frame example for experiments and modified the namespace declaration in views.clj`` to be

(ns demo.views (:require [demo.routes :as routes] [demo.subs :as subs] [re-frame.core :as re-frame] ["@microsoft/office-js" :as office]))
and get the error
[:app] Compiling ... [:app] Build failure: module without entry or suffix: @microsoft/office-js
ExceptionInfo: module without entry or suffix: @microsoft/office-js
	Clojure.core/ex-info (core.clj:4739)
	clojure.core/ex-info (core.clj:4739) (npm.clj:207) (npm.clj:165) (npm.clj:387) (npm.clj:358)* (npm.clj:618)* (npm.clj:610)
Any hints to where I might start looking for the problem?


it’s sorta saying you can copy the file in the dist directory to your static server, or you need to compile it yourself?


easiest thing to do for now would be to `

<script src="/assets/office-js/office.js"></script>


where you copy it to resources/public/js]


and just refer to the global variable that file creates via js/office


yeah microsoft things are very unfriendly towards packaging


probably best to follow their instructions


I’ll try that - thanks


ok @thheller thanks for the tough love. I think I got what I needed by hooking into the :configure stage on startup, and then just running my own fs-watch that runs independently, so it’ll run even if shadow fails. Thanks