Fork me on GitHub

Error when running shadow-cljs release app:

Closure compilation failed with 1 errors
--- app/components/user/payment.js:2
Cannot import Closure files by path. Use either import goog:namespace or goog.require(namespace)
import { firebaseapp } from 'goog:app.helpers.firebase';
import firebase from 'firebase/compat/app'; <--- error here
import 'firebase/compat/functions';
(ns app.components.user.index
   ["antd" :refer (Avatar Button Dropdown Menu Skeleton Spin)]
   ["@ant-design/icons" :refer (LoadingOutlined)]
   [reagent.core :as r]
   ["firebase/compat/app" :default firebase]
   [app.helpers.macros :refer [if-let-n]]
   ["./payment" :refer (onAuth openCheckout openCustomerPortal onActiveSubscription)] <---- imports
   [re-frame.core :as rf]
   [cljs.core.match :refer [match]]))
Stuck on debugging this. I hope someone can help 🙂


import { firebaseapp } from 'goog:app.helpers.firebase'; should be import firebaseapp from 'goog:app.helpers.firebase';


or probably import firebase_helper from 'goog:app.helpers.firebase'; firebase_helper.firebaseapp assuming thats a def in the ns?


Doesn't work. Same error message. payment.js

import firebase_helper from 'goog:app.helpers.firebase';
import firebase from 'firebase/compat/app'; <-- error points to this line
import 'firebase/compat/functions';

const { firebaseapp } = firebase_helper;
(ns app.helpers.firebase
  (:require ["firebase/compat/app" :default firebase]
            [app.envvars.core :refer [APP_ENV]]))


(def ^:export firebaseapp (.initializeApp firebase (if (= APP_ENV "production") firebase-prod-config firebase-dev-config)))


shadow-cljs watch app still works though.


just not able to compile release version


I'm unsure what this might be. what happens if you remove that line?


That worked:white_check_mark: Hehe i don’t know why i included this line. But weird that it fails compilation with it.


Hi all! I just setup TailwindCSS, which is parsing the ShadowCLJS’s app.js to figure out which CSS classes have been used, but can not extract some class names because instead of quotes the app.js contains escaped unicode characters `\x22`  like this: `\x22flex justify-between items-center border-b-2 border-gray-100 py-6 md:justify-start md:space-x-10\x22` . Did anyone experience the same issue?


