Skip to content

Commit

Permalink
docs: 0.4.x readability improvements
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Russell <git@ryanrussell.org>
  • Loading branch information
ryanrussell committed Sep 17, 2022
1 parent 41590b1 commit 3a5ff45
Show file tree
Hide file tree
Showing 8 changed files with 13 additions and 13 deletions.
2 changes: 1 addition & 1 deletion docs/0.4.x/en-US/features.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Feature Discovery Terminal

The rest of these docs are written in a bit of an experimental way. Perseus is *really big*, and there are a lot of features that you can use. This is a place where you can learn about them all, and easily find code examples for a particular pattern you want to use. Perseus is written with a ton of a examples, and these are all great sources of information, but they're a bit hard to find sometimes. This page is a list of usage patterns of Perseus that you can use to fidn exactly what you're looking for!
The rest of these docs are written in a bit of an experimental way. Perseus is *really big*, and there are a lot of features that you can use. This is a place where you can learn about them all, and easily find code examples for a particular pattern you want to use. Perseus is written with a ton of a examples, and these are all great sources of information, but they're a bit hard to find sometimes. This page is a list of usage patterns of Perseus that you can use to find exactly what you're looking for!

*Note: this is a bit of an experimental documentation design. Let us know what you think and add your suggestions [here](https://github.com/arctic-hen7/perseus/discussions/new)!*

Expand Down
2 changes: 1 addition & 1 deletion docs/0.4.x/en-US/getting-started/first-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ These two environments couldn't really be more different, and, while Perseus tri

The first section is the usual one, pulling in dependencies that we want everywhere. Both `perseus` and `sycamore` are needed in the browser and on the server-side, so we put them here. Most of the packages you bring in yourself will go here too. As a general rule of thumb, put stuff here unless you're getting errors or trying to optimize your app (which we have a whole section on).

The second is `[target.'cfg(not(target_arch = "wasm32"))'.dependencies]`, which looks scary, but is actually pretty simple when you think about it. It defines the `dependencies` section only on the `target` (operating system) that matches the condition `cfg(not(target_arch = "wasm32"))` --- the target that's not `wasm32`, which is Rust's way of talking about the browser. This section contains engine-only dependencies. In other words, the code that runs in the browser will have no clude these even exist. We put two things in here: `tokio` and `perseus-warp`. The first is an asynchronous runtime that Perseus uses in the background (this means we can do stuff like compile three parts of your app at the same time, which speeds up builds). The second is one of those integration crates we were talking about earlier, with the `dflt-server` feature enabled, which makes it expose an extra function that just makes us a server that we don't have to think about. Unless you're writing custom API routes, this is all you need.
The second is `[target.'cfg(not(target_arch = "wasm32"))'.dependencies]`, which looks scary, but is actually pretty simple when you think about it. It defines the `dependencies` section only on the `target` (operating system) that matches the condition `cfg(not(target_arch = "wasm32"))` --- the target that's not `wasm32`, which is Rust's way of talking about the browser. This section contains engine-only dependencies. In other words, the code that runs in the browser will have no clue these even exist. We put two things in here: `tokio` and `perseus-warp`. The first is an asynchronous runtime that Perseus uses in the background (this means we can do stuff like compile three parts of your app at the same time, which speeds up builds). The second is one of those integration crates we were talking about earlier, with the `dflt-server` feature enabled, which makes it expose an extra function that just makes us a server that we don't have to think about. Unless you're writing custom API routes, this is all you need.

The third section is exactly the same as the previous, just without that `not(...)`, so this one defines dependencies that we use in the browser only. We've put `wasm-bindgen` here, which we could compile on the server, but it would be a little pointless, since Perseus only uses it behind the scenes in making your app work in the browser. (This is needed for a macro that a Perseus macro defines, which is why you have to import it yourself.)

Expand Down
4 changes: 2 additions & 2 deletions docs/0.4.x/en-US/reference/compilation-times.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

As you may have noticed while using Perseus, compiling even very small changes to your app takes *a long time*. This is because Perseus has a significant amount of boilerplate to make all its features work essentially seamlessly, and because Rust generally takes quite a while to compile anything.

The first step in addressing this is to figure out whether your app needs exporting or not. If not, then you should use `#[perseus::main_export]` rather than `#[perseus::main(...)]` in your `lib.rs`, and then you don't need to bring in a server integration, which should speed things up slightly. Notably, if you choose not to do this, there's no actual compile-time difference between `perseus export` and `perseus serve` (there used to be, back in the days of `.perseus/`, but those horrors are gone now). As a general rule, apps that *can* go to static files *should* go to static files, because they'll be faster. (It's also more easily possible to push static files to edge networks in deployment, which usually means faster load times for your users, depending on your hosting provider.)
The first step in addressing this is to figure out whether your app needs exporting or not. If not, then you should use `#[perseus::main_export]` rather than `#[perseus::main(...)]` in your `main.rs`, and then you don't need to bring in a server integration, which should speed things up slightly. Notably, if you choose not to do this, there's no actual compile-time difference between `perseus export` and `perseus serve` (there used to be, back in the days of `.perseus/`, but those horrors are gone now). As a general rule, apps that *can* go to static files *should* go to static files, because they'll be faster. (It's also more easily possible to push static files to edge networks in deployment, which usually means faster load times for your users, depending on your hosting provider.)

