Hacker News new | past | comments | ask | show | jobs | submit login
Elder.js – An Opinionated, SEO Focused, Svelte Framework (elderguide.com)
210 points by ramshorst on May 14, 2021 | hide | past | favorite | 74 comments



Hey all, Elder.js author and maintainer.

Elder's main "opinionated-ness" comes from the fact that we're going to put SEO decisions above all others.

This includes doing things such as:

* partial hydration

* no client-side routing wiz-bang

* 0kb JS if there are no hydrated components

* and several other tradeoffs.

It was also built as an SSG first and it is really good at building very large sites (faster than Hugo). [0]

Happy to answer any questions. Here is an overview of the "whys" behind many of the uncommon decisions Elder.js made. [1]

---

[0] https://github.com/Elderjs/elderjs/discussions/166

[1] https://nicholasreese.com/lessons-from-building-a-static-sit...

Edit: format/add links


happy Elder.js user here! just want to tag on my site for folks who are considering adopting elder/svelte/tailwind:

https://swyx.io/ and source code: https://github.com/sw-yx/swyxdotio/

and it is working great for SEO/performance despite me layering on some extra js for tweets and youtube links and the like.


Pretty happy user here as well! I actually used your source code as reference to build my personal site [redacted], so thanks for open-sourcing!

One issue I have with elderjs (with the version that I'm using - haven't been up to date), is that hot-reloading with rollup seems to cause issues with css. The experience is not as smooth as per say nextjs fast-refresh, but I'm content with it for my use-case.


Try the latest version pushed today. V1.4.0 moved the dev server into the rollup config and it should be a lot smoother.


Awesome, checking it out! Thanks for the great work.


I'm a bit confused about these benchmarks, especially those regarding Hugo. I remember watching a video[0] all the way back in 2015 where Hugo was able to create 5000 pages in roughly 6 seconds. It feels odd that it would take more than 13 times as long to build twice the amount of pages now. Considering that the benchmark you linked to was using newer hardware, and a faster version of Hugo. I guess the benchmark itself might be very different, but it still feels like a huge performance drop.

Anyway, Elder looks very promising, and I like the idea of using Svelte a lot more than working with Hugo templates. What do you think is the main thing that limit the built time for smaller sites?

[0] https://www.youtube.com/watch?v=CdiDYZ51a2o


To be honest, I'm not familiar with the specifics of the benchmark. I was surprised as well.

Currently I think the biggest limiter for small sites is that we sequentially fork the processes and wait for each to bootstrap.

I'm sure we could eek out a huge gain by rewriting it and optimizing, but at this point it is faster than anything else in the ecosystem and throwing more CPU cores at a problem is cheaper than throwing more development hours at the problem. :)


> * partial hydration

I guess I am not caught up on hip terminology. Can you explain what this means to someone who authored his first web site in 1993 on a NeXT Cube what that means?


In front end JS frameworks there is a tendency to render your site on the server, then also ship JS to the client which then takes over the rendering of the page and adds interactivity.

As you can guess this adds a lot of overhead.

Partial hydration allows the developer to specify which parts of the page have interactivity and only those parts of the page are made interactive.


Wow, faster than Hugo. Holy s#%t! That’s insane!

Looks awesome, can’t wait to try it out.


Stoked to hear what you think.

We're building ElderGuide.com (a nursing home directory) which has 18k complex pages in about 1 minute 22 seconds.


Ah, the marvels of modern computer processors when they’re not running 18 layers of bloat.

Re: https://elderguide.com is that where the Elderjs name comes from?


Yep. :) Though I often laugh at the thought of seniors using a cutting edge JS framework.


Senior citizen here and author of (I think) the first book on VuePress. Ah… thanks


Casual ageism in action, don't you just love the tech world.


I was just surveying the terrain for an SEO-dependent static site with headless CMS, so it's nice to have a framework with that particular focus to consider as part of that mix. Thanks!


This guide is nicely written but uses jargon that people who haven’t been keeping up with client and server-side JavaScript frameworks won’t be familiar with, including “route,” “slug,” and “hydration,” not to mention “Svelte” and “SEO.”

