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

💡 RFC: Allow exports from astro components #1142

Closed
1 of 3 tasks
jasikpark opened this issue Aug 17, 2021 · 18 comments
Closed
1 of 3 tasks

💡 RFC: Allow exports from astro components #1142

jasikpark opened this issue Aug 17, 2021 · 18 comments

Comments

@jasikpark
Copy link
Contributor

jasikpark commented Aug 17, 2021

Background & Motivation

Related to #491

I think an interesting pattern we could support is allowing astro files to export data:

---
import Markdown from "@astro/components";
import MainLayout from "@layouts/MainLayout.astro";
import Header from "@components/Header.astro";
export const title = "This is a title";
export const date = new Date("2021-08-17");
export const author = "McAuthor AuthorPants";
---

<MainLayout>
  <Markdown>
    <Header title={title}/>
    Hiya this is my content
  </Markdown>
</MainLayout>
  • And then Astro.fetchContent("**/*.astro") would return a similar object to Astro.fetchContent("**/*.md") allowing components in markdown without too much effort..
  • import {...} from './SomeComponent.astro' would return these exports.

Proposed Solution

  • At compile-time, all exported things are hoisted out of the render function (similar to what we do with getStaticPaths() today).
  • If a hoisted thing references an un-hoisted variable, error in the compiler saying that exported things must be "pure" (aka can only reference other exported variables).
  • Those exports are now available when you import a component (ex: import {someExportedConst} from './Main.astro';)
  • Remove the markdown filtering from Astro.fetchContent to now support Astro components and pages as well.

Possible solutions

Alternatives considered

Risks, downsides, and/or tradeoffs

Open Questions

I think I remember #309 ending with a comment that scoping would be complicated to solve?

Detailed Design

No response

Help make it happen!

  • I am willing to submit a PR to implement this change.
  • I am willing to submit a PR to implement this change, but would need some guidance.
  • I am not willing to submit a PR to implement this change.
@jasikpark
Copy link
Contributor Author

jasikpark commented Aug 17, 2021

This is a pattern that's already used in 'astro/www' but with a hand-rolled index page rather than with support for collections!

@FredKSchott
Copy link
Member

This is actually possible and intentionally disabled right now. you can see the filtering happening in packages/astro/src/internal/fetch-content.ts.

      // Only return Markdown files, which export the __content object.
      if (!mod.__content) {
        return;
      }

I think the only question would be: what should the response object format look like? Right now, because its always Markdown it's always the same object, complete with markdown frontmatter as properties on the object. If a proposal could include a design for the .astro response interface, I think this could be reasonably added!

@jasikpark
Copy link
Contributor Author

It'd be great to both allow the object to contain the exports from the astro file + synthetic exports like .headings and .content and .content.raw like markdown that would be generated by astro!

@FredKSchott
Copy link
Member

I still want to experiment with the idea of everything exported getting pulled out of the component instance scope and into the module scope! But right now, since exports aren't supported, there's not much we can do here.

@davideast
Copy link

I don't have much of an opinion in terms of a proposal, but I would really love to see this feature as well. I'm currently building more complicated posts/pages in a .astro file, and then hard coding the metadata so it renders in an "articles" list.

@FredKSchott
Copy link
Member

It'd be great to both allow the object to contain the exports from the astro file + synthetic exports like .headings and .content and .content.raw like markdown that would be generated by astro!

I don't think parsing out synthetic things from an astro component would be possible. An imported component is different from a rendered component. We wouldn't know things like headings until it's been rendered.

But I am still +1 for the more narrowly focused proposal to allow exports from Astro components and then expose those.

@jasikpark
Copy link
Contributor Author

For sure, simply getting support for exports from astro files would be superb!

@FredKSchott FredKSchott changed the title 💡 RFC: Allow Astro.fetchContent for astro pages. 💡 RFC: Allow exports from astro pages. Aug 24, 2021
@FredKSchott
Copy link
Member

@jasikpark just updated your title, would love to work with you on this proposal if you're interested @jasikpark!

For the record there was some previous discussion in #619 that we can borrow from. This exact feature was out of scope for that proposal, so now that we've aligned on component script scoping I'd love to focus on this more specifically.

Naively, I love the idea of "all exports hoisted out of the component scope" + "a lint pass to make sure that nothing in the component scope is referenced from a hoisted export, and error if it does". We need this for getStaticPaths already, so the idea would just be to open it up to all exports.

@jasikpark
Copy link
Contributor Author

@jasikpark just updated your title, would love to work with you on this proposal if you're interested @jasikpark!

For the record there was some previous discussion in #619 that we can borrow from. This exact feature was out of scope for that proposal, so now that we've aligned on component script scoping I'd love to focus on this more specifically.

Naively, I love the idea of "all exports hoisted out of the component scope" + "a lint pass to make sure that nothing in the component scope is referenced from a hoisted export, and error if it does". We need this for getStaticPaths already, so the idea would just be to open it up to all exports.

Absolutely! I am not equipped with the knowledge of how to implement this, but I would love to be able to bring this to fruition!

@matthewp
Copy link
Contributor

This issue is titled "Allow exports from astro pages" but I'm assuming this applies to exports from any .astro file, correct?

@FredKSchott FredKSchott changed the title 💡 RFC: Allow exports from astro pages. 💡 RFC: Allow exports from astro components Aug 25, 2021
@FredKSchott
Copy link
Member

yes! updated. Also @jasikpark I made some additions to the issue but have not yet cleaned it up or proposed a full design

@drwpow
Copy link
Member

drwpow commented Oct 5, 2021

RFC Discussion Notes:

  • Supported in new compiler! 🎉 (but with caveats)
  • Proposal needs rules outlined (e.g. can’t work after top-level await)
  • Overall, no one is against having exports

Decision: approved! (but obviously needs docs)

@natemoo-re
Copy link
Member

The TC39 Spec on top-level await, since it's relevant to any caveats in the new compiler
https://github.com/tc39/proposal-top-level-await

@jasikpark
Copy link
Contributor Author

Example of it working! https://codesandbox.io/s/serene-wright-gwc6q?file=/src/components/AllowsExports.astro

@jasikpark
Copy link
Contributor Author

The TC39 Spec on top-level await, since it's relevant to any caveats in the new compiler tc39/proposal-top-level-await

I wonder if node will ever get that natively, similar to how all browsers support top level await today: https://caniuse.com/mdn-javascript_operators_await_top_level

@smakinson
Copy link

I'm just beginning to check out astro and I came across this while looking for how a page that is used for a listing might either filter pages that were created via a dynamic route or share the data that was loaded in getStaticPaths in the [something].astro page by exporting some of it. Is this RFC related to a workflow like this?

I don't think this is really equivalent, but something along the lines of how Hugo can list from .Pages (https://gohugo.io/templates/lists/) might be an example.

@jonathantneal
Copy link
Contributor

Hey everyone! This RFC is still accepted, and it has been moved to https://github.com/withastro/rfcs/blob/main/active-rfcs/support-exports-from-astro-components.md

In an effort to improve our RFC process, we made some changes to better organize things, which include a dedicated RFC repository.

@happycollision
Copy link
Contributor

FYI, anyone looking now, here is a permalink, as the one above is outdated: https://github.com/withastro/rfcs/blob/58749fdcc29f4da9c160a428b907c2b03780aa12/active-rfcs/0005-support-exports-from-astro-components.md

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

9 participants