Fork me on GitHub

@mikerod I don't see how that isn't solved by one level of indirection


You write your own thing that requires the generated CLJS entry point and you feed the bundler your entry point


That's an interesting point. I get what you're saying. I'll give that a try

Muhammad Hamza Chippa11:02:29

Does anyone use material-ui in the clojurescript. I am trying to use in my codebase but unable to use make-styles and styled-component type of thing. I try to replicate this simple code in cljs but it is not working REACT CODE

import * as React from 'react';
import { makeStyles } from '@mui/styles';
import Button from '@mui/material/Button';

const useStyles = makeStyles({
  root: {
    background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
    border: 0,
    borderRadius: 3,
    boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
    color: 'white',
    height: 48,
    padding: '0 30px',

export default function Hook() {
  const classes = useStyles();
  return <Button className={classes.root}>Hook</Button>;
 (:require [reagent.core :as r]
            [reagent.dom :as dom]
[reagent-mui.material.button :refer [button]]
[reagent-mui.jss-styles :refer [make-styles with-styles styled with-theme]]

(defn usestyles [] (make-styles {
                             :root {:background "linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)"
                                    :border 0
                                    :borderRadius 3
                                    :boxShadow "'0 3px 5px 2px rgba(255, 105, 135, .3)'"
                                    :color "white"
                                    :height 48
                                    :padding "0 30px"

(def classes (usestyles))

 [button {:class-name (:root classes)}


Have you read the documentation of make-styles?

Muhammad Hamza Chippa11:02:09

yes yes I have extensively use make-styles in the react codebase but somehow it is not working in cljs codebase


There's also a test in the reagent-mui repo that shows how to use that function.

Muhammad Hamza Chippa11:02:35

it will be a great favor if you share the link ?


No, not in the React codebase. Read the documentation specifically of the reagent-mui.jss-styles/make-styles.


Just search the repo for the word make-styles?


Seems like it.


For some reason cljsbuild is adding the following errors to my compiled JS. Any hints as to why this might be happening?

// Compiled by ClojureScript 1.10.764 {:language-out :ecmascript-next}
Warning: environ value 8u312 for key :java-version has been overwritten with 1.8.0_312
Warning: environ value /usr/local/openjdk-8 for key :java-home has been overwritten with /usr/local/openjdk-8/jre


seems I needed to set JAVA_HOME and JAVA_VERSIONS for the compile command: something like this;

[email protected]:/tmp# JAVA_HOME=/usr/local/openjdk-8/jre JAVA_VERSION=1.8.0_312 lein doo chrome-headless-no-sandbox test once


@mikerod fwiw, :bundle :target is intentionally simplistic because it was clear that there's a lot of patterns that need to be supported that we don't necessarily want to write into the compiler


@dnolen Yeah, I can certainly understand that & I figured that was the case. I want to try this extra level of indirection idea today & see how it goes. I’m also looking to see how it works if I’m using the :bundle :target as a cljs-library too. I’m curious how much work/redundancy it will be on my other app’s config that use this lib. They’ll have to also pull the CSS, which is somewhat of a “transitive dependency” to them at that point - if that makes sense.


but also to make sure it was easy to create the next level of tooling


everything you mentioned was applied when I started on Krell

👍 1

the entrypoint is is not the ClojureScript one - but one that loads RN stuff


also custom passes to do asset collection etc.


the idea being that, :bundle :target leaves the door wide open for anyone to produce affordances and reduce boilerplate


w/o introducing all that churn into ClojureScript


That’s quite interesting. I wish there were more publicly shared examples of doing things a bit more sophisticated like this. Just to get a look at how people have addressed some of these fairly common concerns. Your work sounds certainly relevant.


I’m trying to migrate over to :bundle :target. I was doing it all manually before. The way it was described prior to :bundle helping out. I think it is looking promising though at some good boilerplate reduction. This could definitely be a good thing for my org where the old way has quite a bit of steps to enumerate in each project we do (which is a growing number).


hrm, transitive CSS is an annoying case


Yeah. My situation is basically we have a common UI “components” library that we use by a bunch of our actual top-level applications. Prior to :bundle :target, there was basically this boilerplate, webpack config + webpack entry point + npm package.json + CLJS :foreign-libs declaration that the library project used itself for testing, but also all my top-level applications also had to replicate basically the same way so the “transitive npm deps” were brought in as needed by the library. So my hope with :bundle :target was that the “downstream” top-level applications will no longer have to repeat so much of this boilerplate. I haven’t gotten that far yet though. The CSS was one thing I immediately noticed I’ll have to still have a pattern for. Some of the npm dependencies my UI “components” lib has have css that you’d typically bring in via, eg.:

import "react-resizable/css/styles.css";
I cannot just use a CDN or some external reference to it in my particular case since my top-level applications need to be basically “self contained” because the env they are deployed in cannot call out to arbitrary public IPs (an on-premise/firewalled sort of usage).


@mikerod let's take this to #cljs-dev I have some thoughts

👍 1

A separate question from me. I have tried to post it on, but I’m having difficulty with it allowing me to post topics for some reason (WIP). Using this setup: deps.edn

{:deps {org.clojure/clojurescript {:mvn/version "1.11.4"}}}
(ns example.macrotrouble.core
  (:require [example.macrotrouble.util :as u]))

(def o (js-obj "x" 10))

(u/defprop my-x o "x")
(ns example.macrotrouble.util
  #?(:cljs (:require [goog.object]))
  #?(:cljs (:require-macros [example.macrotrouble.util])))

(defmacro defprop [n o prop-name]
  `(def ~n (goog.object/get ~o ~prop-name)))
Then running:
clj -M --main cljs.main --compile example.macrotrouble.core --repl
The browser JS console immediately shows:
Uncaught TypeError: Cannot read properties of undefined (reading 'get')
    at core.js:8:84
The same can be recreated at the repl, via require + :reload of the ns in question. The fix is to also require the “invisible” goog.object usage of the core ns coming from the macro expansion:
(ns example.macrotrouble.core
  (:require [goog.object]
            [example.macrotrouble.util :as u]))
This surprised me due to the fact that it is leaking out that the macroexpansion is requiring other ns’s. Is this some special issue only occurring due to it being a goog.* ns?


This is not specific to goog stuff - it's a proper fix and you have to use it for all such namespaces.


macros cannot emit a direct use of goog.object anymore since


instead create a helper function in the macro ns that calls goog.object/get


or just use unchecked-get


Which is marked as INTERNAL. :D


Yeah, I am fine with just wrapping the calls in a wrapper “normal fn”, if that means the callers do not have to care about it




Ok so a bit more on this question.


I didn't think I was assuming goog was required globally


My macro ns requires it.


its a bit annoying but goog.module namespaces are now basically a local reference. so it ends up missing when the ns that the code ends up in doesn't have it.


Yeah, I think I understand. However, this is quite sneaky.


I did read that blog post before originally and just assumed it meant if I actually left off the :require in the macro definition ns.


@mikerod goog.module does not create a global refernce


and any GCL namespace can become a goog.module


there you cannot ever rely on some GCL namespace existing globally


you can safely assume this for ClojureScript namespaces as that aligns w/ Clojure expectation, but not GCL


Ok. It sounds like if you wrap the goog.object/get reference in a defn instead and use that in the macro form returned, I can workaround the problem of the callers having to require goog.object as well.


If that works, I feel it isn’t a major problem, just a little sneaky to remember.