Leptos

repository·main·Indexed 12 days ago

https://github.com/leptos-rs/leptos

A Rust framework for building high-performance web applications. This documentation includes integration examples with Axum and Ory Kratos, guides on isomorphic functionality, server-side rendering (SSR), and utilities like the #[lazy] macro for WASM code splitting and LazyRoute for optimized page loading.

Tokens
53.6K
Snippets
180
Records
250
Agent score
97%

What's inside Leptos

  1. Overview of Sitemaps with Axum implementation

    main

    This implementation shows how to serve a dynamic sitemap file via an Axum server.

    Key components of this example include:

    • Data Source: A Postgres database used to store blog post data.
    • Dynamic Generation: Sitemaps are generated based on blog post slugs retrieved from the database.
    • XML Generation: The example uses the xml crate to construct the sitemap XML structure.
  2. Overview of Leptos Core Packages

    main

    Leptos is composed of several modular layers that can often be used independently:

    • leptos: The main entrypoint. It re-exports most layers and provides control-flow components like <Show/>, <ErrorBoundary/>, <For/>, <Suspense/>, and <Transition/>.
    • leptos_meta: Used for managing <head> tags (metadata) from within components. It is decoupled from the core DOM renderer.
    • leptos_router: Provides nested routing logic (based on solid-router). It allows dividing a page into independently-rendered parts.
    • leptos_dom: The DOM renderer and SSR implementation.
    • leptos_reactive: The underlying reactive engine.
    • leptos_macro: Contains the view!, component, and Params (for typed queries/routes) macros.
  3. Use next_tuple to extend or create tuples

    main
    The next_tuple crate provides utilities to extend an existing tuple or create a new tuple by appending a single value to it. This is useful in functional-style transformations where you need to incrementally build up tuple structures.
  4. Use any_spawner to write executor-agnostic asynchronous code

    main

    The any_spawner crate provides a utility to spawn tasks across different executors without coupling your code to a specific runtime. This allows you to write asynchronous logic that can be used in various environments (e.g., different async runtimes) by setting the executor at runtime.

    Key Constraints

    • Single Executor: You can only set one global executor per program.
    • One-time Initialization: The executor must be initialized once at runtime.
    • No Join Handles: The spawn methods do not return a handle or result to track the task.
    • Return Type: The Future being spawned must output ().
    use any_spawner::Executor;
    
    // Initialize the global executor (e.g., using futures_executor)
    Executor::init_futures_executor()
        .expect("executor should only be initialized once");
    
    // Spawn a thread-safe Future
    Executor::spawn(async { /* ... */ });
    
    // Spawn a Future that is !Send (local to the current thread)
    Executor::spawn_local(async { /* ... */ });
  5. Understand the E2E testing stack

    main

    The end-to-end (E2E) testing implementation in this project uses a combination of Gherkin specifications and WebDriver-based browser automation. The stack consists of:

    • Cucumber: The test runner that executes Gherkin specifications as Rust tests.
    • Fantoccini: The browser client used to interact with web pages via WebDriver.
    • Cargo Leptos: The build tool used to compile the example, start the server, and execute the E2E tests.
    • chromedriver: The WebDriver required to provide control for the Chrome browser.
  6. Understand the E2E testing stack for Leptos

    main

    End-to-end (E2E) testing in this project uses a stack designed to run Gherkin specifications as Rust tests, interacting with a real browser via WebDriver. The stack consists of:

    • Cucumber: The test runner that executes Gherkin specifications.
    • Fantoccini: The browser client used to interact with web pages via WebDriver.
    • Cargo Leptos: The build tool used to compile the example, start the server, and execute the E2E tests.
    • chromedriver: The WebDriver implementation for Chrome.
  7. Use the `either_of` crate for multi-type enumerations

    main
    The either_of crate provides utilities for working with enumerated types that can contain one of multiple (2..n) different types. This is useful when you need a single type to represent several distinct possible types in a type-safe manner.
  8. Use OpenAI GPT to drive server functions via OpenAPI

    main

    This project demonstrates a workflow where server functions are documented using an OpenAPI schema (generated via utoipa) and served through a Swagger UI at the /swagger-ui endpoint.

    Crucially, it shows how to transform that OpenAPI specification into a function list that can be fed into OpenAI's chat completion endpoint. This allows the AI to generate JSON values that are then passed back into your Leptos server functions to execute tasks (e.g., 'say hello' or 'generate a list of names').

  9. Understand the Leptos Login Example (CSR Only)

    main

    This project is a Client-Side Rendered (CSR) application example. It demonstrates how to implement authentication using an existing API via an API token, specifically in scenarios where you cannot or do not want to modify the underlying API.

    Key architectural components:

    • CSR Architecture: The application logic and authentication flow reside primarily on the client side.
    • api-boundary crate: This crate provides the shared data structures used for communication between the server and the client, ensuring type safety across the boundary.
  10. Explore Leptos integration examples in the projects directory

    main

    The projects directory contains medium-to-large-scale examples demonstrating various use cases and integrations between Leptos and other libraries. Unlike the core examples directory, these projects are built against specific versions and may not be regularly linted or updated, allowing for a wider variety of community-driven implementations.

    Available project examples include:

    • meilisearch-searchbar: Integrating the Meilisearch Rust-based search engine with a Leptos server to provide an autocomplete search bar.
    • nginx-mpmc: Using Nginx as a load balancer/proxy to provide different clients to users while running multiple Leptos servers that provide server functions.
    • ory-kratos: Running Ory Kratos (Identification service) alongside a Leptos server and utilizing their UI Node data types within Leptos.
    • tauri-from-scratch: A detailed guide on using Tauri to render Leptos apps on non-web targets via WebView, supporting SSR and communication with a Leptos server.
    • counter_dwarf_debug: Demonstrating how to set up breakpoints in the browser or Visual Studio Code for debugging Leptos applications.
    • bevy3d_ui: Using the Bevy 3D game engine alongside Leptos within a WebAssembly (WASM) environment.
  11. How fine-grained reactivity works in reactive_graph

    main

    The reactive_graph crate implements a fine-grained reactive system using three core primitives. This approach models data flow by composing these units, ensuring that updates to a signal only trigger the specific computations or effects that depend on it, avoiding unnecessary diffing.

    Core Primitives

    1. Signals: Atomic units of state that can be directly mutated (e.g., ArcRwSignal). They act as "source" nodes.
    2. Computations: Derived values that cannot be mutated directly but update automatically when their dependencies change (e.g., ArcMemo). They act as both "source" nodes (for others to subscribe to) and "subscriber" nodes.
    3. Effects: Side effects used to synchronize the reactive system with the outside world (e.g., Effect). They act as "subscriber" nodes.

    Key Characteristics

    • Dynamic Dependency Tracking: Dependencies are tracked at runtime rather than being declared statically. If a computation contains conditional logic, it will only subscribe to the dependencies used in the currently active branch. Subscribers automatically unsubscribe from unused dependencies between runs.
    • Asynchronous Effect Scheduling: While updating a signal changes its value immediately, dependent Effects are scheduled as asynchronous tasks. They run during the next "tick" of the async runtime. This makes the library async runtime agnostic (compatible with tokio, wasm-bindgen-futures, glib, etc.).
    • Efficiency Focus: The system is optimized to minimize the execution of effects (which are assumed to be expensive) at the cost of a small amount of raw update speed for signal propagation.
    use reactive_graph::{
        computed::ArcMemo,
        effect::Effect,
        prelude::{Read, Set},
        signal::ArcRwSignal,
    };
    
    let count = ArcRwSignal::new(1);
    let double_count = ArcMemo::new({
        let count = count.clone();
        move |_| *count.read() * 2
    });
    
    // the effect will run once initially
    Effect::new(move |_| {
        println!("double_count = {}", *double_count.read());
    });
    
    // updating `count` will propagate changes to the dependencies,
    // causing the effect to run again
    count.set(2);
  12. Understand the Leptos Reactive System

    main

    The reactive system (leptos_reactive) is the foundation of Leptos. It manages dynamic values (signals), their relationships (derived signals and memos), and side effects (effects).

    Key Concepts

    • Signals: Dynamic values that you give ownership of to the reactive system. When you create a signal, you receive a Copy + 'static identifier (an index into a slotmap arena) used to access the value.
    • Derived Signals & Memos: Values that depend on other signals.
    • Effects: Side effects that run in response to reactive changes.
    • Reactive Scopes: Data ownership is tied to the lifetime of the reactive scope (e.g., a component). When a scope is dropped, the items owned by the reactive system within that scope are also dropped. This acts as a form of 'garbage collection' tied to the UI lifecycle rather than Rust's lexical scopes.

    Design Philosophy

    To minimize expensive side effects (like DOM updates or network requests), the system assumes that data is relatively cheap to compute but side effects are expensive to execute.