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

Svelte simple counter example #154

Merged
merged 4 commits into from
Nov 14, 2023
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
1 change: 1 addition & 0 deletions docs/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ edit-url-template = "https://github.com/redbadger/crux/edit/master/docs/{path}"
"getting_started/web_leptos.html" = "./Web/leptos.html"
"getting_started/web_react.html" = "./Web/nextjs.html"
"getting_started/web_remix.html" = "./Web/remix.html"
"getting_started/web_svelte.html" = "./Web/svelte.html"
"getting_started/web_yew.html" = "./Web/yew.html"
"getting_started/ios.html" = "./iOS/manual.html"
"getting_started/ios_with_xcodegen.html" = "./iOS/with_xcodegen.html"
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
1. [Web](./getting_started/web/index.md)
1. [TypeScript and React (Next.js)](./getting_started/web/nextjs.md)
1. [TypeScript and React (Remix)](./getting_started/web/remix.md)
1. [TypeScript and Svelte (Parcel)](./getting_started/web/svelte.md)
1. [Rust and Yew](./getting_started/web/yew.md)
1. [Rust and Leptos](./getting_started/web/leptos.md)
1. [Rust and Dioxus](./getting_started/web/dioxus.md)
Expand Down
1 change: 1 addition & 0 deletions docs/src/getting_started/web/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ This section has two guides for building TypeScript UI with Crux:

1. [TypeScript and React (Next.js)](./nextjs.md)
2. [TypeScript and React (Remix)](./remix.md)
3. [TypeScript and Svelte (Parcel)](./svelte.md)

## Web apps with Rust UI

Expand Down
127 changes: 127 additions & 0 deletions docs/src/getting_started/web/svelte.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Web - TypeScript and Svelte (Parcel)

These are the steps to set up and run a simple TypeScript Web app that calls
into a shared core.

```admonish
This walk-through assumes you have already added the `shared` and `shared_types` libraries to your repo, as described in [Shared core and types](../core.md).
```

```admonish info
There are many frameworks available for writing Web applications with JavaScript/TypeScript. We've chosen [Svelte](https://svelte.dev/) with [Parcel](https://parceljs.org/) for this walk-through. However, a similar setup would work for other frameworks.
```

## Create a Svelte App

Let's create a new project which we'll call `web-svelte`:

```sh
mkdir web-svelte
cd web-svelte
mkdir src/
```

## Compile our Rust shared library

When we build our app, we also want to compile the Rust core to WebAssembly so
that it can be referenced from our code.

To do this, we'll use
[`wasm-pack`](https://rustwasm.github.io/wasm-pack/installer/), which you can
install like this:

```sh
# with homebrew
brew install wasm-pack

# or directly
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
```

Now that we have `wasm-pack` installed, we can build our `shared` library to
WebAssembly for the browser.

```sh
(cd shared && wasm-pack build --target web)
```

Create a `package.json` file and add the `wasm:build` script:

```json
"scripts": {
"wasm:build": "cd ../shared && wasm-pack build --target web",
"start": "npm run build && concurrently -k \"parcel serve src/index.html --port 8080 --hmr-port 1174\" ",
"build": "pnpm run wasm:build && parcel build src/index.html",
"dev": "pnpm run wasm:build && parcel build src/index.html"
},
```

Also make sure to add the `shared` and `shared_types` as local dependencies to the `package.json`:

```json
"dependencies": {
// ...
"shared": "file:../shared/pkg",
"shared_types": "file:../shared_types/generated/typescript"
// ...
}
```

#### Create an app to render the UI

Create a `main.ts` file in `src/`:

```typescript
{{#include ../../../../examples/simple_counter/web-svelte/src/main.ts}}
```

This file is the main entry point which instantiates a new `App` object.
The `App` object is defined in the `App.svelte` file:

```js
{{#include ../../../../examples/simple_counter/web-svelte/src/App.svelte}}
```

This file implements the UI and the behaviour for various user actions.


In order to serve the Svelte app, create a `index.html` in `src/`:

```html
{{#include ../../../../examples/simple_counter/web-svelte/src/index.html}}
```

This file ensures that the main entry point gets called.

#### Wrap the core to support capabilities

Let's add a file `src/core.ts` which will wrap our core and handle the
capabilities that we are using.

```typescript
{{#include ../../../../examples/simple_counter/web-svelte/src/core.ts}}
```

This code sends our (UI-generated) events to the core, and handles any effects that the core asks
for via the `update()` function. Notice that we are creating a [store](https://svelte.dev/docs/svelte-store)
to update and manage the view model. Whenever `update()` gets called to send an event to the core, we are
fetching the updated view model via `view()` and are udpating the value in the store. Svelte components can
import and use the store values.

Notice that we have to serialize and deserialize the data that we pass between
the core and the shell. This is because the core is running in a separate
WebAssembly instance, and so we can't just pass the data directly.

## Build and serve our app

We can build our app, and serve it for the browser, in one simple step.

```sh
npm start
```

```admonish success
Your app should look like this:

<p align="center"><img alt="simple counter app" src="./simple_counter.webp" width="300"></p>
```
5 changes: 5 additions & 0 deletions examples/bridge_echo/Crux.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ cores = ["shared"]
template = "web-remix"
source = "web-remix"
cores = ["shared"]

[shells.web_svelte]
template = "web-svelte"
source = "web-svelte"
cores = ["shared"]
7 changes: 7 additions & 0 deletions examples/simple_counter/web-svelte/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
wasm/pkg/
dist/**
target/*
static/*
.parcel-cache/*
package-json.lock
8 changes: 8 additions & 0 deletions examples/simple_counter/web-svelte/.parcelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "@parcel/config-default",
"transformers": {
"*.svelte": [
"parcel-transformer-svelte3-plus"
]
}
}
30 changes: 30 additions & 0 deletions examples/simple_counter/web-svelte/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "web-svelte",
"private": true,
"scripts": {
"wasm:build": "cd ../shared && wasm-pack build --target web",
"start": "npm run build && concurrently -k \"parcel serve src/index.html --port 8080 --hmr-port 1174\" ",
"build": "pnpm run wasm:build && parcel build src/index.html",
"dev": "pnpm run wasm:build && parcel build src/index.html"
},
"dependencies": {
"bincode": "file:../shared_types/generated/typescript/bincode",
"bulma": "^0.9.4",
"concurrently": "^7.6.0",
"parcel": "^2.8.3",
"parcel-transformer-svelte3-plus": "^0.2.8",
"reflect-metadata": "^0.1.13",
"shared": "file:../shared/pkg",
"shared_types": "file:../shared_types/generated/typescript",
"svelte": "^3.56.0",
"typescript": "^4.9.5"
},
"devDependencies": {
"@parcel/config-default": "^2.10.2",
"@parcel/transformer-inline-string": "^2.8.3",
"@parcel/transformer-webmanifest": "^2.8.3",
"@types/node": "^18.15.11",
"@types/webpack": "^5.28.1",
"process": "^0.11.10"
}
}
Loading
Loading