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

Adds js front matter type for arbitrary JavaScript front matter. #2819

Closed
darthmall opened this issue Feb 22, 2023 · 17 comments
Closed

Adds js front matter type for arbitrary JavaScript front matter. #2819

darthmall opened this issue Feb 22, 2023 · 17 comments
Labels
breaking-change-canary This applied a breaking change in a canary release. enhancement

Comments

@darthmall
Copy link

There’s an example of configuring a custom JavaScript format for frontmatter in the official demos. It adds functionality that is fairly similar to the component scripts in Astro.

It strikes me as something that might be nice to add to the pre-configured frontmatter formats that are shipped with Eleventy. But I have a couple of reservations as well…

First, based on the demo, it looks like it does add a dependency to core: node-retrieve-globals.

Second, there’s already the js format which allows you to specify frontmatter as a single JavaScript object. It’s not exactly the same as the javascript format in the demo, but it’s similar enough that I can imagine the difference being confusing. I’m not sure why a person might expect that js lets you define a single objects and javascript lets you write a script where all of the variable are exported to the template context.

Still, it’s not hard for me to imagine that this would be useful to people. I know a lot of people like the component scripts in Astro.

@zachleat zachleat added this to the Eleventy 3.0.0 milestone Mar 17, 2023
@zachleat zachleat changed the title Add configuration for javascript frontmatter to core? Adds node front matter type for node.js JavaScript front matter. Nov 3, 2023
@zachleat
Copy link
Member

zachleat commented Nov 3, 2023

This is shipping with 3.0 as the node front matter type in core.

@zachleat
Copy link
Member

zachleat commented Nov 3, 2023

For those curious, this is using https://github.com/zachleat/node-retrieve-globals

@zachleat
Copy link
Member

zachleat commented Nov 3, 2023

If you have opinions on the name, please let me know!

We can’t use js or javascript due to existing aliasing in the gray-matter dependency: https://github.com/jonschlinkert/gray-matter/blob/ce67a86dba419381db0dd01cc84e2d30a1d1e6a5/lib/engine.js#L14

@zachleat
Copy link
Member

zachleat commented Nov 3, 2023

TIL there is also an existing feature to override the default front matter syntax project-wide:

eleventyConfig.setFrontMatterParsingOptions({
	language: "node"
});

Now this nunjucks file will use node front matter by default (instead of yaml):

---
const hi = "hi";
---
{{ hi }}

Docs for this shipping here: https://www.11ty.dev/docs/data-frontmatter/#change-the-default-format-project-wide

@darthmall
Copy link
Author

Node’s not bad, in my opinion. A thought occurred looking at this again: Astro calls these “component scripts”, so maybe this could be just “script”.

---script
const greeting = "howdy";
---

I dunno if I think this is better, just wanted to put it up for debate.

@zachleat
Copy link
Member

zachleat commented Nov 8, 2023

I don’t actually prefer this but it’s worth noting that server might be an option that has some caché to it, given React’s "use server" directive. 🫣

@darthmall
Copy link
Author

I dunno if I like server. Being unfamiliar with React, I don’t know what "use server" means.

One thought that does occur to me about node, though, is that some day, conceivably, there could be other JavaScript runtime that could be used to run Eleventy, and if you’re using something like Bun to run Eleventy, then calling this frontmatter type node seems a little weird. 🤔

@wommy
Copy link

wommy commented Nov 13, 2023

lmao they both kinda stink 😅 not terrible tho
and i dont have a better suggestion 😓

and bun is aiming for near node compatibility

its strange the clarity of that perspective, serverside js being node called from the client

@hawkticehurst
Copy link

hawkticehurst commented May 26, 2024

I don’t actually prefer this but it’s worth noting that server might be an option that has some caché to it, given React’s "use server" directive. 🫣

Very late to this discussion, so not sure if this is already set in stone... but I would cast a very strong +1 towards server (instead of node).

Using the word "server" (whether in code or file names) as marker for code that is only run on the server and/or at build time is becoming so widely used across other frameworks I think it would be a nice alignment with prior work and be a really helpful transition for those coming to 11ty for the first time.

For reference, see:

@zachleat zachleat added the needs-documentation Documentation for this issue/feature is pending! label May 30, 2024
@mayank99
Copy link
Contributor

If you have opinions on the name, please let me know!

We can’t use js or javascript due to existing aliasing in the gray-matter dependency: https://github.com/jonschlinkert/gray-matter/blob/ce67a86dba419381db0dd01cc84e2d30a1d1e6a5/lib/engine.js#L14

Would it make sense to make a breaking change here? javascript is obviously the best name, and it matches the custom frontmatter example in the existing documentation. Since this is going in 3.0, it feels like the right time to make such a change.

Alternatively, I guess script works too and is runtime-agnostic same as javascript.


I don’t actually prefer this but it’s worth noting that server might be an option that has some caché to it, given React’s "use server" directive. 🫣

Next –– "use server" is the default, so the inverse "use client" is used to opt out of server only components

It's worth pointing out that "use server" creates a server endpoint. It's not used for marking code that executes at build time or on request. See docs.

