Skip to content

Commit

Permalink
Merge pull request #1523 from leptos-rs/more-docs
Browse files Browse the repository at this point in the history
Additional random docs
  • Loading branch information
gbj authored Aug 10, 2023
2 parents 19ea6fa + 4def35c commit 0b650ee
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 2 deletions.
2 changes: 1 addition & 1 deletion docs/book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@
- [Responses and Redirects](./server/27_response.md)
- [Progressive Enhancement and Graceful Degradation](./progressive_enhancement/README.md)
- [`<ActionForm/>`s](./progressive_enhancement/action_form.md)
- [Deployment]()
- [Deployment](./deployment.md)
- [Appendix: Optimizing WASM Binary Size](./appendix_binary_size.md)
28 changes: 28 additions & 0 deletions docs/book/src/async/11_suspense.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,34 @@ Every time one of the resources is reloading, the `"Loading..."` fallback will s

This inversion of the flow of control makes it easier to add or remove individual resources, as you don’t need to handle the matching yourself. It also unlocks some massive performance improvements during server-side rendering, which we’ll talk about during a later chapter.

## `<Await/>`

In you’re simply trying to wait for some `Future` to resolve before rendering, you may find the `<Await/>` component helpful in reducing boilerplate. `<Await/>` essentially combines a resource with the source argument `|| ()` with a `<Suspense/>` with no fallback.

In other words:

1. It only polls the `Future` once, and does not respond to any reactive changes.
2. It does not render anything until the `Future` resolves.
3. After the `Future` resolves, its binds its data to whatever variable name you choose and then renders its children with that variable in scope.

```rust
async fn fetch_monkeys(monkey: i32) -> i32 {
// maybe this didn't need to be async
monkey * 2
}
view! { cx,
<Await
// `future` provides the `Future` to be resolved
future=|cx| fetch_monkeys(3)
// the data is bound to whatever variable name you provide
bind:data
>
// you receive the data by reference and can use it in your view here
<p>{*data} " little monkeys, jumping on the bed."</p>
</Await>
}
```

[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/11-suspense-907niv?file=%2Fsrc%2Fmain.rs)

<iframe src="https://codesandbox.io/p/sandbox/11-suspense-907niv?file=%2Fsrc%2Fmain.rs" width="100%" height="1000px" style="max-height: 100vh"></iframe>
Expand Down
74 changes: 74 additions & 0 deletions docs/book/src/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Deployment

There are as many ways to deploy a web application as there are developers, let alone applications. But there are a couple useful tips to keep in mind when deploying an app.

## General Advice

1. Remember: Always deploy Rust apps built in `--release` mode, not debug mode. This has a huge effect on both performance and binary size.
2. Test locally in release mode as well. The framework applies certain optimizations in release mode that it does not apply in debug mode, so it’s possible for bugs to surface at this point. (If your app behaves differently or you do encounter a bug, it’s likely a framework-level bug and you should open a GitHub issue with a reproduction.)