It seems fine for its intended audience, but if they wanted to help out beginners who somehow stumbled onto this page, adding some outgoing links to definitions where these terms are introduced might be useful.


WordPress has slugs, SEO is a very broad concept, both don't have anything to do with JS specifically.

"beginners" is a very broad term. You have to write for _somebody_ or your text engages no one.


All these are common terms for static site generation, server side rendering, and web development in general.

If even the front end framework Svelte is new to you, that's hint you'd likely learn more by checking out Svelte.

It's not realistic to expect a project to spell out everything for a complete beginner.


Sure, I’m not expecting anything. I made a suggestion for a minor improvement.


I’ve written about eight Svelte applications and I have no idea what this article is about.

I highly recommend Svelte, though.


This is cool. I just shipped an app using Svelte [1] and I liked working with the framework. I would be interested to work with it more.

My app replaces Safari's new tab page with a wallpaper and weather widget. Obviously performance is crucial for this - your wallpaper needs to appear immediately after you hit Cmd-T.

Svelte was a nice way to get the benefits of a component-based framework while still shipping only a tiny JS bundle to customers. It has some rough edges, but it's cool to see the community fill out the gaps with tools like this.

[1]: https://apps.apple.com/us/app/beautiful-new-tabs/id156706823...


Quite the fan of Elder.js; I build my personal site using it (https://alexanderobenauer.com), where the entire site is built once, each time I push a change, then hosted on static hosting (Netlify).

The flexibility on how routes map to various files and templates is wonderful. Some routes are simply markdown files (copied directly from my notes app) that are then rendered into the right template file.


Hi Nick, just saw your svelte summit presentation you gave and was pretty impressed with Edler.js!

I have a simple site, basically 5 different templates. 2 of those templates will be used for content of ~500 pages each. So Elder was exactly what I was looking for.

However:

I want to re-hydrate my server-side rendered app/dynamic-parts including client-side routing.

Elderguide (and in the YT talk) mentions that for more complex SPA-y stuff I shouldn't use it. I played around with Elder but finally settled on Routify, because it gives me re-hydrated client-site routing out of the box. SvelteKit I haven't looked into at all because they released it just when I was done with my app ;-)

Would you mind elaborate how Elder's feature differ from SvelteKit?

Thank you!

PS.: Even if my use-case might isn't a fit, I think the use-case's where Elder would be my first choice are pretty clear.


To be honest, I've only briefly played with SvelteKit as it still isn't finalized.

Here are the main parts where Elder.js stands out

pros:

* Purpose built for large sites with SEO in mind.

* Hooks and plugin ecosystem for common issues. Responsive images, sitemaps, critical path css, etc.

* 0kb JS and partial hydration.

* Blazing fast builds.

* Async shortcodes make working with and future proofing static content a breeze.

cons:

* The complex Rollup implementation needed for partial hydration leads to less optimal dev experience. HMR isn't a possibility as it currently stands. Until `esbuild` is stable reloads won't be as fast as with Vite.

* Unfamiliar way of handling routing / no dynamic routing. (PR to simplify this is basically done [0])

* No client side routing.

* Less optimal for "apps" and logged in experiences until this PR is merged. [0] This should happen in the next week.

---

[0] https://github.com/Elderjs/elderjs/pull/130


> A Highly Optimized Build Process: that will span as many CPU cores as you can throw at it to make building your site as fast as possible. For reference, Elder.js easily generates a data intensive 18,000 page site in 8 minutes using a budget 4 core VM.

How does this compare to something like Hugo?


Eight minutes!? That’s over 100ms of CPU time per page. I’m baffled and more than a little horrified that you would call that highly optimised. I would honestly expect anything calling itself highly optimised to be doing that in closer to 8 seconds. 1.7̅ms is ample for something carefully put together, probably even in JavaScript and with a database (fetch everything up front in one or so queries), though it’ll certainly be easier in a language like Rust. I admit I’d be decidedly impressed by a reasonably-featured JavaScript SSG doing 18,000 pages in 8 seconds; but more practically, in a JavaScript ecosystem, I’d be targeting definitely under a minute.

