This post series is indexed at NgateSystems.com. You'll find a super-useful keyword search facility there too.
Last reviewed: Nov '24
1. Introduction
All your development work thus far has been conducted in a local npm run dev
server. Nobody else but you can see your webapp here! To launch it to the expectant world you need to:
- "build" a version of your project that is suitable for remote operation
- "deploy" this to a remote cloud host
2. Building your project
The "build" bit is easy. Just start a new VSCode terminal session for your project and enter the following:
npm run build
This launches the "Vite" build tool that will have been installed in your project automatically during the Svelte installation procedure.
Vite starts by creating an optimized production build of both your client-side and server-side Svelte code. It then applies an "adapter" that tunes this production build for your target environment.
An adapter is a small plugin (a file copied into your project) that takes the built app as input and generates output for deployment - ie for you to upload to the Cloud host. The Google Cloud provides a variety of different hosting environments. The "Google App Engine" (GAE) is the environment used in this post series.
The Google App Engine:
- provides a home for your "built" code
- runs a version of the arrangement that you have previously operated with
npm run dev
when "poked" by a URL submitted to a web browser, - "scales" the resources required to run this arrangement efficiently when multiple users access it simultaneously.
In other words, the GAE is a seriously sophisticated hardware and software complex. Fortunately, since this series isn't doing anything seriously sophisticated (though your opinion might differ), you don't need to worry about this. But what will make you sit up is when I tell you that this is the point at which you will have to start paying Google for its services.
If this scares you, please relax - my own billing over recent years has averaged less than $1 a month.
If you are really concerned about the prospect of paying Google and have already opted out for simplicity by creating a "rules-friendly" webapp as described in Post 3.4, you might like to know that a webapp that contains only client-side code would also have the option of deploying to free Firebase hosting. I'm not going to go into the details here as they'd only be a distraction, but chatGPT would happily supply them if you asked.
So, moving on, as indicated above, you need to find an App Engine "adapter" for your project. While there isn't an official Google Svelte adapter, a thriving Svelte community has posted several different adaptors as open software on Git repositories.
The one I recommend is the svelte-adapter-appengine
. This can be installed with:
npm install --save-dev svelte-adapter-appengine
To use the adapter in your project replace the current content of your svelte.config.js
file with the code shown below:
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import adapter from "svelte-adapter-appengine";
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter(),
},
};
export default config;
And now build your project again with npm run build
.
This should produce output that looks something like the following:
> svelte-dev@0.0.1 build
> vite build
vite v5.4.0 building SSR bundle for production...
✓ 110 modules transformed.
page.server.js initialised
firebaseConfig.apiKey AIzaSyDOVyss6etYIswpmVLsT6n-tWh0GZoPQhM
heartbeats undefined
heartbeats undefined
heartbeats undefined
vite v5.4.0 building for production...
✓ 112 modules transformed.
.svelte-kit/output/client/_app/version.json 0.03 kB │ gzip: 0.05 kB
.svelte-kit/output/client/.vite/manifest.json 8.92 kB │ gzip: 0.94 kB
.........
.svelte-kit/output/server/entries/pages/login-with-cookie/_page.svelte.js 6.90 kB
.svelte-kit/output/server/chunks/internal.js 7.01 kB
.svelte-kit/output/server/entries/pages/inventory-maintenance-all_client-version/_page.svelte.js 7.09 kB
.svelte-kit/output/server/index.js 93.25 kB
✓ built in 4.75s
Run npm run preview to preview your production build locally.
3. Deploying your project
The npm run build
has now been tucked away in your project's build
folder. You can upload this to the web with a simple "deploy" command, but some initial scene-setting is required. You must:
- Move your project onto the Google "Blaze" pricing plan
- Configure your project's use of AppEngine
- Install the GCloud tool that performs the deployment
- Give your Gmail account the App Engine Deployer (roles/appengine.deployer) role in the Cloud console's IAM module.
3.1 Moving a project onto "Blaze" pricing
On the Firebase console's "Project Overview" page for your project, mouse over the tool stack in the left-hand column and note, at the bottom of this, a "Related Development Tools" section showing that the project is currently on the "Spark" free plan. Click the "upgrade" button next to this and then "Select plan" on the "Blaze" popup that now appears.
This will invite you to register a credit card and set a monthly limit on the amount that Google can charge you. My limit is set at $2 and has never been breached
3.2 Configuring App Engine for your project
You do this through the Google Cloud console. This provides an umbrella for the numerous "sub-consoles" that let you configure and administer individual Cloud services.
Sadly, the App Engine isn't listed on the "pinned" Quick access list displayed on the IAM "Welcome" page. But you can easily find it by entering "app engine" in the search box and clicking the "Search" button. Select "Dashboard" from the list of consoles and documents thus revealed.
Now check that the name of your project is showing in the "triple dot" box at the top left of the screen and click the "Create application" button". This will invite you to select a Region (server location) for your project. You'll probably want to use the same regions as you are using for your database. Now, leaving the service account field set to "App Engine Default Service Account", press "Done" to complete the setup
3.3 Setting the App Engine/App Engine Deployer role in IAM
The IAM (Identity and Access Management console) lists the "roles" that have been issued to "principals" for your project. Principals may be people (identified by their Google accounts) or abstract system entities (identified by service accounts). If your Google email doesn't appear as an IAM principal with the "App Engine Deployer" role, your attempts to run a deploy
command will be rejected. To access IAM, return to the Cloud console's welcome page and select "IAM and admin" from the Quick access list.
Now click the "Grant Access" button, enter your Gmail ID in the "new principals" field and then, in the Role field, scroll down to "App Engine" in the left-hand panel and select "App Engine Deployer" in the right-hand panel". "Save" this and you're done.
3.4 Installing the Gcloud tool on your system
The Gcloud tool enables you to to run a terminal gcloud
command to deploy your software to your App Engine host. The installation procedure for the Google Cloud CLI (Command Line Interface) is documented at Google CLI Installation.
Windows users should navigate here to the "Windows" submenu where the document provides a "download" button that creates a Windows Installer file in the download directory. Click this and accept the pre-selected options. The documentation suggests that you need to explicitly request the inclusion of the modules necessary to support App Engine but, at the time of writing (Sept 2024), this no longer appears to be the case.
3.5 Deploying your webapp
This is a big moment! Run the following command in your VSCode terminal session:
gcloud app deploy build/app.yaml --project=[project-id]
Here, [project-id] is the uniquely qualified version of the project name that Google generated when you initialised your project in Post 2.3. For example, my own "svelte-dev" project is deployed with
gcloud app deploy build/app.yaml --project=svelte-dev-80286
The build.yaml
file is an interesting feature of the command. This is a configuration file that was by the preceding Vite "build". It tells gcloud where to find the various artefacts and configurations in the "build" folder.
If all goes well you should see something like the following:
Beginning deployment of service [default]...
#============================================================#
#= Uploading 19 files to Google Cloud Storage =#
#============================================================#
File upload done.
Updating service [default]...-WARNING: *** Improve build performance by generating and committing package-lock.json.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://svelte-dev-80286.nw.r.appspot.com]
You can stream logs from the command line by running:
$ gcloud app logs tail -s default
To view your application in the web browser run:
$ gcloud app browse --project=svelte-dev-80286
This is a huge moment. Your webapp can now be run on the web at https://[Your Project Id].nw.r.appspot.com
(https://svelte-dev-80286.nw.r.appspot.com
in my case). As a short-cut you might use the terminal sessions suggestion to run it by copying and pasting "gcloud app browse --project=svelte-dev-80286" into the terminal session.
4. Summary
I hope that all went well for you. Unfortunately, I expect that if you have made it this far it will have been at the cost of much hair-tearing and, quite possibly, tears. Still, I'm sure that it will have been worth it.
This series concludes in the next section with posts designed to flesh out some aspects of earlier subjects. These would have simply got it in the way I'd introduced them earlier. Just at present, you might find it useful to have a look at Post 4.5 that tells you how you can give you live webapp a smart "Custom Domain" URL to replace the crufty-looking default version that has come out of the development process.
Postscript: When things go wrong
A moment's thought will tell you that, after deployment, log messages on your live pages will no longer go to your project's local terminal session. Instead, they go to the Google Cloud and I'm sorry to say this means that you need to use yet another web-based tool to see them.
So, welcome to the "Google Logs Explorer"!
You'll find the explorer at Google Logs Explorer. Check that your project name is displayed in the "three dot" field at top left and try not be too overwhelmed by the dizzying array of menus and sub-windows.
Your problem here is that Google logs absolutely everything that happens on your project. When you look for console.log
messages, you'll find that these are buried in Google-generated messages about project build activity and page startup etc, etc. Furthermore, Google records this information in minute detail back to the dawn of time. Finding what you want can be a challenge.
To help you through this maze, the Explorer allows you to filter log entries using "Queries" based on log entry field values. If you open a log entry at random (by clicking the >
button in its left-hand margin), you'll see that it is an object containing properties such as logName
and textPayload
. A console.log("In Actions 1")
statement in your webapp, for example, would create a log entry with a textPayload
value of "In Actions 1".
A query is specified by creating a list of "match" criteria for log properties. The example below matches log entries for console.log
messages for my svelte-dev
App Engine project that have the value "In Actions".
resource.type="gae_app"
log_name="projects/svelte-dev-80286/logs/stdout"
textPayload ="In Actions"
The Logs Explorer offers you various methods of setting up your query. The most basic approach would be to type your query specification directly into the "query specification" window revealed by toggling the "confused" square box icon on the RHS of the screen and enabling the "Show query" slider.
To save your typing, various pull-down menus let you select standard filters for "Resource type" and "Severity level" etc. Setting these to "GAE application" and "All severities" seems a good idea for present purposes.
Additionally, of course, you'll want to set the time range for the filter. You do this separately by clicking the "Pick time range" box at the top of the screen and adjusting the start/finish times.
Finally, to run your query spec you click the big blue "Run Query" button at the top right.
In the example below, I've used a "regular expression" in the textPayload
spec to pick up console.log
messages that start with the words "In Actions". This therefore picks up "In Actions 2" and "Action 3" messages as well as the precise "In Actions" matches.
resource.type="gae_app"
log_name="projects/svelte-dev-80286/logs/stdout"
textPayload =~ "^In Actions"
Here's a screenshot for this query displaying logging output for a series of webapp runs on App Engine.
Top comments (0)