Deploying Sapper with Up

Grosse mer à Étretat by Claude Monet.

A quick note about this guide: this is a work in progress, which I am updating as I get my own deploy pipeline working; feel free to ping me on Twitter if something isn’t working right in the steps I outline below, and I’ll update this guide as quickly as possible.

What this is: a simple guide for deploying a generic instance of Sapper using TJ Holowaychuk’s deployment manager, Up.

What this is not: a generic guide for deploying to any given hosting service.

In other words, this is a very specific provider and use case. Just the same, I thought I’d write something up (no pun intended) to help no matter what your use case. Hopefully this will help you, even if you’re using a different service, since some of the methodology for deployment will be similar across different services.

About Sapper and Svelte

If you don’t know what Sapper and Svelte are, Rich Harris (the framework author) has written up a few revelatory blog posts outlining some truly novel approaches to these modern tools. You can read Svelte’s intro blog post here and Sapper’s intro here.

Without saying too much, I’ll just add my own quick adulation. Svelte and Sapper are phenomenal! There’s some truly groundbreaking innovation taking place under Rich’s tutelage, and the tooling is slowly but steadily leading to the type of amazing computing paradigms Bret Victor is famous for advocating. There’s more to say here, but I’ll just </hyperbole>. 😆

Installing Sapper

One easy way to get Sapper up and running is to clone the sapper-template repository. From the Sapper docs:

npm install -g degit
degit sveltejs/sapper-template my-app
cd my-app
npm install
npm run dev

You’re now ready to code in Sapper (and Svelte)! But let’s deploy your app first.

Install and set up Up

A quick note about Up. At the time of this writing, Up has a 50% early adopter promo coupon, so if you decide you need to sign up, make sure to use the code am-376E79B073F3. Also, much of what is listed here can be read over at the Up documentation site, but including step by step for convenience. (Additionally, here’s a good introduction to Up for the uninitiated.)

First, install Up:

curl -sf https://up.apex.sh/install | sh

Note that if you’re using a build pipeline or some type of sandboxed service to operate your deploys, you may need to specify an alternate (bin) directory. Here’s what I did on CodeShip:

curl -sf https://up.apex.sh/install | BINDIR=. sh
Wheatstack (Sun in the Mist)

Set up an IAM role and set AWS credentials

You’ll need to go into the IAM console on AWS to set up your user and policy. Fortunately, Up provides a useful default IAM policy to set the correct access rights to different AWS resources. You can copy that policy here. (Just click the “Show policy” link.)

If you’re developing locally, you’ll need to install the AWS cli. But if you’re only concerned with live deploys, you can skip the parts in the next few paragraphs about the AWS cli and local credentials, though that may still prove useful depending on your particular pipeline.

If you’re on a Mac and have Homebrew installed, it’s as simple as running:

brew install awscli

Otherwise, the primary package manager for installing the cli is Python’s package manager pip. If you already have pip and the necessary Python version installed, run:

pip install awscli --upgrade --user

If things aren’t going right, you can refer to the official awscli documentation.

Now that you have an IAM user and keys, you’ll need to put them in the right place with the AWS cli so Up can automagically take advantage of them. For local access, these are placed in the ~/.aws/credentials file with the following command (make sure to enter the right AWS user profile name, my-app-user in this case):

aws configure --profile my-app-user

That should give you a credentials file looking something like this:

[my-app-user]
aws_access_key_id = xxxxxxxxxx
aws_secret_access_key = xxxxxxxxxx

Otherwise, for a non-local deployment pipeline you’ll need to set a couple environment variables, like so:

AWS_ACCESS_KEY_ID=xxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxx

(In my example, on CodeShip, I went to “project settings” > “environment” to add the environment variables.)

Up Configuration

With Up installed and AWS configured with the right environment variables, you’ll now want to configure your Up/Sapper project. This is done with an up.json file in the root of your project folder. Here’s one way to structure that file with two different stages (production and staging):