I will admit I’ve grown used to Rust code and code that’s been designed to be fast. (Zola’s not that, by the way; it makes many decisions in favour of subjective ergonomics and flexibility at enormous runtime cost, as well as doing a lot of theoretically-unnecessary cloning and such all over the place, which could speed things up a lot if it were sorted out somehow (I haven’t contemplated the matter). For my own website with some admittedly very complex templates, and that’s probably Zola’s slowest part, it’s scaling at about 2ms per page with a warm disk cache. Actually, it does some multithreading, but much of the most expensive stuff in the process isn’t parallelised, so repeated runs average using almost a quarter of my 16-thread laptop. I feel I should multiply that 2ms by something, but I’m not sure quite what!)

Edit: Later on the page: “As of October 2020, ElderGuide.com has ~20k pages and builds in 1 minute 22 seconds.” 4ms wall time (16ms if still operating on four cores) is much more encouraging. I guess the page could do with revision. Later still, “Build times on our ~20k page site are routinely less than 10 minutes on a modest VM.” which seems to be the first set of figures again.


I get what you are saying.

In that example most of it was waiting on the remote database. (I’m ans SQL newb).

That said, Elder.js makes it easy to see what is causing performance hits with full perf tracking.

These days that same site is 1 min 22sec.


General rule of thumb with databases is to reduce the number of queries. Fetch large batches of information. This can be difficult to arrange with how such systems are commonly built and/or coded; some sort of intermediary between the consumer and the database can be warranted, which you can tell, “oh btw, these are the items that I’m going to want, d’you mind just fetching them all now so you can hand them directly to the consumers when they ask for them rather than issuing a new query for each?” In a well-done system like this, the database will be a minor component in the performance—templating and other JS-side transformations are much more expensive than fetching easily-identified rows from a database that’s been designed to handle zillions of requests per surprisingly-small-unit-of-time.

I’m curious what fraction of the 1m22s it now takes is waiting for the database.

Building performance tracking into the product? Good job! That shows me that you’re genuine in caring about it, which is still more encouraging. I’m going to investigate Elder.js.


> much of the most expensive stuff in the process isn’t parallelised

Are you sure? Markdown and template rendering of all pages/sections and image processing is done in parallel. I expect those to be the most expensive stuff. The things that are currently done sequentially are taxonomies (an oversight, the pages in them are rendered in parallel) and the search index generation (oversight as well).


No, I’m not sure; I apologise for being wrong (since you know what you’re doing). I just went searching for signs of threading and rayon and thought I was only finding it on the earlier parts of the process and image stuff. But I wonder why repeated runs of `zola build --drafts` on my site with no images for it to process average less than 25% of total CPU usage? I would have thought >170ms was long enough for it to hit its stride inside each process.


> Eight minutes!? That’s over 100ms of CPU time per page.

Your calculation seems wrong.

(8×60×1000)/18000 = 26.666667 milliseconds per page


Four CPUs were involved, so multiply that figure by four.


It beats it. Here are the benchmarks one of our users ran: https://github.com/Elderjs/elderjs/discussions/166


That's pretty impressive. Hugo appears to have a steady growth in overhead right up until the point where elde.js overtakes it when the number of pages hits 10,000.


I was wondering the same. How does this end up differing from SvelteKit using Vite?


(Elder.js Author)

SvelteKit's offering is great. Much better than Sapper. For Vite the HMR on SvelteKit is better than Elder.js but SvelteKit doesn't offer Partial Hydration.

The main difference is Elder.js is designed for static sites and offers tools to help make building large static sites easier.

For instance, when it comes to building non-trivial static sites, there is a lot of data massaging that needs to happen and be in sync across the entire project. A good example is when reading from a headless CMS or generating a sitemap.

With Elder.js, you can massage this data once and add it where you need to via a hook and it will be available on all pages.