The next step is pretty trivial: `rustup override set nightly`. This command will set the default toolchain in your project (you have to run that command in your proejct directory) to `nightly`, which tends to nearly cut compile times in half! In general, the nightly compiler will be much faster than the stable one, because it uses all sorts of unstable features that improve compilation times. If you want maximum assurances though, switch back to the stable compiler before running `perseus deploy` so your production app is secured against any nightly compiler bugs (which do happen) and you get the best of both worlds.
The next step is pretty trivial: `rustup override set nightly`. This command will set the default toolchain in your project (you have to run that command in your project directory) to `nightly`, which tends to nearly cut compile times in half! In general, the nightly compiler will be much faster than the stable one, because it uses all sorts of unstable features that improve compilation times. If you want maximum assurances though, switch back to the stable compiler before running `perseus deploy` so your production app is secured against any nightly compiler bugs (which do happen) and you get the best of both worlds.

From here, we get a little more radical. There's something called [Cranelift](), a compiler backend that can be used [for Rust]() to speed up development compilation times. Of course, the sacrifice here is runtime speed, but as long as you build with the usual compiler for production, you again get the best of both worlds. To set this up, you'll need to download the latest version of [this project](https://github.com/bjorn3/rustc_codegen_cranelift) from [here](https://github.com/bjorn3/rustc_codegen_cranelift/actions?query=branch%3Amaster+event%3Apush+is%3Asuccess) (click on the most recent action run, and then download the appropriate artifact). Then, unzip that (twice, there's a nested zip folder) and you'll get a `build/` folder, which you can put anywhere on your system. Then, add the contents of that (which should contain `cargo-clif` and `rustc-clif`) to your system's `PATH` (tutorial [for Windows](https://stackoverflow.com/a/44272417), and [for Linux/MacOS](https://linuxize.com/post/how-to-add-directory-to-path-in-linux/)).

Expand Down
2 changes: 1 addition & 1 deletion docs/0.4.x/en-US/reference/deploying.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ If you don't need a server for your app, you can use `perseus deploy -e`, which

## Optimizations

Of course, when you're deploying your app, you want it to be as fast as possible. On the engine-side, this is handled automatically by Rust, which will naturally produce super-fast binaries. On the browser-side, there are problems though. This is because of the way the internet works --- before your users can run your super-fast code, they need to download it first. That download process is what's involved in loading your app, which is generally the indicator of speed on the web. That means we actually improve the speed of your app by optimizing more aggreassively for the *size* of your app, thus minimizing download times and making your app load faster.
Of course, when you're deploying your app, you want it to be as fast as possible. On the engine-side, this is handled automatically by Rust, which will naturally produce super-fast binaries. On the browser-side, there are problems though. This is because of the way the internet works --- before your users can run your super-fast code, they need to download it first. That download process is what's involved in loading your app, which is generally the indicator of speed on the web. That means we actually improve the speed of your app by optimizing more aggressively for the *size* of your app, thus minimizing download times and making your app load faster.

With JavaScript, you can 'chunk' your app into many different files that are loaded at the appropriate times, but no such mechanisms exists yet for Wasm of any kind, which means your final `bundle.wasm` will be big. This is often used as a criticism of Wasm: the Perseus basic example produces a bundle that's over 200kb, where a JavaScript equivalent would be a tenth of the size. However, this comparison is flawed, since JavaScript is actually slower to execute. It's an oversimplification, but you can think of it like this: JS needs to be 'compiled' in the browser, whereas Wasm is already compiled. For that reason, it's better to compare Wasm file sizes to image file sizes (another type of file that doesn't need as much browser processing). In fact, that over 200kb bundle is probably faster than the tenth-of-the-size JS.

Expand Down
2 changes: 1 addition & 1 deletion docs/0.4.x/en-US/reference/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ If you add `default-features = false` to your `Cargo.toml` and expect Perseus to

