Closed shishkin closed 8 months ago
@shishkin Thanks for the issue. Probably Astro "see" the normal AsyncAPI component (with parser onboard) and try to "compile" it - I have similar problem as I remember with older version of NextJS and treeshaking. Try to import component without parser from absolute path:
import AsyncApiComponentWP from "@asyncapi/react-component/esm/containers/AsyncApi/Standalone";
and let me know about problems!
Also, you should use stringify
(https://github.com/asyncapi/parser-js#stringify) function to stringify the parsed document. Document can have circular references in schemas and normal JSON.stringify
can throw error about cyclic values. stringify
function exposed by parser preserves that circular references and add another optimizations. React component then can read that, no worry about that :)
So your code should look like:
---
import "~/styles/asyncapi.css";
import parser, { AsyncAPIDocument } from "@asyncapi/parser";
import { AsyncApiComponentWP } from "@asyncapi/react-component/esm/containers/AsyncApi/Standalone";
const parsed = await parser.parse("...");
const schema = AsyncAPIDocument.stringify(parsed);
---
<AsyncApiComponentWP
schema={schema}
config={{ show: { sidebar: true } }}
client:load
/>
Thanks @magicmatatjahu!
Importing import AsyncApiComponent from "@asyncapi/react-component/esm/containers/AsyncApi/Standalone"
threw "Cannot find module". Adding lib
to the import path @asyncapi/react-component/lib/esm/containers/AsyncApi/Standalone
threw "Cannot read properties of undefined (reading 'default')". Also VS Code complains about absence of typings for the module. I tried to hack the component's package.json
by adding explicit exports
without any success however. Anything else I should try?
@shishkin What version of astro are you using, v1 or latest v2?
Latest 2.0.4
@shishkin You're right, something is wrong with ESM support in Astro. CJS imports /lib/cjs/...
work in dev, but don't in build time. I tried to make workaround with this:
---
import { createElement } from "react";
import { renderToString } from "react-dom/server";
import Layout from '../layouts/Layout.astro';
import parser from "@asyncapi/parser";
import { AsyncApiComponentWP } from "@asyncapi/react-component";
const schema = `
asyncapi: '2.5.0'
info:
title: Account Service
version: 1.0.0
description: This service is in charge of processing user signups
channels:
user/signedup:
subscribe:
message:
$ref: '#/components/messages/UserSignedUp'
components:
messages:
UserSignedUp:
payload:
type: object
properties:
displayName:
type: string
description: Name of the user
email:
type: string
format: email
description: Email of the user
`
const parsed = await parser.parse(schema);
const stringified = parsed.constructor.stringify(parsed);
const config = { show: { sidebar: true } };
const component = createElement(AsyncApiComponentWP, { schema: stringified, config });
const renderedComponent = renderToString(component);
---
<Layout>
<div id="asyncapi" set:html={renderedComponent}></div>
</Layout>
<script is:inline src="https://unpkg.com/@asyncapi/react-component@1.0.0-next.46/browser/standalone/index.js"></script>
<script define:vars={{ schema: stringified, config }}>
const root = document.getElementById("asyncapi");
AsyncApiStandalone.hydrate({ schema, config }, root);
</script>
And it works, however it's not perfect because you need to fetch whole ReactDOM library in browser. Let me know if you find something better!
Thanks for your suggestion @magicmatatjahu. I somewhat improved on it:
---
import "~/styles/asyncapi.css";
import js from "@asyncapi/react-component/browser/standalone/without-parser.js?url";
import parser from "@asyncapi/parser";
import { AsyncApiComponentWP, ConfigInterface } from "@asyncapi/react-component";
const parsed = await parser.parse(`...`);
const schema = parser.AsyncAPIDocument.stringify(parsed);
const config: ConfigInterface = { show: { sidebar: true } };
---
{
import.meta.env.SSR ? (
<>
<div id="asyncapi">
<AsyncApiComponentWP schema={schema} config={config} />
</div>
<script src={js}></script>
<script define:vars={{ schema, config }}>
AsyncApiStandalone.hydrate(
{schema: schema, config: config},
document.querySelector("#asyncapi > section") );
</script>
</>
) : (
<></>
)
}
I was able to use normal rendering mechanism without explicit renderToString
by guarding with SSR
env. I also figured I could import browser build without parser on the client.
Now, if I could only externalize react like esm.sh does and replace it with preact, I could further slim down the JS part of the component hydration.
@shishkin Yeah, sorry for using the standalone build with parser, but as I see you figure out that we also have without parser.
Now, if I could only externalize react like esm.sh does and replace it with preact, I could further slim down the JS part of the component hydration.
yeah, it will be perfect to decrease final size of app. Let me know about any other problems!
this is breaking on docusaurus as well
Error: Cannot read properties of undefined (reading '0') Uncaught TypeError: setClickedItem is not a function at handleSetExpanded (Toggle.js?f463:16:1)
constate] Component not wrapped within a Provider. at Toggle (webpack-internal:///./node_modules/@asyncapi/react-component/lib/components/Toggle.js:14:21) at section at ErrorComponent (webpack-internal:///./node_modules/@asyncapi/react-component/lib/containers/Error/Error.js:33:20) at AsyncApiComponent
[Autocomplete] You provided the render
option but did not provide a renderer.render
. Since v1.6.0, you can provide a render
function directly in renderer
.
To get rid of this warning, do any of the following depending on your use case.
render
option only to override Autocomplete's default render
function, pass the render
function into renderer
and remove the render
option.render
option to customize the layout, pass your render
function into renderer
and use it from the provided parameters of the render
option.render
option to work with React 18, pass an empty render
function into renderer
.
See https://www.algolia.com/doc/ui-libraries/autocomplete/api-reference/autocomplete-js/autocomplete/#param-render
at SearchBarThis issue has been automatically marked as stale because it has not had recent activity :sleeping:
It will be closed in 120 days if no further activity occurs. To unstale this issue, add a comment with a detailed explanation.
There can be many reasons why some specific issue has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model.
Let us figure out together how to push this issue forward. Connect with us through one of many communication channels we established here.
Thank you for your patience :heart:
Still a problem on docusuarus
This issue has been automatically marked as stale because it has not had recent activity :sleeping:
It will be closed in 120 days if no further activity occurs. To unstale this issue, add a comment with a detailed explanation.
There can be many reasons why some specific issue has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model.
Let us figure out together how to push this issue forward. Connect with us through one of many communication channels we established here.
Thank you for your patience :heart:
Description
I struggle to get the react component working in Astro. I followed the usage guide for Next.js with SSR to make sure to parse the schema on the server and import only the
AsyncApiComponentWP
component.Component renders in SSG in dev mode, but fails in production build and fails to hydrate on the client. In client-only mode I see the same error as during SSG hydration on the client side. When hydration fails, component is not interactive (though all content is there with proper styles).
Expected result
Expected it to work.
Actual result
When running SSG production build I see this error from Astro:
When running in dev mode I see this error in the browser:
Steps to reproduce
Create Astro project and add this component:
Troubleshooting
I traced
node-fetch
dependency and it is used by the@asyncapi/parser
. I'm not sure why parser is still loaded inAsyncApiComponentWP
. I supposed WP stood for "without parser" 🤷Is there a way to cleanup ESM dependencies for the standalone WP component to really not depend on CJS and node-only or browser-only packages?
Previously I struggled with this component on Deno (ultimately I gave up in favor of a custom element web component option) where the issue was the
isomorphic-dompurify
. I was wondering why sanitization has to happen insideAsyncApiComponentWP
. Maybe the parser should be sanitizing the markup bits of schema, so that parsed schema can be assumed safe?