{
"name": "my-app",
"profile": "my-app-user",
"regions": ["us-east-1"],
"stages": {
"production": {
"domain": "my-app.com"
},
"staging": {
"domain": "staging.my-app.com"
}
}
}

Make sure to replace my-app and my-app-user with the actual name of your project as well as the AWS (“profile”) IAM user. Also make sure you’re pointing to the right AWS region(s), as well as the correct domain names of your production and staging apps.

Domains and DNS routing

If you’d like to use Up to purchase your domains, you can do so directly from the command line. Just follow these instructions.

But if you have domains that have been purchased elsewhere, you’ll need to map those correctly with a few more steps. First, figure out what nameservers to map by running:

up stack

That should output something roughly like:

Production
domain: my-app.com
endpoint: xxxxxxxxxxxxxx.cloudfront.net
nameservers:
• ns-xxx.awsdns-xx.net
• ns-xxx.awsdns-xx.com
• ns-xxxx.awsdns-xx.co.uk
• ns-xxxx.awsdns-xx.org
Staging
domain: staging.my-app.com
endpoint: xxxxxxxxxxxxxx.cloudfront.net

You can then sign in to you registrar’s website (name, namecheap, godaddy, etc.) and fill in the four nameservers to your provider’s interface. Note: altering DNS records can take some time to propagate, so this step may require some patience.

For more explicit instructions on the above step, again, refer to the Up documentation.

Finally, if you don’t have domains yet and want to just fallback on AWS defaults, it’s a simple as excluding the domain names:

{
"name": "my-app",
"profile": "my-app-user",
"regions": ["us-east-1"],
"stages": {
"production": {},
"staging": {}
}
}

Note that the first time you make any stack changes (before your first deploy), Up won’t complain about staging changes, etc. However, any additional changes after the first deploy will need to be planned and applied:

up stack plan
up stack apply

Deploying

One more important thing to note about Up which you’ll need for your Sapper app. When Up deploys, it actually just uploads everything local to the folder, excluding any .* files and anything in .upignore. This means if you have a build folder—which Sapper does—you’ll need to create a build hook for that in your up.json file. That file should now look something like the following, hook included:

{
"name": "my-app",
"profile": "my-app-user",
"regions": ["us-east-1"],
"hooks": {
"build": [
"npm run build"
]
},
"stages": {
"production": {
"domain": "my-app.com"
},
"staging": {
"domain": "staging.my-app.com"
}
}
}

Now you’re ready to deploy! Deploying to production is now as simple as:

up

That’s it! And for staging, just specify the target:

up staging

I like to see everything that’s happening, so I’ll often run:

up staging -v

Up has a number of great commands which you can see in the documentation or just type up --help.

Again, if you’re deploying via a pipeline, just insert one of the appropriate commands above at the tail end of any other deploy commands. As long as your AWS environment variables are all set, Up should upload everything correctly.

Poplars (Wind effect)

A note about Node versions on AWS Lambda

At the time of this writing, AWS Lambda defaults to Node version 8.10, which should be adequate for most needs. However, if you need to run a more cutting-edge version of Node, you should be able to do so by putting a Makefile in the root of your project with something like:

node-v9.5.0-linux-x64:
@curl -sL https://nodejs.org/dist/v9.5.0/node-v9.5.0-linux-x64.tar.gz | tar -xz

Make sure to specify the right version for your needs. Then in your up.json file, include a make build step in one of your hooks, like so:

“hooks”: {
“build”: [
“make”
]
},

That should do the trick.

Wrap Up

Hopefully this guide has helped you get up and running quickly. If you need additional help or if I somehow missed a step (likely!—I had a few missteps getting started on my own) please ping me personally on Twitter so I can update this guide. Or stop over in our Discord channel.We love helping people out and want every step for onboarding newcomers to be seamless as possible.

Also, if you have a cool project you’re building with Sapper and Svelte, let us know about that too!

A Seascape, Shipping by Moonlight