The Doctor Is In: Converting Spin 1 Apps to Spin 2

In December, Fermyon released Spin 2.1. While the Wasm Component Model has been quietly humming along inside of Spin since version 1.5, Spin 2 introduced the changes necessary to let developers build and use components. Along the way, we made some breaking changes (which is why we chose to increment the major version).

This post explains how to upgrade Spin apps from version 1 to version 2. Spoiler: The process is as easy as spin doctor. Let’s set up a project and see the transformation in action.

The Setup

I created a TypeScript app with Spin 1.5. To do this, I just did a spin new http-ts hello-spin command. From there, I did an npm init and then a spin build --up and tested everything out.

This left me with a project that looks like this:

tree --gitignore .
.
├── README.md
├── package-lock.json
├── package.json
├── spin.toml
├── src
│   └── index.ts
├── tsconfig.json
└── webpack.config.js

1 directory, 7 files

(Note that by using --gitignore we omit the node_modules/ directory from output.)

And here’s what our spin.toml file looks like:

spin_manifest_version = 1
authors = ["Matt Butcher <matt.butcher@fermyon.com>"]
description = ""
name = "hello-spin"
trigger = { type = "http", base = "/" }
version = "0.1.0"

[[component]]
id = "hello-spin"
source = "target/spin-http-js.wasm"
exclude_files = ["**/node_modules"]
[component.trigger]
route = "/..."
[component.build]
command = "npm run build"

Most importantly, we can see from the first line that this app targets spin_manifest_version = 1.

When Spin 2 was released, the new spin_manifest_version is 2.

Knowing When to Upgrade

Spin 2 can run Spin 1 apps. We can see this easily by installing Spin 2 and running our existing app:

$ spin --version
spin 2.1.0-pre0 (0405da75 2023-12-08)
$ spin build --up
Building component hello-spin with `npm run build`

> hello-spin@1.0.0 build
> npx webpack --mode=production && mkdir -p target && spin js2wasm -o target/spin-http-js.wasm dist/spin.js

asset spin.js 4.56 KiB [compared for emit] (name: main)
runtime modules 670 bytes 3 modules
./src/index.ts 2.85 KiB [built] [code generated]
webpack 5.75.0 compiled successfully in 570 ms

Starting to build Spin compatible module
Preinitiating using Wizer
Optimizing wasm binary using wasm-opt
Spin compatible module built successfully

Finished building all Spin components
Logging component stdio to ".spin/logs/"

Serving <http://127.0.0.1:3000>
Available Routes:
  hello-spin: <http://127.0.0.1:3000> (wildcard)

There was nothing we needed to do at all. It just works.

If you have small Spin applications that already work just fine for you, there may be no need to upgrade.

However, if you are still actively developing the project, we highly recommend upgrading an app as soon as possible. This way, you will continue to gain all of the new features, patches, and performance improvements that are coming along as Spin 2 matures.

Using spin doctor to Upgrade an App

We all know the top level Spin commands: new, build, up, and deploy. But Spin has some other hidden gems, and among them is spin doctor.

The spin doctor command can detect and automatically fix problems with Spin applications. It’s a useful tool when you’re trying to figure out what’s wrong with a spin.toml or why your application is misbehaving.

The automatic upgrade feature of spin doctor was added in Spin 2.1.

One thing it can do is update your app from Spin 1 to Spin 2. Let’s give it a shot. One nice thing we can do up front is look at git’s output to see the current status of our files. Later we can use the same command to view what spin doctor changed.

$ git status
On branch main
nothing to commit, working tree clean

Okay, let’s give the doctor a call.

$ spin doctor
📟 The Spin Doctor is in.
🩺 Checking spin.toml...

⚠  Diagnosis: Version 1 manifest can be upgraded to version 2
🩹 The Spin Doctor can help! Would you like to: Upgrade manifest to version 2
Version 1 manifest backed up to "spin.toml.v1_backup".
❤  Treatment applied!
❤  No problems found.

According to the output, spin doctor did two things:

  • It upgraded our main spin.toml to version 2
  • It saved a backup copy in spin.toml.v1_backup

Let’s check what git sees:

$ git status -sb
## main
 M spin.toml
?? spin.toml.v1_backup

That confirms what we saw in spin doctor’s output: spin.toml was modified, and a backup was created.

Let’s take a look at the new spin.toml manifest:

spin_manifest_version = 2

[application]
name = "hello-spin"
version = "0.1.0"
authors = ["Matt Butcher <matt.butcher@fermyon.com>"]

[application.trigger.http]
base = "/"

[[trigger.http]]
id = "trigger-hello-spin"
component = "hello-spin"
route = "/..."

[component.hello-spin]
source = "target/spin-http-js.wasm"
exclude_files = ["**/node_modules"]
allowed_outbound_hosts = ["redis://*:*", "mysql://*:*", "postgres://*:*"]

[component.hello-spin.build]
command = "npm run build"

Quite a bit has changed during this update. If you’d like to explore the new spin.toml format, it is explained in Writing Spin Manifests, and every parameter is detailed in the Spin Application Manifest Reference. But one thing we can see immediately is that we are now running a version 2 manifest.

Testing the Automatic Update

In order to test out our new application, we will need to rebuild the app. While many apps can just be restarted (since little changed in the way we build the Wasm apps), it is safer to do a full spin build --up to test our changes:

$ spin build --up
Building component hello-spin with `npm run build`

> hello-spin@1.0.0 build
> npx webpack --mode=production && mkdir -p target && spin js2wasm -o target/spin-http-js.wasm dist/spin.js

asset spin.js 4.56 KiB [compared for emit] (name: main)
runtime modules 670 bytes 3 modules
./src/index.ts 2.85 KiB [built] [code generated]
webpack 5.75.0 compiled successfully in 570 ms
Warning: You're using a pre-release version of Spin (2.1.0-pre0). This plugin might not be compatible (supported: >=1.5). Continuing anyway.

Starting to build Spin compatible module
Preinitiating using Wizer
Optimizing wasm binary using wasm-opt
Spin compatible module built successfully
Finished building all Spin components
Logging component stdio to ".spin/logs/"

Serving <http://127.0.0.1:3000>
Available Routes:
  hello-spin: <http://127.0.0.1:3000> (wildcard)

And there we have it! Our application has been automatically upgraded.

Conclusion

In this post, we looked at upgrading a Spin 1 app to Spin 2 using the spin doctor command with the auto-migration addition in Spin 2.1.0.

While Spin 2 can happily run Spin 1 applications, we recommend updating any actively developed apps, as you’ll get all the benefits of new features, fixes, and performance improvements.

If you’d like to explore the features of Spin 2, check out the introductory blog post. And one of the most awesome features of Spin 2 is the ability to compose components. We have an excellent walk-through with some fancy diagrams! And if you’re ready to get started, head over to the quickstart guide.

As always, with Spin, nobody must code alone! Join the Fermyon Discord Server to see what others are building, to ask questions, and to get to know the community.

Interested in learning more?

Talk to us