Fork me on GitHub
#clojurescript
<
2022-02-03
>
dnolen00:02:52

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

dnolen00:02:40

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

mikerod00:02:14

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 https://github.com/arttuka/reagent-material-ui 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>;
}
CLJS CODE
(ns  
 (: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)}
     "Hamza"]

p-himik11:02:40

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

p-himik11:02:13

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 ?

p-himik11:02:36

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

p-himik11:02:51

Just search the repo for the word make-styles?

p-himik11:02:23

Seems like it.

Franklin12:02:42

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

Franklin12:02:00

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

root@cf144c04da13:/tmp# JAVA_HOME=/usr/local/openjdk-8/jre JAVA_VERSION=1.8.0_312 lein doo chrome-headless-no-sandbox test once

dnolen15:02:48

@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

mikerod15:02:35

@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.

dnolen15:02:35

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

dnolen15:02:57

everything you mentioned was applied when I started on Krell

👍 1
dnolen15:02:09

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

dnolen15:02:18

also custom passes to do asset collection etc.

dnolen15:02:45

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

dnolen15:02:56

w/o introducing all that churn into ClojureScript

mikerod15:02:05

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.

mikerod15:02:46

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).

dnolen15:02:02

hrm, transitive CSS is an annoying case

mikerod17:02:05

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).

dnolen17:02:44

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

👍 1
mikerod19:02:17

A separate question from me. I have tried to post it on http://clojureverse.org, 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"}}}
src/example/macrotrouble/core.cljs
(ns example.macrotrouble.core
  (:require [example.macrotrouble.util :as u]))

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

(u/defprop my-x o "x")
src/example/macrotrouble/util.cljc
(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?

p-himik19:02:35

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

thheller19:02:57

macros cannot emit a direct use of goog.object anymore since https://clojurescript.org/news/2021-11-04-release

thheller19:02:14

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

thheller19:02:29

or just use unchecked-get

p-himik19:02:51

Which is marked as INTERNAL. :D

mikerod19:02:17

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

mikerod19:02:21

Interesting

mikerod19:02:31

Ok so a bit more on this question.

mikerod19:02:41

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

mikerod19:02:47

My macro ns requires it.

thheller19:02:36

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.

mikerod19:02:14

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

mikerod19:02:29

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.

dnolen20:02:26

@mikerod goog.module does not create a global refernce

dnolen20:02:39

and any GCL namespace can become a goog.module

dnolen20:02:56

there you cannot ever rely on some GCL namespace existing globally

dnolen20:02:36

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

mikerod21:02:01

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.

mikerod21:02:23

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