Giter Club home page Giter Club logo

leptos-practice's Introduction

Leptos Practice

This repo walks you through a bunch of both client-side and server-side features Leptos provides, such as signals, resources, and server functions.

Tips

These are some notes of what I've learnt through tinkering with this app.

Leptos

  • Leptos is a web frontend framework that is reactive primitive with signals like SolidJS
  • Instead of using virtual DOM, it works with real DOM nodes and can observe and detect partial changes made inside a structure by signal
  • This makes rendering to occur as less frequently as possible

SSR + Hydration

  • In the SSR mode, cargo-leptos helps coordinate the build process that requires two separate binaries: one compiled to native code and running the server, and the other compiled to WASM and running in the browser.
    • In my project leptos-app, they are backend and frontend, respectively.
    • It's a build tool that enables parallel building of server and client in watch mode
      • Execute this command to start watching: cargo leptos watch
    • It's not necessary, but eases the complexity of handling multiple binaries at one hand to a greater extent by giving you some special features:
      • Recompiling both the server and client upon changes made
      • Build-in support for TailwindCSS, SASS, and testing
      • Optimization of the WASM with wasm-opt
    • I'm a big fan of TailwindCSS and the auto recompiling feature sounds fascinating to me, so I decided to use it.
  • In leptos, page loading works in these orders:
      1. The browser makes a GET request for the current URL to the server
      1. The server receives the request and checks whether it has a way to handle it at that path
      • In leptos_axum and leptos_actix, such method as leptos_routes(), or leptos_routes_with_handler() takes route list, decides how to handle it, and generates a list of all possible routes your app can handle
      1. The server renders the root of your app (e.g., <App/>) with the URL being requested and other data such as the HTTP headers
      1. Your app runs once on the server at this timing, building up an HTML version of the component tree that'll be rendered at the current route
      1. The server returns this HTML page, injecting info on how to load the version of your app that has been compiled to WASM so it can run in the browser as well
      • At this stage, the HTML page is still at the state of "dehydrated", without any of the reactivity or event listeners added (In other words, it's waiting to be "hydrated")
      1. The browser receives this HTML page from the server
      1. It immediately goes back to the server to begin loading the JS and WASM necessary to run the interactive, client-side version of your app
      1. When the WASM version has reloaded, it does the same route-matching process as the server did at No.2
      • During this initial hydration phase, the WASM version of you app doesn't recreate the DOM nodes forming your app
      • Instead, it walks over the existing HTML DOM tree, picking up some elements and adding the necessary interactivity
      • Conversely, interacive devices such as a counter button cannot work before the WASM has loaded even though the page appears interactive
  • Client-side navigation works effectively like this:
    • When the user clicks a link to navigate to another page, the browser won't make another round trip to the server
    • Instead of reloading the full page, the WASM version of your app will load the new page right there in the browser, without requesting it from the server
    • Essentially, your app upgrades itself from a server-loaded "multi-page app" into a browser-rendered "single-page app."
      • This has the best of both worlds: a fast initial load time thanks to SSR, and fast secondary navigations thanks to the client-side routing

Reactivity

  • create_signal is similar to useState in React, and almost equivalent to createSignal in SolidJS
  • create_effect is almost equivalent to useEffect in React, but there's a difference;
    • It doesn't take that dependency array
      • Leptos automatically tracks deps knowing which signals are accessed within the effect so you don't have to explictly add it
        • For example, if use_last is true, the effect will rerun whenever first, last, or use_lastchanges in this case
        • but if not, only will first be the tracking target
        let (first, set_first) = create_signal(String::new());
        let (last, set_last) = create_signal(String::new());
        let (use_last, set_use_last) = create_signal(true);
        
        create_effect(move |_| {
            log(
                if use_last.get() {
                    format!("{} {}", first.get(), last.get())
                } else {
                    first.get()
                },
            )
        });

Async

  • create_resource allows you to integrate async into the sync reactive system
    • The word "resource" points to reactive data structure in this context
    • It lets the Future into a signal that returns Some(T) if it's resolved, and None if it's still pending, rather than waiting for its data to be loaded with .async
    • Just like useSWR or useSWRInfinite in swr, a React hooks library, it takes a source signal as its first arg, and a fetcher as its second one
    let (count, set_count) = create_signal(0);
    
    let async_data = create_resource(
        count, // a source signal
        |value| async move {
            logging::log!("loading data from API");
            load_data(value).await
        }, // a fetcher (every time `count` changes, this will run)
    );
    • To create a resource that runs only once, you can pass a non-reactive, empty source signal:
    let once = create_resource(|| (), |_| async move { load_data().await });
  • Compared to create_resource, create_action is more suitable for a situation where an async function needs to run in response to a user's action such as clicking a button
    • e.g., create_action for add_todo, create_resource for list_todos
  • Unlike create_resource, create_local_resource handles local resources that don't load on the server but in the browser
    • Since the Future that a fetcher will generate runs only on the local system, its data type doesn't need to be serializable
  • Both <Suspense> and <Transition> take resource elements as their children, observing the status of them loading
    • If resources are still loading, the fallback component is displayed instead
  • The difference between <Suspense> and <Transition> is the former one causes flickering every time the data reloaded whereas the latter one only shows the fallback the first time
  • <Async> is the no fallback version of <Suspense> that helps omit a bit of boilerplates

sea-orm-cli

  • When you want to start database configurations from scratch, execute this command:
sea-orm-cli migrate init
sea-orm-cli generate entity -u postgres://postgres:postgres@localhost:5432/postgres -o entity/src
  • It generates entity files based on your migration settings

TailwindCSS standalone CLI

  • Reflect the styles in style/input.css on style/output.css by executing this command:
tailwindcss -i style/input.css -o style/output.css --watch
  • In the --watch mode, changes will be reflected soon after you've made in style/input.css

Reference

leptos-practice's People

Contributors

brklntmhwk avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.