I found a workaround: Adding an empty space at beginning and end of the class string did the trick. Before: [:nav {:class "hidden md:flex space-x-10"} After: [:nav {:class " hidden md:flex space-x-10 "} @thheller I wonder if there is some setting which would make class names automatically recognizable?


I've never seen that? which is the JS like this?


oh wait you are talking about a development watch build I assume?


yes, exactly


the file is ./target/cljsbuild/public/js/app.js


for development builds the code uses eval to load the sources. thats why you see the \x22


for development you should be pointing tailwind at the cljs-runtime dir. those are normal files with the proper strings


target/cljsbuild/public/js/cljs-runtime that is


for release builds you can point it at just the app.js


In our setup we just create the whitelist manually, because last time I checked tailwind / purgeCSS doesn't know about the reagent class syntax. If you use reagent, you'll need to change some values for that to work out too, e.g., w-1.5 -> w-1*5


w-1.5 is not a valid classname. I generally just keep everything in :class "..." and don't use :div.class at all


cool, thanks @thheller for the quick support!


w-1.5 is a valid classname, it is just that div.w-1.5 is not valid reagent syntax (that is why we changed it). See the docs here to see w-1.5:


I'm debugging an issue related to :optimize-constants that I think I've bisected down to 2.15.13 (`2.15.12` and before seem to work fine, 2.15.13 and after seem to have the issue). In particular, after 2.15.13, many keyword constants in the code seem to not be assigned. Some keywords (like var cljs$cst$keyword$shouldComponentUpdate=new cljs$core$Keyword(null,"shouldComponentUpdate", "shouldComponentUpdate",1795750960)) are properly created once and all callsites properly reference this global cljs$cst$keyword$XXXXXXXX var, others (like new cljs$core$Keyword(null,"body","body",-2049205669)) are created new every time. Has anyone observed anything similar to this before? Appreciate any help.


@leiferiksonventures is :body maybe only used in one place? maybe the closure compiler is trying to be too smart for its own good?


closure compiler as an optimization might inline the new call to safe the var. that would be my only guess?


@thheller In this case, :body is used 36 times. My most extreme example is :recur (due to plenty of cljs.core.async), which is allocated at 3560 callsites as new cljs$core$Keyword(null,"recur","recur",-437573268).


it should inline all of them but :optimize-constants is not a thing in shadow-cljs so maybe something else is going on?


constants are optimized as a compiler pass during optimizations. not by the cljs compiler


you may also try :compiler-options {:shadow-keywords true}. that optimizes them a little more


Just checked :shadow-keywords and still have the same issue (some keywords are fine, others are repeatedly reallocated). I did see that 2.15.13 bumped the cljs / closure compiler versions ( -- maybe that's where the issue lies.


hmm indeed. I also see this now. I'll look into it


should be fixed in 2.17.0. thanks for the report. there really should be a test for this. went unnoticed for too long.


fun thing was that the replacement was working totally fine except that some keywords have a precomputed numeric negative hash


and the compiler pass was only looking for numbers


and some time ago the closure compiler changed how they represent negative numbers in the AST


so some keywords/symbols would still be replaced while others were not


Wow -- excellent. Thank you for the update. Nice find. Tricky bug too.


I also see that the latest version of shadow-cljs fixes the issues I was having with Material UI (that was keeping me on ES5 output v.s. ES6 output). Thank you! Very awesome.

Jimmy Miller19:02:10

So, I am looking at including some cljs in a js web app. I looked at various targets most importantly :npm-module, and :esm. I read a bunch of issues about various tradeoffs. Was unsure what to pick. But a coworker of mine just tried target :browser and loading that into webpack works perfectly fine. Maybe I'm missing it, but it seems like from the documentation that isn't what I'd expect. It seems like those other targets are there to make it work with existing js apps. Now there was one limitation, I couldn't control exports at a fine-grained level, just exporting whole namespaces. Adding a simple little js with some imports and re-exports fixed that all though. So I guess my question is, am I missing something? Is there a reason I shouldn't use target browser + a shim to do this? Is this something that just happens to work but might break in the future? Could target :browser add an exports like esm and make it work with existing js stuff without the nested namespace object?


we use :npm-module for metabase. • shadow-cljs.edn: • exported var: • imported into js: • webpack: and

Jimmy Miller19:02:39

Yeah, ran into issues with "goog.promise" is not found that I never dug into on :npm-module. Also the talk of deprecation made me a bit hesitant. Thanks for the links though 🙂


yeah i don’t have much more on tradeoffs but if you want to consult how it works for us its all open


:npm-module is best for integration with other tools currently. :browser by default will bundle all JS dependencies on its own in a way that webpack can't see. so you'll end up with duplicated ones such as react for example


although I regret some of the :npm-module design it'll likely stay as is

Jimmy Miller05:02:20

Ahh, got ya. I will definitely try to figure out the issues we were having with :npm-module. Right now, that limitation isn’t too big of a deal for us though, we don’t have dependencies in common with the js project. But that will probably change over time. Glad to hear that :npm-module will stay put. Makes me feel better about using it.


why do browser builds take so much longer to compile compared to react-native builds? At first thought it was standard cljs->js compilation but if the native builds are much faster for same app must be other reasons


define "so much longer"? browser builds bundle JS so if you include 5000 npm deps that'll take a while. react-native does not bundle since metro will be doing that, so technically you have to add the metro time.


Oh ok that makes sense. Since react native libraries ship their JS already transpiled. Does shadow cache npm dep bundling or is there concerns against that?


its cached yes


hm to be clear - i meant on initial build, is the cache used or are packages compiled just incase?


not sure which cache you are refering to. there is none on initial build.


you have given me no data to comment or know what you are talking about


so please provide more data if you have more questions


like actual build time, files in build, etc


Im not diagnosing a specific issue, was asking a general question. My main q was answered above so thanks, and will follow up w more data if I notice anything that can be fixed


yes, I'd like to answer. but you haven't given me any details on how your build actually takes and if by react-native you mean :target :react-native in shadow-cljs or react-native alone


also you have not defined "so much longer"? what does that mean? for some people 1sec is "so much longer". for some it is 30sec. I don't know and can't answer.


Yes sorry about ambiguity as I know you're always assisting with questions and lack of context doesn't help. Next time I give my project a run (on mobile now) I'll check and see if anything's worth reporting


(For above I meant target :react-native versus :browser, yes. Can't remember build times but it was fresh project)


it's javascript