Svelte Client-side Application
Learning Objectives
- You know how to add a Svelte-based client-side application to a project.
- You can create a client-side Svelte project that can retrieve information from a server-side application.
At this point, you should have a working server-side setup that you can start with the docker compose --build
command. Now, we will create a client-side setup that uses Svelte.
Setting up client directory with Svelte
In the root folder of the project (that is, the folder that contains the server
folder), run the command deno run -A npm:sv@latest create client
to create a new Svelte project and a new client
folder for it. The command asks for a few options — use the following:
- Pick “SvelteKit minimal” as the Svelte app template.
- Select “No” when asked for whether to add type checking with TypeScript.
- Do not add anything to the project when asked “What would you like to add to your project?”.
- Select “None” when asked which package manager you wish to install dependencies with.
Once you have selected the options and press enter, a new Svelte project is created to the client
folder. The structure of the whole project is now as follows.
tree --dirsfirst
.
├── client
│ ├── src
│ │ ├── lib
│ │ │ └── index.js
│ │ ├── routes
│ │ │ └── +page.svelte
│ │ └── app.html
│ ├── static
│ │ └── favicon.png
│ ├── package.json
│ ├── README.md
│ ├── svelte.config.js
│ └── vite.config.js
├── server
│ ├── app.js
│ ├── app-run.js
│ ├── deno.json
│ ├── deno.lock
│ └── Dockerfile
└── compose.yaml
Next, go to the folder client
and run the command deno install --allow-scripts
. The command installs the dependencies of the project.
Once the dependencies have been installed, in the client folder, run the command deno run dev --open
to start a development server and to open up the page in the browser.
The development server is available at the address http://localhost:5173
. Accessing it in a browser, you should see a page with the text “Welcome to SvelteKit”.
To shut down the server, press Ctrl + C
in the terminal where the server is running.
Adding a Dockerfile
To containerize the client-side application, we need to add a Dockerfile
to the client
folder. Create a file called Dockerfile
to the client
folder and add the following contents to it.
FROM denoland/deno:alpine-2.0.2
WORKDIR /app
COPY package.json .
RUN DENO_FUTURE=1 deno install
COPY . .
CMD [ "run", "dev", "--host"]
Similar to the server-side application, the Dockerfile uses the Alpine Linux Deno as the base image. The working directory is set to /app
, and the package.json
file is copied to the image. The dependencies are cached with the DENO_FUTURE=1 deno install
command, and the rest of the files are copied to the image. Finally, the command to run the image is defined; the command translates to deno run dev --host
.
The
--host
flag is used to expose the server to the network. This is necessary when running the server in a container, as the server is not accessible from the host machine without it.
At this point, remove the node_modules
folder from the client
folder. This is important especially if you use an operating system that is not Linux, as the node_modules
folder might contain files that are not compatible with the Linux-based Docker image.
Compose configuration
Next, we modify the compose.yaml
file to add the client. Let’s call the service client
. The service is built from the folder client
of the project (i.e., the folder that has the Svelte application).
For development purposes, we bind the folder src
in the folder client
of our project to the src
folder of the app
folder of the container. This way, changes to the source code of the project are immediately reflected in the container. We also expose the port 5173
of the container to the port 5173
of the host machine, and finally define that the client
depends on the service server
.
This configuration looks as follows.
client:
build: client
restart: unless-stopped
volumes:
- ./client:/app
ports:
- 5173:5173
depends_on:
- server
With the above, the compose.yaml
is now as follows.
services:
client:
build: client
restart: unless-stopped
volumes:
- ./client/src:/app/src
ports:
- 5173:5173
depends_on:
- server
server:
build: server
restart: unless-stopped
volumes:
- ./server:/app
ports:
- 8000:8000
Running the project
Now, in the root folder of the project, we can run the project using the docker compose up --build
command. This builds the images and starts the containers.
docker compose up --build
..
Now, the Deno backend is available at the address http://localhost:8000
and the Svelte frontend is available at the address http://localhost:5173
.
To stop the project, press Ctrl + C
in the terminal where the project is running.
Environment configuration
Next, create a file called .env.development
to the root of the Svelte project (the folder client
). Add the following line to the file.
PUBLIC_API_URL=http://localhost:8000
The file .env.development
is used to define environment variables that are used in the development environment. The variable PUBLIC_API_URL
is used to define the address of the API that the Svelte application uses. The prefix PUBLIC_
is used to indicate that the variable is public, meaning that it is available to the client-side code.
The public variables are imported from $env/static/public
in the Svelte project.
Retrieving data from the server
To test the connection and to see that the Svelte application can fetch data from the backend, we can create a component that fetches data from the backend and displays it on the page. Create a folder called components
to src/lib
of the Svelte-project and add component called Message.svelte
to the folder. Place the following code to the Message.svelte
file.
<script>
import { PUBLIC_API_URL } from "$env/static/public";
let message = $state("");
const fetchMessage = async () => {
const response = await fetch(PUBLIC_API_URL);
const data = await response.json();
message = data.message;
};
</script>
<button onclick={fetchMessage}>Fetch message</button>
<p>Message is: {message}</p>
Next, modify the +page.svelte
in the src/routes
to match the following.
<script>
import Message from "$lib/components/Message.svelte";
</script>
<Message />
Now, with the project running (again, with docker compose up --build
), open the address http://localhost:5173
in a browser. You should see a button that says “Fetch message”. Clicking the button should fetch the message “Hello world!” from the server and display it on the page.