If you've tried to download the bleeding-edge version of the CLI with `cargo install`, using a Git dependency on the `perseus-cli` package, you've probably been hit with a whole host of errors that don't make a whole lot of sense! The reason for this is that the Perseus CLI depends on including a folder that's not checked into Git (the engine, `.perseus/`, but transformed in various ways). That means that, to build the CLI, you need to have that folder available, which `cargo install` isn't smart enough to do yet from a Git dependency.

The way you get around this is unfortunately inconvenient, you'll have to manually clone the whole Perseus repository and then build the CLI yourself. You can do that by running `bonnie setup` in the root of the Perseus repo (after you've cloned it), and then you can build the binary in `packages/perseus-cli/` -- that will give you a copy of the CLI in `target/`! Be warned though that ussing the bleeding-edge CLI is generally not recommended, as the interdependencies in the engine can be quite fragile, and even the smallest changes that aren't breaking usually can be breaking when you're using the bleeding-edge version of the CLI with a released version of Perseus.
The way you get around this is unfortunately inconvenient, you'll have to manually clone the whole Perseus repository and then build the CLI yourself. You can do that by running `bonnie setup` in the root of the Perseus repo (after you've cloned it), and then you can build the binary in `packages/perseus-cli/` -- that will give you a copy of the CLI in `target/`! Be warned though that using the bleeding-edge CLI is generally not recommended, as the interdependencies in the engine can be quite fragile, and even the smallest changes that aren't breaking usually can be breaking when you're using the bleeding-edge version of the CLI with a released version of Perseus.

## Hydration doesn't work with X

Expand Down
4 changes: 2 additions & 2 deletions docs/0.4.x/en-US/reference/initial_subsequent_loads.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Initial vs. Subsequent Loads

In a Persues app, there are two ways for a page in your app to be loaded, and it's important to understand this if you want to work with the more advanced features of Perseus. The first way is an *initial load*, which is when a user comes onto your site from an external URL (e.g. a search engine). The second is a *subsequent load*, which is when a user moves from one page on your site to another (e.g. a link on your landing page takes them to an about page).
In a Perseus app, there are two ways for a page in your app to be loaded, and it's important to understand this if you want to work with the more advanced features of Perseus. The first way is an *initial load*, which is when a user comes onto your site from an external URL (e.g. a search engine). The second is a *subsequent load*, which is when a user moves from one page on your site to another (e.g. a link on your landing page takes them to an about page).

## Initial Loads

Expand All @@ -12,7 +12,7 @@ This HTML file has in it a prerendered version of the page, meaning the user wil

Once this Wasm is loaded, all other links in the app are controlled by subsequent loads. Importantly, if the user goes to an external URL and then comes back, another initial load will occur (though hopefully their browser will have cached the Wasm bundle, reducing the load time to almost zero).

One caveat to all this is if i18n is being used, in which case there's unfortunately no way for the server to reliably know which language a page should be returned in. If the user requested `/en-US/about`, no problem, but if they just gave us `/about`, we need to send them a script to figure out their locale. Specifically, this comes in a blank HTML page that includes the Wasm bundle, which will then detect the locale and mvoe ahead with rendering.
One caveat to all this is if i18n is being used, in which case there's unfortunately no way for the server to reliably know which language a page should be returned in. If the user requested `/en-US/about`, no problem, but if they just gave us `/about`, we need to send them a script to figure out their locale. Specifically, this comes in a blank HTML page that includes the Wasm bundle, which will then detect the locale and move ahead with rendering.

Unfortunately, this approach does lead to a moment of having a blank screen before the Wasm bundle has loaded, something that we aim to resolve in the longer-term.

Expand Down
2 changes: 1 addition & 1 deletion docs/0.4.x/en-US/reference/plugins.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Plugins

Like many fullstack frameworks, Perseus supports *plugins*, which allow you to extend the basic functionality of Perseus in sometimes extreme ways! However, unlike other frameworks, Perseus is already extremely customizabel with usual usage, due to the way it exposes all operations directly to the user. For example, if you wanted to restructure your server, all that code is open to you directly.
Like many fullstack frameworks, Perseus supports *plugins*, which allow you to extend the basic functionality of Perseus in sometimes extreme ways! However, unlike other frameworks, Perseus is already extremely customizable with usual usage, due to the way it exposes all operations directly to the user. For example, if you wanted to restructure your server, all that code is open to you directly.

In earlier version of Perseus, there was a folder called `.perseus/` that stored a large amount of internal code, and plugins were mostly used to modify that. Today, that code simply doesn't exist anymore, and everything is bundled into the main app! (With the consequence of a slightly wild `Cargo.toml`...) This means that most things aren't done with a plugin anymore.

Expand Down
Loading

0 comments on commit 3a5ff45

Please sign in to comment.