Rust全栈Web开发工具cargo-leptos的使用,快速构建高性能Leptos框架应用
Leptos的构建工具:
特性
- 在监视模式下并行构建服务器和客户端,以获得快速的开发者反馈
- CSS热重载(无需页面重载,仅更新CSS)
- 构建服务器和客户端以进行水合(不支持客户端渲染模式)
- 支持工作区和单包设置
- 使用dart-sass进行SCSS编译
- 使用Lightning CSS进行CSS转换和压缩
- 使用Cargo构建服务器和客户端(wasm)二进制文件
- 使用wasm-bindgen生成JS-Wasm绑定
- 包括对JS代码片段的支持,以便从WASM调用某些JS代码
- 使用Binaryen中的wasm-opt优化wasm
watch
命令用于自动重建和浏览器实时重载test
命令用于运行组成Leptos项目的lib和bin包的测试build
构建服务器和客户端end-to-end
命令用于构建、运行服务器并调用bash shell钩子。钩子通常会启动Playwright或类似工具new
命令用于基于模板创建新项目,使用cargo-generate。当前模板包括- 一个Actix启动器
- 一个Axum启动器
- 一个Axum启动器,将客户端和服务器代码保存在工作区中的单独crate中
- 'no_downloads’特性允许用户管理可选依赖项
开始使用
安装:
cargo install --locked cargo-leptos
如果您出于任何原因需要最新的超级新鲜版本:
cargo install --git https://github.com/leptos-rs/cargo-leptos --locked cargo-leptos
帮助:
cargo leptos --help
要设置您的项目,请查看示例
依赖项
sass的依赖项在首次使用时如果尚未安装且未被which找到,则会自动安装在缓存目录中。 不同版本的依赖项可能会在此目录中累积,因此请随时删除它。
操作系统 | 示例 |
---|---|
Linux | /home/alice/.cache/cargo-leptos |
macOS | /Users/Alice/Library/Caches/cargo-leptos |
Windows | C:\Users\Alice\AppData\Local\cargo-leptos |
如果您希望强制安装依赖项,或者正在使用Nix或NixOs,可以启用no_downloads
特性来安装,以防止cargo-leptos尝试下载和安装它们。
cargo install --features no_downloads --locked cargo-leptos
单包设置
单包设置是指前端和服务器的代码都在同一个包中定义。
配置参数在包的Cargo.toml
部分的[package.metadata.leptos]
中定义。有关可以使用的参数的完整列表,请参阅参数参考。所有路径都相对于包根目录(即相对于Cargo.toml
文件)
工作区设置
使用工作区设置时,支持单包和多包项目。后者是指前端和服务器位于不同的包中。
所有在其Cargo.toml
中定义了[package.metadata.leptos]
部分的工作区成员都会自动包含为Leptos单包项目。多包项目在工作区级别的Cargo.toml
的[[workspace.metadata.leptos]]
部分中定义,该部分接受三个强制参数:
[[workspace.metadata.leptos]]
# 项目名称
name = "leptos-project"
bin-package = "server"
lib-package = "front"
# 更多配置参数...
注意双方括号:可以定义多个项目,并且一个包可以在多个项目中使用。
构建特性
使用cargo-leptos构建时,前端(库包)使用目标wasm-unknown-unknown
和特性--no-default-features --features=hydrate
编译为wasm。
服务器二进制文件使用特性--no-default-features --features=ssr
编译。
参数参考
这些参数在工作区部分[[workspace.metadata.leptos]]
或包(用于单包设置)部分[package.metadata.leptos]
中使用。
请注意,Cargo Manifest使用单词target有两种不同的含义。
作为包的配置[[bin]]
目标和作为编译输出的目标三元组。
在这里,后者被称为target-triple。
编译参数
# 设置使用的二进制目标的名称
#
# 可选,仅在bin-package定义了多个目标时才需要。也可以使用LEPTOS_BIN_TARGET=name环境变量设置
bin-target = "my-bin-name"
# 对输出的css、js和wasm文件启用额外的文件哈希
#
# 可选:默认为false。也可以使用LEPTOS_HASH_FILES=false环境变量设置(必须在运行时也设置)
hash-files = false
# 设置cargo-leptos用于跟踪最新哈希的文件名
#
# 可选:默认为"hash.txt"。也可以使用LEPTOS_HASH_FILE_NAME="hash.txt"环境变量设置
hash-file-name = "hash.txt"
# 编译所有目标时使用的特性
#
# 可选。可以使用命令行参数--features扩展
features = []
# 编译bin目标时使用的特性
#
# 可选。可以使用命令行参数--bin-features覆盖
bin-features = ["ssr"]
# 编译bin目标时是否使用--no-default-features标志
#
# 可选。默认为false
bin-default-features = false
# 为发布编译时bin目标使用的配置文件
#
# 可选。默认为"release"
bin-profile-release = "my-release-profile"
# 为调试编译时bin目标使用的配置文件
#
# 可选。默认为"debug"
bin-profile-dev = "my-debug-profile"
# 编译bin目标时使用的目标三元组
#
# 可选。环境变量:LEPTOS_BIN_TARGET_TRIPLE
bin-target-triple = "x86_64-unknown-linux-gnu"
# 编译lib目标时使用的特性
#
# 可选。可以使用命令行参数--lib-features覆盖
lib-features = ["hydrate"]
# 编译lib目标时是否使用--no-default-features标志
#
# 可选。默认为false
lib-default-features = false
# 为发布编译时lib目标使用的配置文件
#
# 可选。默认为"release"
lib-profile-release = "my-release-profile"
# 为调试编译时lib目标使用的配置文件
#
# 可选。默认为"debug"
lib-profile-dev = "my-debug-profile"
# 修复阻止增量编译的cargo错误(参见#203)
#
# 可选。在0.2.3之前默认为false,自0.2.3和#216起无条件启用(此设置已弃用)
separate-front-target-dir = true
# 将附加参数传递给编译到WASM的cargo进程
#
# 可选。无默认值
lib-cargo-args = ["--timings"]
# 将附加参数传递给构建服务器的cargo进程
#
# 可选。无默认值
bin-cargo-args = ["--timings"]
# 构建服务器时运行的命令,而不是"cargo"
#
# 可选。无默认值。环境变量:LEPTOS_BIN_CARGO_COMMAND
bin-cargo-command = "cross"
# 是否为所有cargo-leptos构建启用擦除组件模式。这优化了编译速度,
# 但代价是每个组件的运行时/二进制大小开销
#
# 可选。默认情况下,调试构建使用擦除组件,发布构建不使用
always-erase-components = false
# 是否为所有cargo-leptos构建禁用擦除组件模式
#
# 可选。默认情况下,调试构建使用擦除组件,发布构建不使用
disable-erase-components = false
# 启用wasm-opt特性
#
# 可选。默认情况下,使用"-Oz"、"--enable-bulk-memory"和"--enable-nontrapping-float-to-int"。有关所有特性,请咨询`wasm-opt --help`
# 通过提供特性,您将覆盖默认启用的特性
wasm-opt-features = ["-Oz","--enable-bulk-memory","--enable-nontrapping-float-to-int"]
站点参数
这些参数可以通过设置相应的环境变量来覆盖。它们也可以在.env
文件中设置,因为cargo-leptos会读取在包或工作区目录及其任何父目录中找到的第一个文件。
# 设置输出的js、wasm和css文件的名称
#
# 可选,默认为lib包名称,或在工作区中为项目名称。环境变量:LEPTOS_OUTPUT_NAME
output-name = "myproj"
# 站点根文件夹是cargo-leptos生成所有输出的位置
# 注意:在工作区中运行时,它相对于工作区根目录
# 警告:此文件夹的所有内容将在重建时被擦除!
#
# 可选,默认为Cargo目标目录中的"/site"。环境变量:LEPTOS_SITE_ROOT
site-root = "target/site"
# 站点根相对文件夹,所有编译输出(JS、WASM和CSS)写入的位置
#
# 可选,默认为"pkg"。环境变量:LEPTOS_SITE_PKG_DIR
site-pkg-dir = "pkg"
# 源样式文件。如果它以_.sass_或_.scss_结尾,则将被`dart-sass`编译
# 为CSS并由lightning css处理。当设置为发布时,它还将被压缩
#
# 可选。环境变量:LEPTOS_STYLE_FILE
style-file = "style/main.scss"
# tailwind输入文件
#
# 可选,激活tailwind构建
tailwind-input-file = "style/tailwind.css"
# tailwind配置文件
#
# 可选,默认为"tailwind.config.js",如果不存在
# 则会为您生成
tailwind-config-file = "tailwind.config.js"
# 用于优化CSS的browserlist查询
#
# 可选,默认为"defaults"。环境变量:LEPTOS_BROWSERQUERY
browserquery = "defaults"
# 资源源目录。在此找到的所有文件将被复制并同步到site-root
# assets-dir不能有一个与site-pkg-dir同名的子目录/路径
#
# 可选。环境变量:LEPTOS_ASSETS_DIR
assets-dir = "assets"
# JS源目录。`wasm-bindgen`具有从JS文件包含JS代码片段的选项
# 使用`#[wasm_bindgen(module = "/js/foo.js")]`。此目录中任何JS文件的更改
# 将触发重建
#
# 可选。默认为"src"
js-dir = "src"
# 启用Leptos工作所需的JS胶水的最小化
# 使用SWC(Speed Web Compiler)来混淆和压缩JS,将其视为模块
#
# 仅适用于发布构建
#
# 可选:默认为false。也可以使用LEPTOS_JS_MINIFY=false环境变量设置(必须在运行时也设置)
js-minify = false
# 您的应用程序可能依赖的其他文件
# 对这些目录中任何文件的更改将触发重建
#
# 可选
watch-additional-files = ["additional_files", "custom_config.json"]
# 服务器提供内容的IP和端口。在您的服务器设置中使用它
#
# 可选,默认为127.0.0.1:3000。环境变量:LEPTOS_SITE_ADDR
site-addr = "127.0.0.1:3000"
# 重载服务器使用的端口号(仅在监视模式下使用)
#
# 可选,默认为3001。环境变量:LEPTOS_RELOAD_PORT
reload-port = 3001
# 用于运行端到端测试的命令。有关端到端测试的部分
#
# 可选。环境变量:LEPTOS_END2END_CMD
end2end-cmd = "npx playwright test"
# 运行端到端测试的目录
#
# 可选。环境变量:LEPTOS_END2END_DIR
end2end-dir = "integration"
# 生成API路由时用于服务器功能的默认前缀。可以
# 使用`#[server(prefix = "...")]`为单个函数覆盖
#
# 这对于为所有服务器功能覆盖默认前缀(`/api`)很有用,而无需
# 需要通过`#[server(prefix = "...")]`手动指定每个服务器功能
#
# 可选。默认为"/api"。环境变量:SERVER_FN_PREFIX
server-fn-prefix = "/api"
# 是否禁用将服务器功能的哈希附加到其API名称的末尾
#
# 当应用程序的客户端需要稳定的服务器API时,这很有用。例如,在
# Tauri应用程序中发布CSR WASM二进制文件。Tauri应用程序发布依赖于每个平台的
# 分发方法(例如,Apple App Store或Google Play Store),这些方法通常
# 比网站更新的频率慢得多。此外,用户通常
# 没有安装最新的应用程序版本。在这些情况下,CSR WASM
# 应用程序需要能够继续调用后端服务器功能API,因此API
# 路径需要一致且不能附加哈希
#
# 可选:默认为false。环境变量:DISABLE_SERVER_FN_HASH
disable-server-fn-hash = false
# 在API路由中包含服务器功能的模块路径。这是一种替代
# 策略来防止重复的服务器功能API路由(默认策略是添加
# 哈希到路由的末尾)。模块路径的每个元素将由`/`分隔
# 例如,完全限定名称为`parent::child::server_fn`的服务器功能
# 将具有`/api/parent/child/server_fn`的API路由(可能具有
# 不同的前缀和哈希后缀,取决于其他服务器功能配置的值)
#
# 可选,默认为false。环境变量:SERVER_FN_MOD_PATH
server-fn-mod-path = false
环境变量
编译lib(前端)或bin(服务器)以及运行服务器时设置以下环境变量。
从Leptos配置回显:
- LEPTOS_OUTPUT_NAME
- LEPTOS_SITE_ROOT
- LEPTOS_SITE_PKG_DIR
- LEPTOS_SITE_ADDR
- LEPTOS_RELOAD_PORT
构建时使用的目录:
- LEPTOS_LIB_DIR:库包相对于工作目录的路径
- LEPTOS_BIN_DIR:二进制包相对于工作目录的路径
有关目录的注意事项:
cargo-leptos
在构建和运行之前将工作目录更改为项目根目录,或者如果在工作区中,则为工作区根目录- 在单包配置中,这两个值设置为相同的值
- 除非您可以保证整个项目结构在运行时也可用,否则避免在运行时使用它们
内部调用cargo-leptos
的外部工具的版本是硬编码的。使用这些环境变量来
覆盖cargo-leptos
应使用的版本(例如LEPTOS_SASS_VERSION=1.69.5
):
- LEPTOS_TAILWIND_VERSION
- LEPTOS_SASS_VERSION
端到端测试
cargo-leptos
为方便起见提供端到端测试支持。它是一个简单的
围绕在特定目录end2end-dir
中执行的shell命令end2end-cmd
的包装器。
end2end-cmd
可以是任何shell命令。对于运行Playwright,它
将是npx playwright test
。
它的作用等同于手动运行:
- 在一个终端中,运行
cargo leptos watch
- 在另一个终端中,切换到
end2end-dir
并运行end2end-cmd
测试设置时,请先尝试上述方法。如果那有效但cargo leptos end-to-end
无效,请创建GitHub工单
完整示例代码
以下是一个基于cargo-leptos的简单Leptos应用示例:
// Cargo.toml
[package]
name = "leptos-app"
version = "0.1.0"
edition = "2021"
[package.metadata.leptos]
output-name = "leptos-app"
site-root = "target/site"
site-pkg-dir = "pkg"
site-addr = "127.0.0.1:3000"
[dependencies]
leptos = { version = "0.5", features = ["serde"] }
leptos_meta = "0.5"
leptos_router = "0.5"
serde = { version = "1.0", features = ["derive"] }
[lib]
crate-type = ["cdylib", "rlib"]
[[bin]]
name = "leptos-app"
path = "src/main.rs"
// src/lib.rs
use leptos::*;
use leptos_meta::*;
use leptos_router::*;
#[component]
pub fn App() -> impl IntoView {
provide_meta_context();
view! {
<Stylesheet id="leptos" href="/pkg/leptos-app.css"/>
<Title text="Leptos App"/>
<Router>
<main>
<Routes>
<Route path="" view=HomePage/>
</Routes>
</main>
</Router>
}
}
#[component]
fn HomePage() -> impl IntoView {
let (count, set_count) = create_signal(0);
view! {
<h1>"Welcome to Leptos!"</h1>
<button on:click=move |_| set_count.update(|n| *n += 1)>
"Click me: " {count}
</button>
}
}
// src/main.rs
use leptos::*;
use leptos_app::App;
#[cfg(feature = "ssr")]
#[tokio::main]
async fn main() {
use axum::Router;
use leptos_axum::{generate_route_list, LeptosRoutes};
use leptos_app::app::*;
let conf = get_configuration(None).await.unwrap();
let leptos_options = conf.leptos_options;
let addr = leptos_options.site_addr;
let routes = generate_route_list(App);
let app = Router::new()
.leptos_routes(&leptos_options, routes, App)
cargo-leptos:Rust全栈Web开发工具
工具介绍
cargo-leptos是一个专为Leptos框架设计的Cargo子命令工具,用于简化和加速全栈Web应用的开发流程。它提供了项目脚手架、开发服务器、构建优化和部署支持等功能,让开发者能够快速构建高性能的Leptos应用。
主要特性
- 一体化开发环境设置
- 热重载开发服务器
- 自动CSS处理和优化
- SSR(服务端渲染)和CSR(客户端渲染)配置
- 简单的部署流程
安装方法
cargo install cargo-leptos
使用方法
1. 创建新项目
cargo leptos new my-leptos-app
cd my-leptos-app
2. 运行开发服务器
cargo leptos watch
这将启动开发服务器,默认在localhost:3000,支持热重载。
3. 构建生产版本
cargo leptos build --release
4. 运行生产服务器
cargo leptos serve --release
配置示例
在Cargo.toml中添加leptos配置:
[package.metadata.leptos]
# 应用名称
name = "My Leptos App"
# 开发服务器地址
site-addr = "127.0.0.1:3000"
# 输出目录
site-root = "target/site"
# 资源目录
site-pkg-dir = "pkg"
# 是否启用热重载
reload-ws-port = 3001
项目结构示例
典型的cargo-leptos项目结构:
my-leptos-app/
├── src/
│ ├── main.rs # 服务器入口
│ └── app/ # 前端组件
├── style/ # 样式文件
├── assets/ # 静态资源
└── Cargo.toml # 项目配置
快速开始示例
创建一个简单的计数器应用:
// src/app.rs
use leptos::*;
#[component]
pub fn App() -> impl IntoView {
let (count, set_count) = create_signal(0);
view! {
<button
on:click=move |_| set_count.update(|n| *n += 1)
>
"点击次数: " {count}
</button>
}
}
完整示例demo
以下是一个完整的Leptos计数器应用示例,包含服务器端和客户端代码:
Cargo.toml配置:
[package]
name = "my-leptos-app"
version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { version = "0.5", features = ["csr"] }
leptos_meta = "0.5"
leptos_router = "0.5"
[package.metadata.leptos]
name = "My Leptos App"
site-addr = "127.0.0.1:3000"
site-root = "target/site"
site-pkg-dir = "pkg"
reload-ws-port = 3001
src/main.rs(服务器入口):
use leptos::*;
use my_leptos_app::App;
fn main() {
// 初始化Leptos应用
leptos::mount_to_body(App);
}
src/app.rs(前端组件):
use leptos::*;
// 定义计数器组件
#[component]
pub fn Counter() -> impl IntoView {
// 创建响应式信号
let (count, set_count) = create_signal(0);
// 增加计数函数
let increment = move |_| set_count.update(|n| *n += 1);
// 减少计数函数
let decrement = move |_| set_count.update(|n| *n -= 1);
// 重置计数函数
let reset = move |_| set_count.set(0);
view! {
<div class="counter-container">
<h1>"Leptos计数器应用"</h1>
<div class="counter-display">
<span class="count-value">{count}</span>
</div>
<div class="counter-buttons">
<button class="btn btn-decrement" on:click=decrement>
"-"
</button>
<button class="btn btn-reset" on:click=reset>
"重置"
</button>
<button class="btn btn-increment" on:click=increment>
"+"
</button>
</div>
</div>
}
}
// 主应用组件
#[component]
pub fn App() -> impl IntoView {
view! {
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>"Leptos计数器"</title>
<style>
"
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background-color: #f5f5f5;
}
.counter-container {
text-align: center;
padding: 2rem;
background: white;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.counter-display {
margin: 2rem 0;
}
.count-value {
font-size: 3rem;
font-weight: bold;
color: #333;
}
.counter-buttons {
display: flex;
gap: 1rem;
justify-content: center;
}
.btn {
padding: 0.5rem 1rem;
font-size: 1.2rem;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
.btn-increment {
background-color: #4CAF50;
color: white;
}
.btn-increment:hover {
background-color: #45a049;
}
.btn-decrement {
background-color: #f44336;
color: white;
}
.btn-decrement:hover {
background-color: #da190b;
}
.btn-reset {
background-color: #008CBA;
color: white;
}
.btn-reset:hover {
background-color: #007B9A;
}
"
</style>
</head>
<body>
<Counter/>
</body>
</html>
}
}
运行步骤:
- 创建新项目:
cargo leptos new my-leptos-app
cd my-leptos-app
-
用上面的代码替换对应的文件内容
-
启动开发服务器:
cargo leptos watch
- 在浏览器中访问 http://localhost:3000 查看计数器应用
这个完整的示例展示了如何使用cargo-leptos创建一个功能完整的Leptos计数器应用,包含响应式状态管理、事件处理和样式设计。