React's data flow goes something like this:

  1. default (server components, execute at build-time or on load/request).
  2. "use client" (client components, execute during SSR and in the browser).
  3. "use server" (server actions, execute only on the server e.g. after form submission)

For this reason, I don't think it's necessarily a good idea to borrow the server terminology.

If we're looking at other frameworks, Vue's setup scripts might be closer to 11ty's node frontmatter.

@darthmall
Copy link
Author

I agree with Mayank about use server. Running at build time is not the same thing as running on a server, and in the past we’ve dealt with a lot of questions on Discord about when Eleventy runs — for example, people wanting to use URL parameters in their templates.

@zachleat
Copy link
Member

zachleat commented May 31, 2024

I’m coming around to the idea that a breaking change might make sense here for javascript. A little safety comes from js as the one we advertise on the docs for that previous behavior so javascript is unlikely to be highly used: https://www.11ty.dev/docs/data-frontmatter/#javascript-object-front-matter

@rdela
Copy link
Contributor

rdela commented Jul 3, 2024

My 2¢

Don't mind node, but good ol es, ecma, and ecmascript are other alternatives to javascript.

Do not like script or server at all in front matter.

@zachleat zachleat reopened this Jul 3, 2024
@hawkticehurst
Copy link

hawkticehurst commented Jul 3, 2024

It's worth pointing out that "use server" creates a server endpoint. It's not used for marking code that executes at build time or on request. See docs.

Running at build time is not the same thing as running on a server, and in the past we’ve dealt with a lot of questions on Discord about when Eleventy runs

Ooh these are great call outs –– feeling much less strongly about that +1 now 😅

I’m coming around to the idea that a breaking change might make sense here for javascript. A little safety comes from js as the one we advertise on the docs for that previous behavior so javascript is unlikely to be highly used

I hadn't given javascript a vote since earlier discussions put a line in the sand about not being able to use js or javascript, but if this a possible breaking change that's my actual preference

@hawkticehurst
Copy link

hawkticehurst commented Jul 3, 2024

Actually one more (potentially naive) thought/question:

Is there any way that the functionality of js and javascript can just be combined?

Aka is there some way of allowing both JS object front matter definition and component script functionality to be integrated under the same markers?

An off the cuff example of this could be some type of reserved keyword (i.e. "frontmatter") that if defined/exported will be used as the front matter for the page, otherwise everything else is just part of the "component script."

---js // or `javascript`
export const frontmatter = {
  title: "My page title",
  currentDate: function() { ... }
}
const hi = "hi";
---

<h1>{{frontmatter.title}}</h1>
<p>{{hi}}</p>

The only issue with this is that forcing named variable exports to get the original behavior probably strays pretty far into painful breaking change territory.

The potential solution is to have some type of check for the existence of only naked JS objects and if found will use the current JS object front matter behavior.

// Since there's nothing except the JS object
// uses original JS object front matter behavior 
---js // or `javascript`
{
  title: "My page title",
  currentDate: function() { ... }
}
---

<h1>{{title}}</h1>

Since I'm new to 11ty I'm almost definitely missing something here, but if anything like is possible that would be my actual actual preference

zachleat added a commit that referenced this issue Jul 3, 2024
@zachleat
Copy link
Member

zachleat commented Jul 3, 2024

Alright @hawkticehurst! You’re absolutely right—the approach you suggested was a better solution that doesn’t require a breaking change.

The existing js or javascript front matter syntax is Object-based so the syntax will start with { https://github.com/jonschlinkert/gray-matter/blob/ce67a86dba419381db0dd01cc84e2d30a1d1e6a5/examples/javascript.js

I think this is an acceptable way to support the old behavior and the new behavior without using two different engine names here.

Implemented on 6623330

In 3.0.0-alpha.15, both of these will be supported on both js and javascript:

New:

---js
const title = "My page title";
function currentDate() { … }
---

Old:

---js
{
  title: "My page title",
  currentDate: function() { … }
}
---

@zachleat zachleat closed this as completed Jul 3, 2024
@zachleat zachleat changed the title Adds node front matter type for node.js JavaScript front matter. Adds js front matter type for arbitrary JavaScript front matter. Jul 4, 2024
@zachleat
Copy link
Member

Notably, per some of the valid naming concerns noted above, the node front matter type that shipped in 3.0.0-alpha.1 was removed in 3.0.0-alpha.18 and will throw an error telling folks to use js or javascript moving forward.

Appreciate y’all!

@zachleat zachleat added the breaking-change-canary This applied a breaking change in a canary release. label Jul 29, 2024
rdela added a commit to rdela/tugboat that referenced this issue Jul 30, 2024
rdela added a commit to rdela/tugboat that referenced this issue Jul 30, 2024
* updep:
  switch node to js frontmatter
  11ty/eleventy#2819 (comment)
zachleat added a commit to 11ty/11ty-website that referenced this issue Sep 24, 2024
@zachleat zachleat removed the needs-documentation Documentation for this issue/feature is pending! label Sep 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-change-canary This applied a breaking change in a canary release. enhancement
Projects
None yet
Development

No branches or pull requests

6 participants