Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support astro:content inside Astro components in the Visual Editor #154

Closed
oliverlynch opened this issue Aug 3, 2023 · 11 comments
Closed

Comments

@oliverlynch
Copy link
Contributor

I'm having an issue in the bookshop generate step when trying to use getCollection from astro:content inside astro components. My astro build succeeds, but bookshop generate fails.

I can reproduce this in the sendit astro template by adding the import inside any of the .jsx components.

import { getCollection } from "astro:content";

Bookshop version 3.6.5

Console output:

> npx @bookshop/generate
📚 Generating Bookshop integrations

Looking for Bookshop component libraries...
Loading Bookshop from ./src
Loaded 14 components
Creating structures for all components...
Hydrating structures for nested components...
Loaded 1 Bookshop

Looking for output sites...
Found 1 site

Modifying output site at ./dist
Connected 0 component thumbnail(s)
Added live editing to 5 pages containing Bookshop components
 > src/shared/astro/Navigation.astro:2:30: error: Could not resolve "astro:content" (mark it as external to exclude it from the bundle)
    2 │ import { getCollection } from "astro:content";
      ╵                               ~~~~~~~~~~~~~~~

/Users/oliverlynch/_millstream/clients/2022b.theoarhouse.au/node_modules/esbuild/lib/main.js:1493
  let error = new Error(`${text}${summary}`);
              ^

Error: Build failed with 1 error:
src/shared/astro/Navigation.astro:2:30: error: Could not resolve "astro:content" (mark it as external to exclude it from the bundle)
    at failureErrorWithLog (/Users/oliverlynch/_millstream/clients/2022b.theoarhouse.au/node_modules/esbuild/lib/main.js:1493:15)
    at /Users/oliverlynch/_millstream/clients/2022b.theoarhouse.au/node_modules/esbuild/lib/main.js:1151:28
    at runOnEndCallbacks (/Users/oliverlynch/_millstream/clients/2022b.theoarhouse.au/node_modules/esbuild/lib/main.js:941:63)
    at buildResponseToResult (/Users/oliverlynch/_millstream/clients/2022b.theoarhouse.au/node_modules/esbuild/lib/main.js:1149:7)
    at /Users/oliverlynch/_millstream/clients/2022b.theoarhouse.au/node_modules/esbuild/lib/main.js:1258:14
    at /Users/oliverlynch/_millstream/clients/2022b.theoarhouse.au/node_modules/esbuild/lib/main.js:629:9
    at handleIncomingPacket (/Users/oliverlynch/_millstream/clients/2022b.theoarhouse.au/node_modules/esbuild/lib/main.js:726:9)
    at Socket.readFromStdout (/Users/oliverlynch/_millstream/clients/2022b.theoarhouse.au/node_modules/esbuild/lib/main.js:596:7)
    at Socket.emit (node:events:512:28)
    at addChunk (node:internal/streams/readable:324:12) {
  errors: [
    {
      detail: undefined,
      location: {
        column: 30,
        file: 'src/shared/astro/Navigation.astro',
        length: 15,
        line: 2,
        lineText: 'import { getCollection } from "astro:content";',
        namespace: '',
        suggestion: ''
      },
      notes: [],
      pluginName: '',
      text: 'Could not resolve "astro:content" (mark it as external to exclude it from the bundle)'
    }
  ],
  warnings: []
}

Node.js v19.7.0
@bglw
Copy link
Contributor

bglw commented Aug 3, 2023

Hey @oliverlynch 👋

This is currently a limitation of the way Astro and Bookshop interact — though we should certainly display this error better. Since Bookshop previews in the browser without access to your source files, interacting with your content collections directly isn't possible from within a component.

We have some future plans to help support this — but there isn't anything in place just yet.

@bglw bglw changed the title Astro: Error resolving astro:content inside components during @bookshop/generate Support astro:content inside Astro components in the Visual Editor Aug 3, 2023
@edmeehan
Copy link

edmeehan commented Nov 4, 2023

If we don't have a solution for this, does someone have a workaround alternative? I can't conditionally import a component file so not sure if there is a simple solution or if this needs to be complex.

@oliverlynch
Copy link
Contributor Author

I managed to work around this by getting all of my collection information outside of the bookshop:live element, then passing it in; for example generating getStaticPaths() with getCollection then passing my static paths list as a prop allowing me to generate a navigation component inside bookshop:live.

@edmeehan
Copy link

I managed to work around this by getting all of my collection information outside of the bookshop:live element, then passing it in; for example generating getStaticPaths() with getCollection then passing my static paths list as a prop allowing me to generate a navigation component inside bookshop:live.

I used Astro middleware to pass collections to Astro.locals to get around this issue. Just posting this if others are running into the same issue.

@silveltman
Copy link

I managed to work around this by getting all of my collection information outside of the bookshop:live element, then passing it in; for example generating getStaticPaths() with getCollection then passing my static paths list as a prop allowing me to generate a navigation component inside bookshop:live.