SvelteKit is less opinionated. It is apples and oranges.

edit: a word.


Can't you do partial hydration by setting certain components to not hydrate inside the <script context="module'>? Thats what it says in the docs but it might not be the same thing in my understanding (which is limited). Also aren't app-wide stores basically the least trivial way of keeping data in sync across an app? Certainly not difficult in SvelteKit as it is - in fact I can't imagine it being any easier.


No, SvelteKit does not have support for partial hydration.

What you're describing is the no js option in SK. That doesn't allow you to selectively add some JS, it's either all or nothing. You set this option on a per page basis, not per component.

The massaging of data that Nick talks about here has to do with data that is needed to build the actual pages, not runtime data (which you could use Stores for).



Big fan of Svelte an and was super-exited to find a static site generator that uses Svelte templates. Actually just released a redesign of my personal site using Elder.js today and am looking forward to using it for more projects in the future.

My site: https://apop.tech GitHub repo: https://github.com/apop880/apop-tech


Previous built static sites with Jekyll (ruby) and most recently moved to NextJS + strapi.

This project looks like exactly what I was really after, 100% seo optimised / prioritised + all SSG. Will definitely give this a shot for the next project.

Appreciate the effort!


Do you support full pre-rendering?

Let's say I have 100 blog posts - can each of them be pre-rendered into HTML and stored on a CDN? Thereafter if I change a sentence in one of them, can it only recreate the one HTML that was changed?


Elder.js is designed to render the entire site at a time. 100 pages should take substantially less than 10s in most CI/CD pipelines.

We refer to what you are looking for as incremental builds and it is honestly a pretty difficult problem as it requires tracking data dependencies. Here is an overview of the complexities. [0]

[0] https://github.com/Elderjs/elderjs/issues/8


I don't understand what "opinionated" stands for in the context of a software/framework/technology.


"Opinionated" means the software has made very deliberate design tradeoffs and is very inflexible/resistant to changing that. This is done to optimize certain objectives like software scope or increasing productivity by enforcing certain methods.

So in this case they cited "no client-side routing wiz-bang" -- that's one of their opinions and won't be introducing any support for that sort of thing.

The classic example is Python's motto "There's Only One Way To Do It", which was in a response to Perl's "There's more than one way to do it."

Another example is Ruby On Rails...it has a strong opinion on how the application should be structured -- must be MVC, most of your code should be in a model, convention over configuration, etc.


Generally, rather than trying to be a generic framework/tool/system allowing all approaches and preferences and practices, it is optimized for / selects a certain subset toward a (hopefully) stated goal and subset.

It is "opinionated" in the sense that it has an "opinion" on what's the right way to accomplish a certain outcome, and thus it preselects/premakes some choices for you.

The implicit tradeoff is that it may not be as good at general problems / all approaches, but may be better or easier or both for specific goals / approaches.


It means that the framework makes certain choices and trade-offs, and doesn't allow the developer using it a choice in those matters.


> and doesn't allow the developer using it a choice in those matters.

I never took "opinionated" software as "no configuration". For me it's always been "custom defaults". It might provide some configuration, it might not, but what makes it opinionated is the fact that the defaults are not generally applicable, but rather tailored for a specific use case.


Hmm, you're probably right, that's a better definition of opinionated.

That said, I think it'd be really difficult to work around Elder.js' opinions.


So a game is just an opinionated game engine.


A game engine is just an opinionated turing machine.


An example of an opinionated game engine would be idTech 5 (Rage engine). It is built around MegaTexture: a huge, non-repeating texture that maps the entire world, backed by a robust caching system.

It allowed for highly complex scenes, great static lighting and short loading times but it lacked in detail and dynamic elements.


So you wrote a whole SSG SEO Svelte Framework for a guide for elderly people and released it as Elder.js? I love it :)


Yep. That’s the story. :)

Lots of Svelte users asked how I built the site so I figured it was worth open sourcing.


I still find front end JavaScript development to be a chore, the least appealing part of any project idea, despite actually liking Working with HTML and CSS… it’s not even really JavaScript as a language.

