storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.4k stars 9.28k forks source link

Add cors headers to storybook dev server #12108

Closed ndelangen closed 4 years ago

ndelangen commented 4 years ago

Ensure composing local refs work without console log errors

ndelangen commented 4 years ago

Odd, we actually have this code: https://github.com/storybookjs/storybook/blob/9182d9f5ddbe136e9cd5fc9f11fa962a3cfe08f1/lib/core/src/server/build-dev.js#L361-L366

So this should already work!

ndelangen commented 4 years ago

https://github.com/storybookjs/storybook/commit/2eae03e89da0e1b22395f65eb07ff5c2cfc0fbc3

ndelangen commented 4 years ago

@shilman @tmeasday did we get reports local dev storybooks didn't ref correctly? I think it was NOT because of missing cors headers, but rather the problem of iframe.html always failing to be fetched.

I think this can be closed.

tmeasday commented 4 years ago

Ahh, ok I may have misunderstood!

asherccohen commented 3 years ago

Hi everyone. Is this an issue in storybook@6.0.27? I am getting cors errors fetching stories.json. I am serving storybook instances locally (npx serve) and I cannot get my main Storybook to fetch stories from other instances running.

ndelangen commented 3 years ago

does npx serve serve with CORS header enabled?

shilman commented 3 years ago

I think npx serve has problems in general with storybook because it rewrites routes. We recommend http-server instead.

tmeasday commented 3 years ago

@asherccohen -- did you generate stories.json?

asherccohen commented 3 years ago

