If I read the docs correctly, there is currently no support for ESM output (`:target :esm`) to "dynamically" output esm files, like :target :npm-module with :ns-regexp works?
I was looking at the options to export modules for StoryBook, their recommended default builder is VIte which works with ESM. But I could also just keep using CJS with npm-module target and use Webpack instead.
:target :esm-files works like :npm-module and outputs separate files per ns
Ah right, experimental feature mentioned on the changelog. I though I had seen it somewhere.
last time I checked storybook heavily relied on static analysis of the files and didn't understand cljs output at all
so not sure that'll work
We have a version with Webpack that uses a custom storybook "indexer" code to parse Shadow-cljs output, that version at least works
Seems like I could implement similar indexer for the ESM files, but it isn't any simpler with the ESM files, even more complex than parsing the npm-module output, as there is the additional ESM "wrapper" file.
what are you parsing in the first place?
I have never used storybook so I'm not really sure whats required these days. some time ago I did a prototype that just used the clojure metadata from the build state to write some boilerplate code
dunno where that went but seems like that might be useful
Recent StoryBooks wants a default export which should be a JS object, and should have a certain properties which it can statically analyze.
And by default it is looking for any exported values in the file to use as stories.
Current impl I have from another project, does some regex magic to find module\.exports or Object\.defineProperty calls etc, and finds out a string value which should be the "title" for the file.
I could probably improve it a bit by emitting correct JS objects from Cljs. But the :esm-files output doesn't work directly because the default export is a reference to the cljs-runtime file, and not a JS object itself.
... and some custom Webpack loader thingie to "fix" the default property in :npm-module code...
I did end up writing at least shorter solution, in my opinion quite a bit cleaner also, no need to parse JS code with regexes.
Our defmeta and defstory macros store the required metadata to compiler state under the namespace, and then we have build hook which takes this metadata and writes one or per namespace .stories.json files to the output-dir. Then we have really simple indexer for StoryBook which just reads these json files as is. The files just need the path of the JS file and name of the JS variable in that file, per story.
With this version, we can use :esm-files output and probably pretty much any JS bundler. StoryBook doesn't care much as long as the refered JS file and variable exists.
The only workaround I needed, was to enable https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/targets/npm_module_goog_overrides.js for esm-files output. HMR broke on StoryBook without the goog.provide version here.
Might be nice to have a public example or repo for the solution... I might ask the client if we can post it somewhere.
I did consider also "full" storybook addon, similar approach as the official plugins due for Vue, Svelte etc, where the StoryBook indexer does "a proper parse" of the Vue etc. source file to find out the story definitions for the metadata.
But definitely less work to just handle it in the macros, and there is a benefit that if we had a macro generating more defstory macro calls, this still should end up generating correct metadata.
could be useful to have a :target :storybook impl that just does all this with minimal config. happy to help set that up if want/can
Could be. This version works for the StoryBook "frontend", but I hear the MCP server / AI integration might require even more setup. Not sure if or how that works together with this approach.
what if you just generated .js files instead? I mean its just boilerplate right?
well, I tried a long time ago and gave up getting tired fighting storybook. I doubt that has changed much š
I think they have rewritten the whole thing like once or twice a year with every major version \o/
If the support was with-in Shadow-cljs, I think it would be quite possible to emit JS files with correct boilerplate
I don't mean actual "compilation". I just mean some random JS by bashing some strings together
(str "export default " (json/write-str the-metadata)) type of thing
Hmm true. Instead of writing the JSON in build-hook, just do the same but write it as valid JS.
It should remove the need for custom indexer config in storybook (which was very short for the json files anyway.)
This has started to happen intermittently in Calva CI. I donāt know if it is CircleCI or something with shadow-cljs or my config.
⢠The step building the calva and test targets exits with 0 exit status before the test target is built.
⢠I have added a step to catch the error early.
āintermittentlyā here is about 50% of the times. So most often I can Re-run failed jobs, and it passes. https://app.circleci.com/pipelines/github/BetterThanTomorrow/calva/9937
āstarted to happenā is: happened first tome 25 days ago.
I donāt know what I could do to figure out more. I fail to reproduce the problem locally. Anyone have a clue/suggestion?
thats usually the shadow-cljs getting killed by the OS/VM usually for reaching some kind of memory limit
try setting a memory limit via deps.edn :jvm-opts
Setting a memory limit via :jvm-opts was indeed the solution. CI hasnāt croaked on this thing once in the 25 or so runs since. Thanks! š ā¤ļø