Fork me on GitHub
#shadow-cljs
<
2024-01-08
>
Shako Farhad13:01:40

I am trying to get storybook 7 work with shadow-cljs and reagent. I have gotten most of the setup done but then I am getting this error: .storybook.button.stories.js: CSF: missing default export Anybody who has gotten storybook to work that can give me some hints to how to fix this?

Ellis13:01:11

Unless you have specific needs from storybook, I'd say it's easier to just use https://github.com/cjohansen/portfolio 🙂

thheller13:01:50

what is your setup? kinda hard to comment without knowing what you did

Shako Farhad13:01:02

shadow-cljs.edn

{:deps true

 :http {:port 9633}
 :nrepl {:port 4005}

 :builds
 {:stories {:target     :npm-module
            :entries    [acme.storybook.button.stories
                         acme.storybook.test.stories]
            :output-dir "stories-output-js"
            :devtools {:enabled false}}
  :app
  {:target          :browser
   :output-dir      "resources/public/js"
   :asset-path      "js"
   :modules         {:app {:entries [acme.cljs.core]}}}}}
package.json:
"devDependencies": {
  "@babel/preset-env": "7.23.7",
  "@babel/preset-react": "7.23.3",
  "@babel/preset-typescript": "^7.23.3",
  "@storybook/react": "7.6.7",
  "@storybook/react-webpack5": "7.6.7",
  "shadow-cljs": "2.26.2",
  "storybook": "7.6.7"
}
.babelrc.json:
{
  "sourceType": "unambiguous",
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "chrome": 100,
          "safari": 15,
          "firefox": 91
        },
        "modules": "commonjs"
      }
    ],
    "@babel/preset-typescript",
    "@babel/preset-react"
  ],
  "plugins": []
}
storybook.main.js
module.exports = {
    stories: ["../stories-output-js/**/*.stories.js"],

    framework: {
        name: "@storybook/react-webpack5",
        options: {}
    },

    docs: {
        autodocs: true
    }
};

thheller13:01:39

and the cljs code?

thheller13:01:49

looks good so far

Shako Farhad13:01:29

(ns acme.storybook.test.stories
  (:require [reagent.core :as r]))

(def button [:button.button "My button"])

(def ^:export default
  #js {:title     "LOL"
       :component (r/reactify-component button)})

(defn ^:export HelloWorldHeader []
  (r/as-element button))

thheller13:01:04

looks good. what does the stories-output-js/acme.storybook.test.stories.js look like? I suspect there is a munging problem

thheller13:01:42

there should be a exports.default = ... but that might be a exports.default$ = ...

Shako Farhad14:01:00

var $CLJS = require("./cljs_env");
var $jscomp = $CLJS.$jscomp;
var COMPILED = false;
require("./cljs.core.js");
require("./reagent.core.js");
var cognitect=$CLJS.cognitect || ($CLJS.cognitect = {});
var cljc=$CLJS.cljc || ($CLJS.cljc = {});
var tick=$CLJS.tick || ($CLJS.tick = {});
var re_frame=$CLJS.re_frame || ($CLJS.re_frame = {});
var module$shadow_js_shim_module$react=$CLJS.module$shadow_js_shim_module$react || ($CLJS.module$shadow_js_shim_module$react = {});
var clojure=$CLJS.clojure || ($CLJS.clojure = {});
var devtools=$CLJS.devtools || ($CLJS.devtools = {});
var cljs=$CLJS.cljs || ($CLJS.cljs = {});
var time_literals=$CLJS.time_literals || ($CLJS.time_literals = {});
var bec_cljs_common=$CLJS.bec_cljs_common || ($CLJS.bec_cljs_common = {});
var ajax=$CLJS.ajax || ($CLJS.ajax = {});
var java=$CLJS.java || ($CLJS.java = {});
var shadow=$CLJS.shadow || ($CLJS.shadow = {});
var module$shadow_js_shim_module$$formkit$auto_animate$react=$CLJS.module$shadow_js_shim_module$$formkit$auto_animate$react || ($CLJS.module$shadow_js_shim_module$$formkit$auto_animate$react = {});
var goog=$CLJS.goog || ($CLJS.goog = {});
var reagent=$CLJS.reagent || ($CLJS.reagent = {});
var module$shadow_js_shim_module$$js_joda$core=$CLJS.module$shadow_js_shim_module$$js_joda$core || ($CLJS.module$shadow_js_shim_module$$js_joda$core = {});
var lambdaisland=$CLJS.lambdaisland || ($CLJS.lambdaisland = {});
var taoensso=$CLJS.taoensso || ($CLJS.taoensso = {});
var com=$ || ($ = {});
var acme=$CLJS.acme || ($CLJS.acme = {});

$CLJS.SHADOW_ENV.setLoaded("acme.storybook.test.stories.js");

goog.provide('acme.storybook.test.stories');
acme.storybook.test.stories.button = new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Keyword(null,"button.button","button.button",1464242525),"My button"], null);
acme.storybook.test.stories.default$ = ({"title": "LOL", "component": reagent.core.reactify_component.cljs$core$IFn$_invoke$arity$1(acme.storybook.test.stories.button)});
acme.storybook.test.stories.HelloWorldHeader = (function acme$storybook$test$stories$HelloWorldHeader(){
    return reagent.core.as_element.cljs$core$IFn$_invoke$arity$1(acme.storybook.test.stories.button);
});
Object.defineProperty(module.exports, "default", { enumerable: true, get: function() { return acme.storybook.test.stories.default$; } });
Object.defineProperty(module.exports, "HelloWorldHeader", { enumerable: true, get: function() { return acme.storybook.test.stories.HelloWorldHeader; } });
//# sourceMappingURL=acme.storybook.test.stories.js.map

Shako Farhad14:01:16

Not sure if this was the best but that is the contents of storybook.test.stories

thheller14:01:21

ah right that is a dev file

thheller14:01:27

so

Object.defineProperty(module.exports, "default", { enumerable: true, get: function() { return acme.storybook.test.stories.default$; } });
is the part creating the export

thheller14:01:53

looks fine to me but I suspect storybook is now doing some kind of source processing, instead of just runtime things it used to do

thheller14:01:59

and it might not recognize that maybe?

thheller14:01:46

been a while since I looked at storybook, but it all looks good to me

Shako Farhad14:01:57

I think so. This post may give some hints to that: https://github.com/storybookjs/storybook/issues/21703

// This works 👇
// const meta = {
//   title: 'Example/Button',
//   component: Button,
//   tags: ['autodocs'],
//   argTypes: {
//     backgroundColor: { control: 'color' },
//   },
// };

// This doesn't 👇
const meta = getMeta('Button', Button);

export default meta;

thheller14:01:24

> SB7 statically analyzes the story files for performance reasons and we can't statically analyze functions.

thheller14:01:30

yep thats what I suspected

Shako Farhad14:01:03

Any workaround? Or just go back to storybook v6?

Shako Farhad14:01:54

@storybook/cli v7.6.7

WARN storyStoreV6 is deprecated, please migrate to storyStoreV7 instead.
WARN - Refer to the migration guide at 
info => Starting manager..
info => Starting preview..
info Using Babel compiler
info => Using implicit CSS loaders
info => Using default Webpack5 setup
 [webpack-dev-middleware] wait until bundle finished
WARN export 'default' (imported as 'previewAnnotations') was not found in '/home/dev/src/mono/bec-core-client/node_modules/@storybook/react/dist/entry-preview-docs.mjs' (possible exports: applyDecorators, argTypesEnhancers, decorators, parameters)
WARN export 'default' (imported as 'previewAnnotations') was not found in '/home/dev/src/mono/bec-core-client/node_modules/@storybook/react/dist/entry-preview.mjs' (possible exports: parameters, render, renderToCanvas)

thheller14:01:38

use 3x backtick please

to get multi
line

thheller14:01:21

sorry I don't have any immediate idea how to solve this

thheller14:01:50

tools that try to parse the actual generated output always have issues with how cljs code looks and I can't easily change that

thheller14:01:19

I'd probably write the stories in JS and just import the reagent components from that

Shako Farhad14:01:09

Thanks for your help! I was also thinking of just writing it in JS and importing the components. I will first try to just downgrade the storybook version and see if I can get anywhere with that first. Thank you!

pandeiro19:02:01

Wondering - did downgrading Storybook version 'just work'? Or did you go with a different solution? Thanks

Shako Farhad10:02:02

Downgrading works, yes. But I went with a different solution that is more tailored to our needs. But you could of course try https://github.com/cjohansen/portfolio. It is pretty good and you don't need to fight JS world quirks to get something useful out.