Skip to content

Commit

Permalink
docs: documented hydration
Browse files Browse the repository at this point in the history
Also documented currently low Lighthouse scores on mobile.
  • Loading branch information
arctic-hen7 committed Dec 21, 2021
1 parent 4fd38a6 commit c22a5f5
Show file tree
Hide file tree
Showing 10 changed files with 37 additions and 6 deletions.
1 change: 1 addition & 0 deletions docs/next/en-US/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
- [Revalidation](/docs/strategies/revalidation)
- [Incremental Generation](/docs/strategies/incremental)
- [State Amalgamation](/docs/strategies/amalgamation)
- [Hydration](/docs/hydration)
- [CLI](/docs/cli)
- [Ejecting](/docs/ejecting)
- [Snooping](/docs/snooping)
Expand Down
17 changes: 17 additions & 0 deletions docs/next/en-US/hydration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Hydration

In the examples of `Cargo.toml` files shown thus far, we've enabled a feature called `hydrate` on Perseus. This feature controls _hydration_, which is a way of making your app more performant. To explain it, we'll need to go a little in-depth.

Perseus uses server-side rendering of some kind for almost everything. In fact, unless you explicitly make something only run in the browser, Perseus will try to prerender it on the server first, either at build-time (faster, so Perseus does this for everything it can) or at request-time. This prerendering process yields a series of HTML and JSON fiels that make up the markup and state of your app. When a page is requested by a user, Perseus can serve them these files, and then the app shell (the Wasm code that runs everything in a Perseus app in the browser) will bring everything to life.

Those prerendered files can be imagined as solid iron, but, to make your app work, we need molten iron. In the real world, you need a lot of heat to turn iron into a liquid, and you need a lot of code to turn simple markup into interactive buttons and text in a browser! So, let's go through the metaphor a bit more: the build process and server are the miners that fetch all the iron out of the mines of the tempalte code you write. Then, that iron is sent to the user's browser, and the app shell does _something_ to get molten iron that can be used to run your app.

Without hydration, the app shell will kindly thank the server for sending it the solid iron, and will then proceed to mine more of its own. In other words, the app shell will completely ignore the prerendered files that the server has sent (displaying them only until it's ready, which is why Perseus apps still work without JavaScript!).

But with hydration, the app shell can intelligently melt the iron that it's been given, it can _hydrate_ the simple markdown. Using hydration is generally much faster than not using hydration, though it's also very hard to implement! Hydration is done by Sycamore, and it's still experimental right now, so it's opt-in with Perseus. You can use the `hydrate` feature flag to enable it in any Perseus app, though you should be aware that there's a chance that things may break in very strange ways! If this happens, try disabling hydration.

## Performance Costs of Disabling Hydration

Not using hydration will impact your site's performance when the user first loads a page (moving around within the app is no problem), because the browser has to do a little more work, but it also has to completely re-display your site. The difference probably won't be noticeable to users, but tools like Lighthouse will notice this and will penalise your site for it.

Notably, to make hydration better for the community, you should file any bugs about hydration on [the Sycamore repository](https://github.com/sycamore-rs/sycamore).
4 changes: 4 additions & 0 deletions docs/next/en-US/pitfalls-and-bugs.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ This will disable optimizations for your Wasm bundle, which prevents this issue
## I want to apply X to my `Cargo.toml`, but it doesn't work

Perseus has a rather unique code structure that will foil most attempts at modifying your own `Cargo.toml`. For example, if you wanted to change the `codegen_units` in the release profile of your app, you couldn't do this in your own `Cargo.toml`, it would have no effect. The reason for this is that the code your write is actually a library that's imported by the CLI's engines, so any custom configuration has to be made directly on the engines. In other words, you'll need to apply your changes on `.perseus/Cargo.toml` instead. You can also apply customizations on the server and the builder, which are separate crates under `.perseus/`. Note that modifying `.perseus/` and retaining your changes requires [ejecting](:ejecting), or you could [write a plugin](:plugins/writing) if it's a change you make a lot.

## I want to disable a Perseus default feature, but it's not doing anything

If you add `default-features = false` to your `Cargo.toml` and expect Perseus to adapt accordingly, you're in for a bit of a shock unfortunately! The reason for this is that the Perseus CLI isn't (yet) smart enough to know you've done this, so it will completely ignore you and press on with default features in the engine, and those settings will override your own. To disable default features, you'll need to also make these changes in `.perseus/Cargo.toml`, `.perseus/builder/Cargo.toml`, and `.perseus/server/Cargo.toml` (and you'll need to [eject](:ejecting) to save your changes). In future versions, the CLI will be able to detect your preferences for this and update accordingly.
9 changes: 9 additions & 0 deletions docs/next/en-US/what-is-perseus.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ The only issue that prevents Perseus from achieving a consistent perfect score o

</details>

<details>
<summary>I'm seeing really low scores on mobile...</summary>

Right now, it's possible that you may see scores of around 50 on mobile for this website, though do not be alarmed! This is caused by a bug in Sycamore's [hydration systems](:hydration) which makes the Perseus website unusable, so we have to disable hydration. This means Perseus has to render a page and then re-render the whole thing (which you may have noticed if you try to scroll really soon after opening this site).

For the vast majority of sites, you'll be able to use hydration without a problem, and you should see _much_ higher scores (well into the 90s), though there are still some pain points for this website in particular that are being worked through (these should be sorted quite soon)!

</details>

If you're interested in seeing how Perseus compares on speed and a number of other features to other frameworks, check out the [comparisons page](comparisons).

## How convenient is it?
Expand Down
2 changes: 1 addition & 1 deletion examples/basic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
perseus = { path = "../../packages/perseus" }
perseus = { path = "../../packages/perseus", features = [ "hydrate" ] }
sycamore = "0.7"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand Down
2 changes: 1 addition & 1 deletion examples/basic/Cargo.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
perseus = "0.3.0-beta.24"
perseus = { version = "0.3.0-beta.24", features = [ "hydrate" ] }
sycamore = "0.7"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
2 changes: 1 addition & 1 deletion examples/i18n/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ edition = "2018"

[dependencies]
# Perseus itself, which we (amazingly) need for a Perseus app
perseus = { path = "../../packages/perseus", features = [ "translator-fluent" ] }
perseus = { path = "../../packages/perseus", features = [ "translator-fluent", "hydrate" ] }
# Sycamore, the library Perseus depends on for lower-leve reactivity primitivity
sycamore = { version = "0.7", features = ["ssr"] }
sycamore-router = "0.7"
Expand Down
2 changes: 1 addition & 1 deletion examples/plugins/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
perseus = { path = "../../packages/perseus" }
perseus = { path = "../../packages/perseus", features = [ "hydrate" ] }
sycamore = "0.7"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand Down
2 changes: 1 addition & 1 deletion examples/showcase/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ edition = "2018"

[dependencies]
# Perseus itself, which we (amazingly) need for a Perseus app
perseus = { path = "../../packages/perseus", features = [ "translator-fluent" ] }
perseus = { path = "../../packages/perseus", features = [ "translator-fluent", "hydrate" ] }
# Sycamore, the library Perseus depends on for lower-leve reactivity primitivity
sycamore = { version = "0.7", features = ["ssr"] }
sycamore-router = "0.7"
Expand Down
2 changes: 1 addition & 1 deletion examples/tiny/Cargo.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
perseus = "0.3.0-beta.24"
perseus = { version = "0.3.0-beta.24", features = [ "hydrate" ] }
sycamore = "0.7"

0 comments on commit c22a5f5

Please sign in to comment.