Comments (17)
But... maybe the pros outweigh the cons here. @drwpow experimented with this in https://gitlab.com/pikapkg/hosting-experiments/-/merge_requests/3 and I think I talked him out of it, but maybe its worth revisiting.
FWIW I’m still on team “no layout” 😛. I think there were some rough edges in the PR, but when it comes to pagination I think you have to learn how to load .md
files anyway. And I liked the consistency of learning how to load .md
files and using it consistently everywhere. It ended up being more “top-down“ and “React-like.” I think if we improved that DX it‘d be less mental overhead. But take that 100% as my opinion; I personally just get confused by having .md
files be a route.
from astro.
Played around with this a bit tonight: https://github.com/snowpackjs/astro/compare/wip-no-layout?expand=1#diff-5b70b2cf9fac365ce8bd02496d6de5aaf87f7d6815488c80e947d19b6299eb38
pages/index.hmx
convertedlayouts/base.hmx
converted, split intoBaseLayout
andBaseHead
.
The good:
- I really like that this takes us back to "a page must always be
<html><head>...</head><body>...</body></html>
. "It's just HTML!" <BaseHead />
forced me to be more specific aboutprops
instead of a general sharedcontext
<BaseLayout />
almost forced some "props drilling" frompage -> BaseLayout -> Nav
component. Not the worst thing in the world (such react, much wow) and then I realized that I could just load that variable directly inside the Nav component and get rid of the issue. But lets go back and make sure that we're good with prop-drilling, or add back the idea of context.- I actually pretty much got rid of "context" entirely in this, which was unexpected but kind of exciting. Was inheriting/merging context that just a required construct of having nested layouts? Now I can just set things as direct variables in the page (
title
anddescription
). The page itself basically acts as the top-level shared context.
The ugly:
- As a user, I'm confused what to do with
<script>
and<style>
in a page. I'm so used to these being top-level "special" concepts in a component, but to follow that it feels really odd to have a<script>
and<style>
to live outside of the page<html>
. But then if I put them in the<html>
, where? Top of the<head>
? Now I'm really mixing JS and HTML together and the context shifting feels really offputting. I have an idea that I want to explore here that might help.
from astro.
To clarify: by “no layout” I meant to say I‘m -1 only on loading layouts from frontmatter. Not the entire concept of layouts. I’m in favor of this approach, personally.
from astro.
Opening another can of worms, which should be moved to another issue? Explicity return props and components from the setup function.
Yea, this has become more obviously "weird" in the move away from nested layouts. That's a good thing since I think its always been weird, but lets spin up a separate thread to address.
Introduce an tag which can have a single <script> tag and n number of <style> tags
So what's interesting about <style>
is that it actually doesn't have this same <script astro>
"where does it go?" problem. <style>
tags go in the head! And represent an element that will eventually end up on the page. It still has the "context shifting / content mixing" problem of nesting CSS styles inside of HTML markup, but since it's all about constructing the full HTML output I think it's more clear since that's kind of just how HTML works (plus you may want control over where those styles live in the head?).
If everyones onboard, I'd love to try the ---
approach first and then see how it feels as users. Definitely not opposed to <astro><script/><style/></astro>
if we still feel like somethings missing afterwards.
from astro.
I'm very much in favor of this approach!
At first I started to think about how Markdown pages would declare their Layout
component, but now I'm starting to rethink Markdown pages entirely. What if we didn't use Markdown pages as entry points and required all pages to be HMX? In order to render a "Markdown" page, we could have an astro:markdown
component? So you could do something like this for inline content.
<script astro>
import Layout from '../layouts/blog.hmx';
</script>
<Layout>
<Fragment slot="astro:head">
<title>My Blog Post</title>
<link rel="stylesheet" href="/styles/blog.css">
</Fragment>
<astro:markdown>
# Hello world!
</astro:markdown>
</Layout>
This approach would have the added benefit of not requiring Markdown content to be inside of your pages/
directory. What if you want the Markdown to live in a docs/
directory? Or a remote source? Could <astro:markdown>
just accept a src
attribute? Whenever we introduce dynamic routes and a data-fetching interface, the src
could easily by dynamic.
<script astro>
import Layout from '../layouts/blog.hmx';
</script>
<Layout>
<Fragment slot="astro:head">
<title>My Blog Post</title>
<link rel="stylesheet" href="/styles/blog.css">
</Fragment>
<astro:markdown src="../docs/hello-world.md" />
</Layout>
from astro.
Much of that thinking is inspired by next-mdx-remote
, by the way! And astro:markdown
doesn't even need to be a special component, we could just expose import Markdown from 'astro/markdown'
.
from astro.
Yea this feels really nice, I that's a great call out that we've moved away from our "it's just HTML" roots.
I think I'm totally sold on the idea of Layouts as components. Slots could be generic too which is really nice for keeping overall number of concepts low.
Also a strong +1 for having a special slot fragment component, and maybe not even supporting "slot=XXX" on any arbitrary component. I like <Template>
but agree it's overloaded. Maybe just <SlotContent slot="...">
?
Also another strong +1 for having a "no slots boilerplate" flow when its not necessary. Slots are still a new concept to many, and besides the extra boilerplate I think they oddly take us back out of the "its just HTML" world that we want to get back to. I still see a lot of value in just doing this if you can:
<script astro>
import BlogLayout from '../layouts/blog.hmx';
</script>
<BlogLayout>
<div>... blog post content here</div>
<BlogLayout>
And then I think the question becomes: does adding to the head mean you need to enter "multi-slot boilerplate mode"? Or, do we still have a special component for adding things to the head, if you don't own the head?
<BlogLayout>
<div>... blog post content here</div>
<BlogLayout>
<!-- and then, if you wanted to add to head... -->
<astro:head>
<title>My Blog Post</title>
<link rel="stylesheet" href="/styles/blog.css">
</astro:head>
I might be thinking too far ahead on this point, though. If we want named slots anyway, lets just build that first and see how it feels. Happy to revisit this later on down the road.
from astro.
@natemoo-re that's 100% where I want to see us go when we start introducing dynamic route handlers. Basically having something like /pages/docs/[slug].hmx
matching all incoming routes, and then looking up files in a docs/
or content/
directory, and then loading it onto the page sort of like you have here.
The problem is that I still see the value in having 1:1 "markdown files : page", since it gives you a super clear way to understand your site structure. "I added this file, and now a new page lives at this URL". It's also easier to build your site, since you have a 1:1 mapping of files to pages.
But... maybe the pros outweigh the cons here. @drwpow experimented with this in https://gitlab.com/pikapkg/hosting-experiments/-/merge_requests/3 and I think I talked him out of it, but maybe its worth revisiting. Especially since it ties into the above, and we may be able to get rid of the layouts concept entirely (and could then push off the named slot support talked about above to a much later stage of development). /cc @matthewp
from astro.
Okay, so attempting to summarize where we're at as a team: There's interest in an experiment to implement:
layouts/
is no longer a concept, no more layout nesting, etc.pages/
is still a thing, but pages are now full HTML.- That incudes
<html>
(maybe) and<head> + <body>
(definitely)
- That incudes
- Pages can still leverage common layout logic, like
<BlogLayout>
- Can just support a single slot for now
- future: A
<SlotContent slot="...">
component that makes it easier to work with multiple, named slots.
And then the big question still remaining is: How do markdown files relate to pages/routes?
- Option: Keep the current
pages/*.md
, and keep the current idea of frontmatterlayout: '../components/BlogLayout.hmx'
? (Freds personal pref: unclear, but leaning -1 if this is just stretching an old idea too far now) - Option: Zero top-level markdown files, and instead
<astro:markdown>...</>
inside of HMX? (Freds personal pref: -1, sometimes devs just wanna write a.md
file, worried this would be too alienating to be the only way to do it, but I love the concept of a<Markdown>
component now being possible!). - Option: Go full into the world of dynamic page loaders: A new top-level
content/*.md
directory and support for[slug].hmx
pages that can load data dynamically out of that content directory. (Freds personal pref: leaning +1 now, I think my first impression of "yea but I can't understand the exact pages & URL scheme that we're building just by looking at thepages/
directory structure" doesn't outweigh the pros here.)
Anything else that I'm missing in either section? Thoughts of the above?
from astro.
Okay yall, keep an open mind with me of this one: a77a2e6
---
import Menu from '../components/Menu.hmx';
import Hero from '../components/Hero.hmx';
import BaseHead from '../layouts/BaseHead.hmx';
import BaseLayout from '../layouts/BaseLayout.hmx';
let title = 'Snowpack';
let description = 'Snowpack is a lightning-fast frontend build tool, designed for the modern web.';
export function setup({ context }) {
return {};
}
---
<html>
<head>
<BaseHead title={title} description={description} />
At first I was skeptical, but then I realized that it solves some really core/essential problems for us including the big one mentioned in the post above. And now that I've spent some time with it I'm REALLY digging it.
Problems solved
<script astro>
- unlike every other element you write, this one isn't actually an element on the page.<script>
would be, but then adding theastro
attribute turns it into something special that runs server-side/build-time. This is really unique and no other elements/attributes have special rules anything like this.- What if I put 2
<script astro>
components on the page? (we have to error). What if 0? (okay). What if I put<script astro>
somewhere nested inside the markup? (error? okay? not sure). - I think the root of the issues outlined above is that you're mixing component markup (HTML) and component setup/configuration/imports (JS) together. As a user I'd really want to think of setup as different from markup, which is why having setup inside markup feels so odd.
- The main issue that kicked this off: Where does
<script astro>
live? In components it's a top-level thing, but in pages there's no good place for it (see "the ugly" above). This is the biggest issue worth solving imo. - Bonus: Frontmatter is already a concept/syntax that devs are familiar with (not true with
<script astro>
).
@natemoo-re I know that we can parse this easy enough into the same exact parse result that we use today, but let me know if this is somehow very tricky in VSCode world.
from astro.
Well I'm glad people have run with this idea 😀. For clarity I'm personally not against layouts at all. I'm not even against a layout prop being returned from the setup script (or in frontmatter in markdown). What I was trying to hit at in this thread is that the primitive of layouts should be components. A special "layout" concept in markdown/etc. can be sugar on top of ordinary component usage. So this thread was intended to be an alternative idea to how they are implemented more so than questioning their overall usefulness.
And I definitely thinking markdown files as pages is a good thing, and pretty much expected if we are going to try to keep in the blog space (I think we want to). We just need to decide what a markdown page compiles to so that we can tell a layout author what slot names exist, etc.
from astro.
Option: Keep the current pages/*.md,
I like this option as well, I don't think we should go too far with this idea. Markdown pages are still a special-case, we just need to define what they get translated into and document how to write a Layout component for them.
from astro.
@FredKSchott re frontmatter setup script ->
That's pretty interesting! You're right that moving to a full-page structure makes it not obvious where to stick the setup script. I think I can grow to like the frontmatter approach. It's similar to 11ty which allows frontmatter in nunjunks templates at the top like that. I can see a scenario were we might also support non-JavaScript frontmatter, maybe yaml instead (which is just sugar for what you wrote).
I wonder if the larger revelation here is that you want some separation between the template part of the HMX and the setup part. Previously we had discussed ideas of having <import>
, <data>
, etc. type of elements that would be sugar for a setup script. Is that still possible within this frontmatter idea? Does it matter if not?
Here's another idea. I don't necessarily like it better, just throwing it out there. If the discovery is having distance between the setup and the template, what about revisiting the <astro>
element idea you had mentioned previously, and doing something like this:
<astro>
<import BlogLayout from="../components/BlogLayout.hmx">
<script> // No need for astro/setup attributes, this is scoped to setup time.
export default {
title: 'My Blog'
}
</script>
</astro>
<html lang="en">
<head> .... <head>
<body>
<h1>{title}</h1>
</body>
</html>
from astro.
I really like that concept @FredKSchott! I think having a universal setup
area of the page makes the line between the server code and what will actually be included on the page very clear.
At the risk of getting lost in more bikeshedding, but here's a combo between @matthewp's suggestion and @FredKSchott's suggestion. Explanation below, but I think it hits a good middle ground. This format could also carry over to Markdown pages as well, if we go that route, since Markdown can contain any HTML.
<astro>
<script>
import BaseHead from '../component/BaseHead.hmx';
/* I'm considering a separate issue for this part! So consider this hand-wavey */
export function setup({ context }) {
const title = 'Snowpack';
const description = 'Snowpack is a lightning-fast frontend build tool, designed for the modern web.';
return {
props: { title, description },
components: { BaseHead }
};
}
</script>
<style lang="scss"> ... </style>
<astro>
<html lang="en">
<head>
<BaseHead title={title} description={description} />
</head>
<body>
<h1>{title}</h1>
</body>
</html>
What I changed:
- Introduce an
<astro>
tag which can have a single<script>
tag andn
number of<style>
tags. This keeps everything "just" HTML without introducing new syntax likeimport
ordata
. - Opening another can of worms, which should be moved to another issue? Explicity return
props
andcomponents
from thesetup
function. Makes it more clear what is locally scoped to the script and what is exposed to the page. Also thought aboutexport const components = {}
but maybe there are different components based on thesetup context
?
from astro.
Okay, played around a bit more with this and it definitely changes things, I think for the better. Here's where I'm at: https://github.com/snowpackjs/astro/pull/new/wip-no-layout-2 (VERY WIP, different pages are in different states of transition).
- No implementation yet, still just playing with the user interface
- Super happy with all pages being full HTML (
<html><head>...
). No layout nesting definitely encourages composition with components more, which is exactly what we want to encourage to build a healthy component ecosystem. - I'd say I'm like 95% happy with
<style>
being inside the<head>
on pages. The only thing giving me pause is that the pages without styles (ex:pages/news.hmx
) feel so much cleaner than the ones with styles (ex:pages/plugins.hmx
). Maybe that would be true regardless of where the style lived? Maybe that will encourage users to use components more, and do less styling in pages? - Layout nesting is gone, but layouts DO still exist for markdown pages. The current direction of that branch is:
- Pages are full HTML pages now, no more layouts or nesting allowed.
- Markdown can still declare a layout though, but the concept of "layouts" is now different. Instead, its more like a page (ex: must return full HTML) that's detached from the file based router, and can be applied to any markdown file arbitrarily. Still not fully fleshed out, but it feels like an interesting & promising direction. You can see it most developed in
layouts/content.hmx
.
- Speaking of
layouts/content.hmx
: by getting rid of layout nesting, we got rid of the idea ofcontext
passing. This is finally forcing us to address how props work in pages.layouts/content.hmx
contains a few experiments (commented as "Attempt 1" - "Attempt 4") on an API for this, curious to hear thoughts. Feel free to play around with your own ideas here as well!
from astro.
@FredKSchott I've rebased your branch against the hmx->astro conversion branch and pushed to here: https://github.com/snowpackjs/astro/compare/wip-no-layout-3?expand=1
from astro.
Okay, I think this has been resolved with #24 merging. @matthewp @natemoo-re feel free to re-open if there's any part of this still unaddressed (or: spin up a new, more focused issue)
from astro.
Related Issues (20)
- [View Transitions] Using client:only in dev causes page reloads on view transitions HOT 3
- @astrojs/mdx>=2 unnecessarily removes whitespaces and line breaks from multiline strings in Astro components props supplied from Remark HOT 1
- Toolbar audit incorrectly flagging images as above the fold HOT 3
- React component not showing only on dev HOT 3
- Astro DB: there is no way of creating a primary key composed of several columns HOT 2
- Warning: ReactDOMServer.renderToStaticNodeStream() is deprecated. HOT 2
- npx astro add fails on Node 22 HOT 6
- Viewtransition calls page twice on hover (prefetch) and on click HOT 6
- Build fails when using <style>. HOT 2
- Can't forward concrete `HTMLAttributes` when using `Polymorphic` component HOT 2
- Astro glob throw unsupported files for svg HOT 7
- Animations using svelte-motion break in deployed Astro + Svelte website. HOT 5
- Node SSR breaks when `X-Forwarded-Host` includes port and `X-Forwarded-Port` is also sent
- The image size isn't changing when viewport changes (Image/Picture built-in component) HOT 5
- Deprecation warning for `ReactDOM.renderToStaticNodeStream` used in `@astrojs/react/server.js` HOT 1
- Query Params are stripped HOT 1
- Adobe react spectrum not working (Unknown file extension ".css" )
- Asset links are not bundled in .html files HOT 3
- `NotificationPayload` type is not correct.
- toolbar: `toggleState` is not working. HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from astro.