It’s the ecosystem I don’t like. I read about “opinionated frameworks” and for a backend framework that tends to be something like Django or Rails, frameworks built to give you everything top to bottom, with clear layering and extension points. However for front end frameworks opinionated seems to mean “has more indecipherable lisp/scheme function/macro style logic” that does what the original author designed it for wonderfully but is a royal pain to extend, modify or really build off in any way other than just forking it.

I’d call this a “framework for sites where SEO is critical” not really an “opinionated framework” it’s more of a “single issue framework” to borrow a political term”

The only “opinionated framework” I’ve ever used in the front end/JavaScript world that felt like a cohesive, truly opinionated framework in the backend Django/Rails kinda way is EmberJS. Which I highly recommend to people who hate the whole JavaScript ecosystem churn. About the only negative I can highlight was poor IDE tooling with older versions which the most recent releases have improved on their end, but is for the most part an issue of IDE developers like JetBrains not considering EmberJS as important as the Angular family and the React, Vue, and other JSX based system family. Which I can understand for the most part due to business realities, but also this is hardly a good reason not to try something when the tools have full auto-reload and progressive compilation to efficiently test things in the browser as you make changes in any text editor you like.


All opinionated-ness seems to be very arbitary. It's a nice way to say "magical api"


Was just going to say: I have only experienced one thing that branded itself opionionated, which was a CSS (reset) file.

So many unexpected behaviours that were really hard to diagnose.

I am now very wary of things calling themselves opinionated.

Though, simultaneously, where does being 'opinionated' start?

Like, we are all building on top of other things, where, inevitably, certain decisions have been made for us. You have to decide whether you can live with those decisions (people say Go, as a language, is quite opinionated), or whether you are going to fork the language and make your own, hehe


When I see opinionated I assume that the developer made a decision that they like, but they know some people won't like. They are saying up front that they aren't trying to satisfy everyone. They're doing it this way, so don't open up issues asking them to support doing it another way.


Opinionatedness is a good thing when a problem has no consensus solution, yet a decision needs to be made.

If the author correctly identifies the problem and is right about the hard part of the solution and manages to convince other people, the community will accept the unimportant parts as default and discard the important but wrong (by consensus, made possible by the opinionated solution) parts.


> Opinionatedness is a good thing when a problem has no consensus solution, yet a decision needs to be made.

This is an excellent and concise way to sum it up.


> simple — It solves my use case.

> opinionated — I don’t believe that your use case exists.

> elegant — The only use case is making me feel smart.

> lightweight — I don’t understand the use-cases the alternatives solve.

https://programmingisterrible.com/post/65781074112/devils-di...


Love this. Gonna remember it.


So the docs are embedded inside a website for elderly care? thats interesting....


Hey, it's an SEO framework. :) Decided as an experiment that links should go to the SEO project that spawned the framework.

So far the links from the JS ecosystem seem to be confusing Google's algos, but we'll give it more time to see how it plays out.


yeah if anything, its a cool mental workout to suddenly realize you are inside the 'creation' that the framework has made.


This is very appealing considering the limitations of client side hydration svelte still has – though I wonder where this stands in relation to the upcoming release of SvelteKit.


elder has important differences to sveltekit: nick has commented on it here https://news.ycombinator.com/item?id=27153319

between the two they honestly reflect all the most relevant site rendering strategies today.


How does this compare to something like SvelteKit with an adapter to generate a static site? I don't know much about Svelte, so maybe my question is weird.


nick (elderjs author) answered the elderjs vs sveltekit question up thread: https://news.ycombinator.com/item?id=27153319


Does it support I18n by default or it needs a plugin? - Sitemap multilanguage - href alternative in head


There is a community plugin for i18n: https://github.com/kiuKisas/elderjs-plugin-i18n


Does a production deploy require a backend server?


Nope. It generates a fully static site with HTML, CSS, JS that you can deploy with any static host. (s3, netlify, cloudflare workers)




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: