How ready is cherry now for web development?
The compiler is pretty stable now. There is no squint.edn for cherry yet and cherry doesn't have watchi functionality yet (might be easy to port it over from squint though).
for web dev there isn't a REPL yet, although I do have a REPL in the playground. the compiler is able to generate REPL-compliant code, but the plumbing to make it work in a browser via nREPL hasn't been done
I think REPL might be slightly less of a concern for frontend web dev since the typical workflow is to do live preview (e.g. vite dev).
For that, Squint has https://github.com/brandonstubbs/vite-plugin-squint which can probably be cloned to create a vite-plugin-cherry so incremental Cherry compile + hot module reload (HMR) is triggered whenever a .cljs file is updated.
Wait nevermind, vite-plugin-squint doesn't support HMR yet.
Looks like the to-do list in the README might be wrong. There's a handleHotUpdate handler.
I don't use any plugin myself. The compilation model of squint and cherry is simple. Whenever a file changes, you can re-compile it using a watcher. Then the JS tooling can pick up on the compiled JS.
Can I use re-frame, reagent, and UIx with cherry as I can with clojurescript? Can I use cherry stack in production?
Damn. You found a use case for cherry in production, but that looks complicated. People were driven away from clojurscript by build complexity.
Borkdude, your example seems deceptively simple.
If you want to avoid builds #scittle might be interesting but otherwise you always have some build stuff unless you use plain JS
Once Cherry/Squint supports enough Clojure features for Closure-library-free CLJS libraries to "just work", you can remove CLJS from the equation (ignoring dead code elimination parity between the Closure compiler and JS tree-shakers). For the time being, however, you need to do this kind of stitching if you want to use CLJS libraries. If you just need a small glue layer to stitch JavaScript libraries together with Clojure syntax, you can use just Cherry/Squint standalone.
My other observation today is that it appears that these problems of having to manually enumerate go away if everything is in the same directory. My workaround at the moment is to just stop having impl and other subdirectories, as unideal as that may be.
I'm not doing frontend work, so at the moment, esbuild is likely my goto rather than vite.
yeah cherry is more limited than squint, since we don't have a cherry.edn config file, it assumes stuff to be in either src or the root dir
Working with it more it makes sense — if the NPM/JSish method is to esbuild it all up at the end for a dist/ version, if it can’t all fit in one big directory, maybe it’s time for a second package at that point.
Different than a big jar
Still working through it, but this seems like it may work in terms of referring across different namespaces in package.json — compile each one with npx cherry other_cherry_ns.cljs, then re-reference them so the modules resolve correctly.
“exports”: {
“.”: “./main_cherry_export_namespace.mjs”,
“./foo.bar.other-cherry-ns”: “./impl/other_cherry_ns.mjs”,
“./yet.another.cherry-ns”: “./impl/yet_another.mjs”
},
Manually enumerating all namespaces as export entrypoints in package.json sounds pretty painful.
If you're using Vite or Rollup, you're better off having a plugin like vite-plugin-squint which hooks into Vite/Rollup's import processing hooks.
There's basically 2 hooks they expose:
1. resolveId
a. Transforms an import "{id}" ESM import statement. For example, a plugin can turn every import "{namespace}.cljs" statement into import "{absolute CLJS file path}.cljs.js".
2. load
a. Returns the contents for a given resolved ID. For example, it can match on *.cljs.js files, strip off the trailing .js to find the absolute path of the source CLJS file, invoke Squint/Cherry's compileString method, and return the compiled result.
This is effectively what vite-plugin-squint does (though it always compiles to .cljs.jsx files instead because JSX is a superset of JS).
https://github.com/brandonstubbs/vite-plugin-squint/blob/main/index.mjs
The handleHotUpdate hook is specific to Vite for hot module replacement (HMR).
With vite-plugin-squint, you can import a CLJS file directly in a :require statement and it just works.
https://github.com/brandonstubbs/vite-plugin-squint/blob/0f932fb72da83e1e93ffc39bdef9d7c7a6d7d37c/demo/react/src/main.cljs#L4
I don't think so since neither Cherry nor Squint support user namespace requires yet so you can't import the re-frame, reagent, or UIx namespaces. https://github.com/squint-cljs/cherry/issues/64 There's also other missing features like multimethods. https://github.com/squint-cljs/cherry/issues/35
user namespaces are supported in squint if you use a squint.edn file. but dependencies from clojars aren't directly supported and indeed, there are some differences. So when it comes to CLJS compatibility you're just better off with regular CLJS.
another differences is that there is no goog.*
Because cherry doesn't support user namespaces that come from cherry libraries, I guess it's far from being ready for production.
You can refer to other compiled JS files like any other JS library
So you technically don’t need to refer to “namespaces”
Can you show me a minimal example of referring to compiled JS files?
There might an example in the examples dir. I’m not at a computer right now but will come back at this later
@amano.kenji I made an example here: https://github.com/squint-cljs/cherry/blob/d290d4180715091cf67ac6fc79d0bb1178bee722/examples/vite/counter.cljs#L2 This refers to a compiled version of: https://github.com/squint-cljs/cherry/blob/main/examples/vite/my_function.cljs
Depending on your frontend library stack of choice, you'll either use:
• Pure CLJS
◦ Typically with shadow-cljs for its better Node.js package interop configs.
• CLJS + Cherry/Squint
◦ CLJS for Clojure libraries that need CLJS's full feature set.
◦ Cherry/Squint for interfacing with Node.js packages that don't play nice with the Closure compiler or for hooking into JS build tools like Vite.
▪︎ Many frontend frameworks have their own custom template formats (e.g. .jsx, .vue, .svelte) which CLJS can't output.
▪︎ Cherry/Squint, however, can output .jsx with its #jsx literal so with a Vite plugin, this can seamlessly integrate with JSX-based frameworks like Solid.js, React, and Preact.
◦ For live reload in both halves of the chain (CLJS via shadow-cljs + Vite), you would do:
▪︎ CLJS
• Configure shadow-cljs to output to a well-known directory (e.g. ./generated).
• shadow-cljs watch
▪︎ Vite
• Configure a Vite alias to point to the shadow-cljs output directory (e.g. $generated → ./generated) so you can do import '$generated/{cljs output}.js' (for JS files) or (:require ["$generated/{cljs output}.js"]) (for Cherry/Squint files) in files under Vite's purview.
• vite dev
In a wild dream, I’m thinking that I could author BigQuery UDFs (which are natively Javascript) in Cherry assuming I can load the standard library from a Google storage bucket. Has anyone tried this? Is there some reason it wouldn’t work?
I don't see why not. Just compile the thing and put it on GS? I found a maybe related article. It mentions webpack but I think I'd use vite nowadays https://medium.com/swlh/how-to-package-a-javascript-library-for-use-in-bigquery-2bf91061f66f
thanks! I’ll take a look