I used Astro middleware to pass collections to Astro.locals to get around this issue. Just posting this if others are running into the same issue.

Hi @edmeehan , can you post you code on this please? I'm not familiar with astro middleware but this could really help me out.

Thanks! :)

@silveltman
Copy link

Update on this;

I get the error even when 'astro:content' is being used outside the bookshop:live component. I have a Layout wrapping it, which uses 'astro:content' and 'astro:transitions':

<Layout>
  <RenderBookshop
    bookshop:live
    settings={settings}
    preview={preview}
    collections={collections}
  />
</Layout>

For me it causes bookshop:live to bring more problems than benefit unfortunately.

@oliverlynch
Copy link
Contributor Author

I used Astro middleware to pass collections to Astro.locals to get around this issue. Just posting this if others are running into the same issue.

Great idea to use middleware - I've moved my navigation generation to middleware which means I no longer need to pass everything down to my site navigation component. This is probably the best workaround for now, although astro can't seem to read the type declarations I've set for local in env.d.ts...

can you post you code on this please? I'm not familiar with astro middleware but this could really help me out.

The basic example on astro docs for middleware works pretty much out of the box with bookshop and the docs go more depth than I can add here, but in my middleware I am getting the "pages" collection to generate navigation, and attaching it to locals so it can be accessed anywhere. I am also attaching all of the collections to locals so that components can reference other pages without using astro:content.

import { defineMiddleware } from "astro:middleware";
import { getCollection, type CollectionEntry } from "astro:content";
import { collections } from "src/content/config";

export const onRequest = defineMiddleware(
  async (ctx: Record<string, any>, next) => {
    const pages = await getCollection("pages", (page) => {
      return page.data.status === "online";
    });

    ctx.locals.tree = makeTree(pages, ctx.params.slug);

    ctx.locals.collections = await getAllCollections();

    return next();
  }
);

The code inside the defineMiddleware function is run for each page that is generated, and anything that you attach to the locals will be available at Astro.locals.

I get the error even when 'astro:content' is being used outside the bookshop:live component. I have a Layout wrapping it, which uses 'astro:content' and 'astro:transitions':

Thats strange, I've just tried adding both astro:content and astro:transitions into my layout, organised similarly to your setup:

<Layout {...props} {id} {paths} {currentPath}>
  <Page bookshop:live contentBlocks={props.content_blocks} />
</Layout>

...and bookshop seems happy enough adding live editing. The only thing I could think of at the top of my head that might cause it is if you are passing the collections as a promise to the bookshop:live component, but I quickly tested it and bookshop didn't seem to mind.

@silveltman
Copy link

silveltman commented Dec 11, 2023

@oliverlynch Thanks for the testing! Seems weird that I'm running into this issue then.

Something I also ran into when trying out the middleware appreach is that Astro.locals seems to be undefined in the CloudCannon live editing. No build errors this time, but I could not actually use the data. Have you also experienced this @oliverlynch ?

@oliverlynch
Copy link
Contributor Author

Something I also ran into when trying out the middleware appreach is that Astro.locals seems to be undefined in the CloudCannon live editing. No build errors this time, but I could not actually use the data. Have you also experienced this

I've tested a bunch of stuff out and it looks like you're right - both passing into the bookshop:live element with props and middleware result in undefined variables in the live editor...

It seems to me that in live mode only props defined within bookshop:live or in the component's __.bookshop.yml file are actually set. I thought the middleware setup had worked as bookshop compiled correctly and the navigation appeared in the live editor, but accessing Astro.locals inside bookshop:live is undefined as you have stated. I assumed passing props worked because it appears to work with the standard component properties normally, and I hadn't used any extra props - This should possibly be mentioned in the bookshop:live documentation.

This limitation is frustrating as centralising my navigation to middleware was partially to help create a page index component, but it won't work inside the live editor. For now I'll probably just use the ENV_BOOKSHOP_LIVE to display a placeholder during live editing, but obviously this is suboptimal. Hopefully we can get support for middleware and/or passing props within bookshop:live in the future.

@Tate-CC
Copy link
Contributor

Tate-CC commented Dec 23, 2023

Hi @silveltman, @oliverlynch, and @edmeehan 👋

Yesterday we released Bookshop 3.9.0 which includes support for using astro:content inside Bookshop components in the visual editor. There is a small caveat that the collection item's content and render functions are just placeholders since we can't access the actual file in the visual editor. Otherwise all the collection item's data/frontmatter will be available and any build issues should be resolved.

@Tate-CC Tate-CC closed this as completed Dec 23, 2023
@silveltman
Copy link

Hi @Tate-CC ,

Sounds awesome! However, I just tried it out and my components are not rendering. Just to be sure, do the component actually work with 'astro:content' OR does the live editor skip these components and render the rest?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants