Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add vite-svelte example #40

Merged
merged 3 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ axum = "0.7.4"
# Rocket dependencies
rocket = "0.5.0-rc.2"

# Salvo dependencies
salvo = { version = "0.68.3", features = ["serve-static"] }

serde_json = "1.0.118"
tracing = "0.1"
tracing-subscriber = "0.3"
env_logger = "0.9.0"

[[example]]
Expand Down Expand Up @@ -90,3 +96,7 @@ path = "examples/webpack-react/server.rs"
[[example]]
name = "rspack-react"
path = "examples/rspack-react/server.rs"

[[example]]
name="vite-svelte"
path="examples/vite-svelte/backend/main.rs"
16 changes: 16 additions & 0 deletions examples/vite-svelte/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "svelte-salvo-ssr"
version = "0.1.0"
edition = "2021"

[[bin]]
name = "svelte-salvo-ssr"
path = "backend/main.rs"

[dependencies]
salvo = { version = "0.68.3", features = ["serve-static"] }
serde_json = "1.0.118"
ssr_rs = "0.5.4"
tokio = { version = "1", features = ["macros"] }
tracing = "0.1"
tracing-subscriber = "0.3"
21 changes: 21 additions & 0 deletions examples/vite-svelte/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Svelte-Salvo-SSR-template
It is a template for Svelte SSR with Salvo-rs and Vite.

1. Install npm dependencies:
```sh
pnpm install
```

2. Use vite to build svelte client JS and CSS:
```sh
pnpx vite build --config vite.client.config.js
```

3. Use vite to build svelte SSR JS:
```sh
pnpx vite build --config vite.ssr.config.js
```
4. Run Rust server:
```sh
cargo run
```
85 changes: 85 additions & 0 deletions examples/vite-svelte/backend/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use salvo::prelude::*;
use ssr_rs::Ssr;
use std::cell::RefCell;
use std::fs::read_to_string;
use std::path::Path;

thread_local! {
static SSR: RefCell<Ssr<'static, 'static>> = RefCell::new(
Ssr::from(
read_to_string(Path::new("./dist/server/server.js").to_str().unwrap()).unwrap(),
""
).unwrap_or_else(|err| {
eprintln!("Failed to initialize SSR: {}", err);
std::process::exit(1);
})
)
}

#[handler]
async fn index(res: &mut Response) {
let result = SSR.with(|ssr| {
let mut ssr = ssr.borrow_mut();
ssr.render_to_string(None).unwrap_or_else(|err| {
eprintln!("Error rendering to string: {}", err);
String::new()
})
});

if result.is_empty() {
eprintln!("Rendered result is empty");
res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
res.render(Text::Plain("Internal Server Error"));
return;
}

//println!("Rendered result: {}", result); // For debugging

let result: serde_json::Value = match serde_json::from_str(&result) {
Ok(val) => val,
Err(err) => {
eprintln!("Failed to parse JSON: {}", err);
res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
res.render(Text::Plain("Internal Server Error"));
return;
}
};

let html = result["html"].as_str().unwrap_or("");
let css = result["css"].as_str().unwrap_or("");

let full_html = format!(
r#"<!DOCTYPE html>
<html>
<head>
<style>{}</style>
<link rel="stylesheet" href="/client/assets/main.css">
</head>
<body>
<div id="svelte-app">{}</div>
<script type="module" src="/client/main.js"></script>
</body>
</html>"#,
css, html
);
res.render(Text::Html(full_html));
}

#[tokio::main]
async fn main() {
Ssr::create_platform();
let router = Router::new()
.push(Router::with_path("/client/<**path>").get(StaticDir::new(["./dist/client"])))
.push(
Router::with_path("/client/assets/<**path>")
.get(StaticDir::new(["./dist/assets/client"])),
)
.push(Router::with_path("/").get(index));

let acceptor = TcpListener::new("127.0.0.1:8080").bind().await;

tracing_subscriber::fmt().init();
tracing::info!("Listening on http://{:?}", acceptor.local_addr());

Server::new(acceptor).serve(router).await;
}
47 changes: 47 additions & 0 deletions examples/vite-svelte/frontend/App.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<script>
import svelteLogo from './assets/svelte.svg'
import viteLogo from '/vite.svg'
import Counter from './lib/Counter.svelte'
</script>

<main>
<div>
<a href="https://vitejs.dev" target="_blank" rel="noreferrer">
<img src={viteLogo} class="logo" alt="Vite Logo" />
</a>
<a href="https://svelte.dev" target="_blank" rel="noreferrer">
<img src={svelteLogo} class="logo svelte" alt="Svelte Logo" />
</a>
</div>
<h1>Vite + Svelte</h1>

<div class="card">
<Counter />
</div>

<p>
Check out <a href="https://github.com/sveltejs/kit#readme" target="_blank" rel="noreferrer">SvelteKit</a>, the official Svelte app framework powered by Vite!
</p>

<p class="read-the-docs">
Click on the Vite and Svelte logos to learn more
</p>
</main>

<style>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.svelte:hover {
filter: drop-shadow(0 0 2em #ff3e00aa);
}
.read-the-docs {
color: #888;
}
</style>
79 changes: 79 additions & 0 deletions examples/vite-svelte/frontend/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;

color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;

font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}

body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}

h1 {
font-size: 3.2em;
line-height: 1.1;
}

.card {
padding: 2em;
}

#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}

@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
1 change: 1 addition & 0 deletions examples/vite-svelte/frontend/assets/svelte.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions examples/vite-svelte/frontend/head.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function buildHead(head, css) {
return `
${head}
<style>${css}</style>
`;
}
10 changes: 10 additions & 0 deletions examples/vite-svelte/frontend/lib/Counter.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script>
let count = 0
const increment = () => {
count += 1
}
</script>

<button on:click={increment}>
count is {count}
</button>
8 changes: 8 additions & 0 deletions examples/vite-svelte/frontend/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import App from './App.svelte';

const app = new App({
target: document.querySelector('#svelte-app'),
hydrate: true
});

export default app;
6 changes: 6 additions & 0 deletions examples/vite-svelte/frontend/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import App from './App.svelte';

export function render() {
const { html, css } = App.render();
return JSON.stringify({ html, css: css.code });
}
2 changes: 2 additions & 0 deletions examples/vite-svelte/frontend/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// <reference types="svelte" />
/// <reference types="vite/client" />
13 changes: 13 additions & 0 deletions examples/vite-svelte/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Svelte</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/frontend/main.js"></script>
</body>
</html>
32 changes: 32 additions & 0 deletions examples/vite-svelte/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"compilerOptions": {
"moduleResolution": "bundler",
"target": "ESNext",
"module": "ESNext",
/**
* svelte-preprocess cannot figure out whether you have
* a value or a type, so tell TypeScript to enforce using
* `import type` instead of `import` for Types.
*/
"verbatimModuleSyntax": true,
"isolatedModules": true,
"resolveJsonModule": true,
/**
* To have warnings / errors of the Svelte compiler at the
* correct position, enable source maps by default.
*/
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true,
/**
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable this if you'd like to use dynamic types.
*/
"checkJs": true
},
/**
* Use global.d.ts instead of compilerOptions.types
* to avoid limiting type declarations.
*/
"include": ["frontend/**/*.d.ts", "frontend/**/*.js", "frontend/**/*.svelte"]
}
16 changes: 16 additions & 0 deletions examples/vite-svelte/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "my-vue-app",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build && vite build --config vite.config.ssr.js",
"preview": "vite preview"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^3.1.1",
"svelte": "^4.2.18",
"vite": "^5.3.1"
}
}
1 change: 1 addition & 0 deletions examples/vite-svelte/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions examples/vite-svelte/svelte.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'

export default {
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
// for more information about preprocessors
preprocess: vitePreprocess(),
}
Loading
Loading