> We asked users to submit their deployment setups to help with this chapter. I’ll quote from them below, but you can read the full thread [here](https://github.com/leptos-rs/leptos/issues/1152).
## Deploying a Client-Side-Rendered App

If you’ve been building an app that only uses client-side rendering, working with Trunk as a dev server and build tool, the process is quite easy.

```bash
trunk build --release
```

`trunk build` will create a number of build artifacts in a `dist/` directory. Publishing `dist` somewhere online should be all you need to deploy your app. This should work very similarly to deploying any JavaScript application.

> Read more: [Deploying to Vercel with GitHub Actions](https://github.com/leptos-rs/leptos/issues/1152#issuecomment-1577861900).
## Deploying a Full-Stack App

The most popular way for people to deploy full-stack apps built with `cargo-leptos` is to use a cloud hosting service that supports deployment via a Docker build. Here’s a sample `Dockerfile`, which is based on the one we use to deploy the Leptos website.

```dockerfile
# Get started with a build env with Rust nightly
FROM rustlang/rust:nightly-bullseye as builder

# If you’re using stable, use this instead
# FROM rust:1.70-bullseye as builder

# Install cargo-binstall, which makes it easier to install other
# cargo extensions like cargo-leptos
RUN wget https://github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-x86_64-unknown-linux-musl.tgz
RUN tar -xvf cargo-binstall-x86_64-unknown-linux-musl.tgz
RUN cp cargo-binstall /usr/local/cargo/bin

# Install cargo-leptos
RUN cargo binstall cargo-leptos -y

# Add the WASM target
RUN rustup target add wasm32-unknown-unknown

# Make an /app dir, which everything will eventually live in
RUN mkdir -p /app
WORKDIR /app
COPY . .

# Build the app
RUN cargo leptos build --release -vv

FROM rustlang/rust:nightly-bullseye as runner
# Copy the server binary to the /app directory
COPY --from=builder /app/target/server/release/leptos_website /app/
# /target/site contains our JS/WASM/CSS, etc.
COPY --from=builder /app/target/site /app/site
# Copy Cargo.toml if it’s needed at runtime
COPY --from=builder /app/Cargo.toml /app/
WORKDIR /app

# Set any required env variables and
ENV RUST_LOG="info"
ENV APP_ENVIRONMENT="production"
ENV LEPTOS_SITE_ADDR="0.0.0.0:8080"
ENV LEPTOS_SITE_ROOT="site"
EXPOSE 8080
# Run the server
CMD ["/app/leptos_website"]
```

> Read more: [`gnu` and `musl` build files for Leptos apps](https://github.com/leptos-rs/leptos/issues/1152#issuecomment-1634916088).
28 changes: 28 additions & 0 deletions docs/book/src/reactivity/14_create_effect.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,34 @@ create_effect(cx, move |prev_value| {

Every time `count` is updated, this effect wil rerun. This is what allows reactive, fine-grained updates to the DOM.

## Explicit, Cancelable Tracking with `watch`

In addition to `create_effect`, Leptos provides a [`watch`](https://docs.rs/leptos_reactive/latest/leptos_reactive/fn.watch.html) function, which can be used for two main purposes:

1. Separating tracking and responding to changes by explicitly passing in a set of values to track.
2. Canceling tracking by calling a stop function.

Like `create_resource`, `watch` takes a first argument, which is reactively tracked, and a second, which is not. Whenever a reactive value in its `deps` argument is changed, the `callback` is run. `watch` returns a function that can be called to stop tracking the dependencies.

```rust
let (num, set_num) = create_signal(cx, 0);

let stop = watch(
cx,
move || num.get(),
move |num, prev_num, _| {
log::debug!("Number: {}; Prev: {:?}", num, prev_num);
},
false,
);

set_num.set(1); // > "Number: 1; Prev: Some(0)"

stop(); // stop watching

set_num.set(2); // (nothing happens)
```

[Click to open CodeSandbox.](https://codesandbox.io/p/sandbox/serene-thompson-40974n?file=%2Fsrc%2Fmain.rs&selection=%5B%7B%22endColumn%22%3A1%2C%22endLineNumber%22%3A2%2C%22startColumn%22%3A1%2C%22startLineNumber%22%3A2%7D%5D)

<iframe src="https://codesandbox.io/p/sandbox/serene-thompson-40974n?file=%2Fsrc%2Fmain.rs&selection=%5B%7B%22endColumn%22%3A1%2C%22endLineNumber%22%3A2%2C%22startColumn%22%3A1%2C%22startLineNumber%22%3A2%7D%5D" width="100%" height="1000px" style="max-height: 100vh"></iframe>
Expand Down
16 changes: 15 additions & 1 deletion docs/book/src/server/26_extractors.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,21 @@ pub async fn axum_extract(cx: Scope) -> Result<String, ServerFnError> {

These are relatively simple examples accessing basic data from the server. But you can use extractors to access things like headers, cookies, database connection pools, and more, using the exact same `extract()` pattern.

> Note: For now, the Axum `extract` function only supports extractors for which the state is `()`, i.e., you can't yet use it to extract `State(_)`. You can access `State(_)` by using a custom handler that extracts the state and then provides it via context. [Click here for an example](https://github.com/leptos-rs/leptos/blob/a5f73b441c079f9138102b3a7d8d4828f045448c/examples/session_auth_axum/src/main.rs#L91-L92).
The Axum `extract` function only supports extractors for which the state is `()`. If you need an extractor that uses `State`, you should use [`extract_with_state`](https://docs.rs/leptos_axum/latest/leptos_axum/fn.extract_with_state.html). This requires you to provide the state. You can do this by extending the existing `LeptosOptions` state using the Axum `FromRef` pattern, which providing the state as context during render and server functions with custom handlers.

```rust
use axum::extract::FromRef;

/// Derive FromRef to allow multiple items in state, using Axum’s
/// SubStates pattern.
#[derive(FromRef, Debug, Clone)]
pub struct AppState{
pub leptos_options: LeptosOptions,
pub pool: SqlitePool
}
```

[Click here for an example of providing context in custom handlers](https://github.com/leptos-rs/leptos/blob/19ea6fae6aec2a493d79cc86612622d219e6eebb/examples/session_auth_axum/src/main.rs#L24-L44).

## A Note about Data-Loading Patterns

Expand Down

0 comments on commit 0b650ee

Please sign in to comment.