Thanks everyone, that helped. I had to manually generate stories.json and also metadata.json (this I hacked by simply adding an empty json file as I don't know how to generate it, any advice is appreciated).

I also had to use http-server wth cors enabled:

npx http-server -p 5000 --cors

tmeasday commented 3 years ago

I also had to use http-server wth cors enabled:

Interesting, good tip.

metadata.json

Empty is fine. I don't think this file needs to exist though -- was it not working, or were you just concerned about a CORS error in the browser console?

asherccohen commented 3 years ago

@tmeasday Now that u pointed it out, metadata.json is optional, but I was driven by the network error and fixed it anyway.

matis-dk commented 3 years ago

I think npx serve has problems in general with storybook because it rewrites routes. We recommend http-server instead.

Works just fine if you add the --cors flag. npx serve storybook-static --cors

henrycity commented 3 years ago

Is there a way that I could just use npm run start-storybook to avoid cors errors when fetching stories.json?

shilman commented 3 years ago

@henrycity start-storybook doesn't currently serve stories.json as far as I know. I've added an experimental feature for that in 6.3, hidden behind a feature flag, and I think that should be fully supported in 6.4.

unikitty37 commented 1 year ago

@shilman Was that support ever added? I'm running 6.5.16, and yarn start-storybook in conjunction with the Ruby/Rails gem view_component-storybook still leaves me with this:

Access to fetch at 'http://localhost:3030/rails/stories/accordion_component/default?measureEnabled=false&outline=false' 
from origin 'http://localhost:9090' has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
header is present on the requested resource. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled.

I can't find anything relating to CORS in the documentation:

image

(including any mention of the experimental feature in the CHANGELOG.md, FWIW)

I'm running Storybook in a Docker container:

  storybook:
    <<: *backend
    command: yarn storybook --port 9090 --host storybook
    environment:
      <<: *app_env
    ports:
      - "9090:9090"

but if I add --cors to that it fails to recognise it as a valid option. What should I be putting there? (As Storybook is running in its own Docker container, I can't work out why it's ignoring --host and setting its origin as http://storybook:9000 rather than http://localhost:9000, in any case — how should I configure that?)

ndelangen commented 1 year ago

Hmm, I think it's had been implemented in 6.5... I'm pretty sure.

In 7.0 the code for this is here: https://github.com/storybookjs/storybook/blob/e54cfed6c7079dac855bfb41349356f55a28ad0b/code/lib/core-server/src/dev-server.ts#L50 https://github.com/storybookjs/storybook/blob/43f93bb8fb8056fbbd46f6d5fd90ca460c5f858a/code/lib/core-server/src/utils/getAccessControlMiddleware.ts#L3-L17

ndelangen commented 1 year ago

Here's the code for 6.5: https://github.com/storybookjs/storybook/blob/68361889edf068fbf0f22a85199a1c3e217f9353/lib/core-server/src/dev-server.ts#L102-L119

tmeasday commented 1 year ago

@unikitty37 that looks like you need CORS header from your Rails server (port 3030)?

unikitty37 commented 1 year ago

Thanks — a previous dev had already set CORS up, but using a rather old method (probably left over from when the app used a much older Rails version). Updating the CORS code to use Rack::Cors seems to have fixed that.

FilipSwiatczak commented 1 year ago

Using "@storybook/react": "^6.5.16" and still seeing this issue: "has been blocked by CORS policy: No 'Access-Control-Allow-Origin'" This is the case for local dev and for locally browsed storybook-static. Pushed storybook-static to aws s3 and same thing there, even with CORS policy open on the bucket. Seems to be related to the storybook itself and I'm hitting a wall. Any suggestions please? This should really work "out of the box"!

image It's the stories.json that's getting CORS and results in the Composition not loading specifically

I'm having: "features: { buildStoriesJson: true, // 👈 Enable this to build the stories.json file },"

And yes it creates the stories.json in storybook-static. @ndelangen so even though the code you quoted adds correct headers it still doesn't work. And the whole Composition section here: https://storybook.js.org/docs/react/sharing/storybook-composition#page-top implies it works out of the box. I'm new to this but it seems like a massive gap in communication?

image Expecting 'Access-Control-Allow-Origin', '*' to be present?

tmeasday commented 1 year ago

@FilipSwiatczak have you tried SB7? We fixed some issues around CORS in v7, so it might be fixed there.

Otherwise, how are you serving on port 61776?

FilipSwiatczak commented 1 year ago

hi @tmeasday, thanks for replying. I was running standard out-of-the-box yarn storybook which runs: storybook dev -p 6006

I migrated to v7.0.2. Deleted node_modules, run npx storybook init, then npx storybook@next automigrate because the storybook command was missing which migrated successfully. Migration check ran successfully Successful migrations: new-frameworks, mdx1to2, github-flavored-markdown-mdx, autodocsTrue, addReact, missing-babelrc

Decided to test the CORS issue in Composition against storybook's own storybook with:

refs: {
    'design-system': {
      title: "Storybook's Design System",
      url: 'https://5ccbc373887ca40020446347-yldsqjoxzb.chromatic.com',
      expanded: false // Optional, true by default
    },
    'our-design-system': {
      title: "Test Design System",
      url: 'https://xxx.co.uk'
    }
  },
image

Storybook's own storybook loads perfectly, for ours it gets index.json and stories.json 200 response with CORS error. Interestingly it gets 404 for the Storybook's index.json and yet it works fine!

image

The test storybook I'm trying to embed is built in storybook react 7.0.0-rc.8 and published in s3. Should I disable the stories generation in that project perhaps? Thanks!

ndelangen commented 1 year ago

You're expecting the 'our-design-system' to work?

That's completely dependent on 'https://xxx.co.uk/' having CORS enabled/supported there.


The storybook design system indeed tries to load index.json which fails, with a 404, because it hasn't been updated to 7.0 yet. Therefore it uses the fallback stories.json which you can see in your screenshot succeeds.

The other composed storybook also tries both, but both fail (presumingly due to CORS errors), therefore the UI in storybook shows the composed storybook failed to load.

FilipSwiatczak commented 1 year ago

thanks @ndelangen are there any resources/guides/pointers from storybook on how CORS should be set in aws s3 static webhosting? Asking since storybook deployer used to take care of that and has been recently archived which makes searching return some outdated results.

It's not related to Storybook as such but would sure be useful for anyone coming across this issue I think. In s3 CORS policy I have :

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

On both buckets (the embedding and the embedded). No difference. I suspect it's something to do with the Referrer Policy: strict-origin-when-cross-origin

Thanks!

ndelangen commented 1 year ago

@FilipSwiatczak that's unfortunately something that's outside of my expertise.

But likely a good question to find/ask on StackOverflow

FilipSwiatczak commented 1 year ago

Update, I made it work in s3 following instructions here: https://stackoverflow.com/questions/50022326/amazon-s3-image-cors-issue

Mostly setting CORS policy in S3 bucket that is Embedded to:

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

Hope this helps anyone landing here figuring out CORS in aws s3. Cheers

sneko commented 1 year ago

Sorry to continue this issue but I'm using Vite locally and launching 2 Storybook with storybook dev at the same time and I'm getting the error:

Access to fetch at 'http://localhost:6007/index.json' from origin 'http://localhost:6006' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

I can confirm http://localhost:6007/index.json exists, and I tried to set server headers in the Vite configuration but it still mention must not be the wildcard '*'. I tried multiple way to configure it (configuring cors, headers, middlewares setting headers).

I'm a bit lost, I was expecting Composition to be out of the box. Do you have a working example with Vite? Is it due to storybook dev and not using storybook start?

Thank you,

sneko commented 1 year ago

Found a "solution": despite I fixed a shared cache issue and that I'm now using different NPM package for each Storybook instance (ref: https://github.com/storybookjs/storybook/issues/15805#issuecomment-1563690740) the CORS issue was still happening when serving at the same time my 2 instances.

The solution was to delay from 3 seconds serving the instance referencing the other one. From there, no more issue! It's kind of weird (remember, everything is done locally, so no real custom CORS settings...), my conclusion:

Anyway, lost too much time on it, the simple delay of 3s is ugly but I'm fine with it for now 👍

ndelangen commented 1 year ago

I'm sorry you spend so much time on this @sneko.

We indeed have code that tries to compose a storybook in a few ways. The assumption we made as maintainers is that a storybook that's being composed will be fully available and ready before it's requested.

We could likely make some tweaks to our server to "hold" the request for longer, whilst the storybook is still getting "booted".

eloiqs commented 1 year ago

@ndelangen

The assumption we made as maintainers is that a storybook that's being composed will be fully available and ready before it's requested.

Is it possible that this has changed between 6.5 and 7? We were composing 3 different storybooks locally on 6.5 (localhost:6007 and localhost:6008 on localhost:6006) without any issues, and now on 7 we're getting cors errors for index.json and stories.json for 6007 and 6008 on 6006 when concurrently starting each storybbok dev processes.

I can't find any notes in the migration docs, but I would suppose it did change between 6.5 and 7 in some kind of way.

Note that manually starting 6007 and 6008 in two different consoles, waiting for boot and then manually starting 6006 in a third consoles, does seem to work ,but is more tedious than juste running one npm command that starts all of them concurrently.

ndelangen commented 1 year ago

Yes it's possible that that changed. Though the fact it worked prior to 7.0 was more of a happy accident.

@eloiqs you could invest a tiny bit of time writing a script that spawns the composed storybooks first, wait for them to be ready, and then spawn the main one?

Sorry for this nuisance.

sneko commented 1 year ago

@eloiqs no matter you want a script or direct CLI you can rely on https://github.com/open-cli-tools/concurrently to do so. Having each subcommand with a sleep X && storybook dev (X being like: 0, 3, 6).

(in my case I didn't have to wait for the previous to be ready, just waiting a few seconds was enough)

tmeasday commented 1 year ago

You might try using wait-on too.

eloiqs commented 1 year ago

👍 wait-on is perfect for this, thanks! Here's what I ended up with

npx concurrently -k -s first -n "app1,app2,composed" -c "magenta,blue,green" \
"storybook dev -c .storybook/apps/app1 -p 6007 --no-open" \
"storybook dev -c .storybook/apps/app2 -p 6008 --no-open" \
"wait-on tcp:6007 && wait-on tcp:6008 && storybook dev -c .storybook/apps/composed -p 6009 --no-open"
bitttttten commented 1 year ago

I am using this in turborepo, where my storybook config lives inside packages/sb, and there are a lot of apps and packages that have their own storybooks.

So I went with something like:

npx concurrently -k -s first -n 'sb,composed' -c 'magenta,blue' 'turbo run storybook --parallel --filter=!sb -- --no-open' 'npx wait-on tcp:6007 && npx wait-on tcp:6008 && turbo run storybook --filter=sb'
bitttttten commented 1 year ago

Although this is not without issues 😅

Screenshot 2023-07-11 at 11 29 39

I get a lot of errors in the console and some remote images don't load (because of cross origin errors I think):

Failed to load resource: the server responded with a status of 404 (Not Found)
:6008/metadata.json:1     Failed to load resource: the server responded with a status of 404 (Not Found)
:6007/metadata.json:1     Failed to load resource: the server responded with a status of 404 (Not Found)
VM721 iframe.html:12 unable to connect to top frame for connecting dev tools
(anonymous) @ VM721 iframe.html:12
runtime.js:4 DOMException: Blocked a frame with origin "http://localhost:6007" from accessing a cross-origin frame.
    at new Instrumenter (http://localhost:6007/node_modules/.cache/.vite-storybook/deps/@storybook_addon-interactions_preview.js?v=5d03fbdf:60:93)
    at instrument (http://localhost:6007/node_modules/.cache/.vite-storybook/deps/@storybook_addon-interactions_preview.js?v=5d03fbdf:239:510)
    at http://localhost:6007/node_modules/.cache/.vite-storybook/deps/@storybook_addon-interactions_preview.js?v=5d03fbdf:249:18
warn @ runtime.js:4
runtime.js:4 DOMException: Blocked a frame with origin "http://localhost:6007" from accessing a cross-origin frame.
    at new Instrumenter (http://localhost:6007/node_modules/.cache/.vite-storybook/deps/@storybook_addon-interactions_preview.js?v=5d03fbdf:60:93)
    at instrument (http://localhost:6007/node_modules/.cache/.vite-storybook/deps/@storybook_addon-interactions_preview.js?v=5d03fbdf:239:510)
    at http://localhost:6007/node_modules/.cache/.vite-storybook/deps/@storybook_addon-interactions_preview.js?v=5d03fbdf:286:25
warn @ runtime.js:4
chunk-F3MVQVF6.js:1 received globals from a non-local ref. This is not currently supported.