I’m blown away by how easy and powerful it is to get Laravel running on the popular serverless platform: Vercel.
This is not a one-to-one replacement for something more robust like Laravel Vapor, but it’s an incredibly useful tool to have in your tool-belt.
Let’s dig in.
You can either create a new Laravel app or use an existing one. I’m going to use Laravel’s CLI tool to quickly scaffold a new app.
To go from stock install to Vercel-ready, we only need to add 3 files to this project:
api/index.php
vercel.json
.vercelignore
Let’s walk through them one by one.
Create a new index.php
file in a new api
folder in the root directory of your Laravel app and fill it in with the following contents:
<?php
// Forward Vercel requests to normal index.php
require __DIR__ . '/../public/index.php';
Unfortunately, Vercel only allows an app’s entry-point to live inside the api
directory, so we have to set up a simple script to forward to Laravel’s normal public/index.php
entry-point.
Add a .vercelignore
file to the root of your project with the following contents:
/vendor
This will make sure we don’t upload the entirety of our vendor
directory to Vercel when we deploy (We’ll set up Vercel to automatically install composer dependencies).
This is the meat of the set up. Create a new vercel.json
config file in your root directory and paste in the following contents:
{
"version": 2,
"framework": null,
"functions": {
"api/index.php": { "runtime": "[email protected]" }
},
"routes": [{
"src": "/(.*)",
"dest": "/api/index.php"
}],
"env": {
"APP_ENV": "production",
"APP_DEBUG": "true",
"APP_URL": "https://yourproductionurl.com",
"APP_CONFIG_CACHE": "/tmp/config.php",
"APP_EVENTS_CACHE": "/tmp/events.php",
"APP_PACKAGES_CACHE": "/tmp/packages.php",
"APP_ROUTES_CACHE": "/tmp/routes.php",
"APP_SERVICES_CACHE": "/tmp/services.php",
"VIEW_COMPILED_PATH": "/tmp",
"CACHE_DRIVER": "array",
"LOG_CHANNEL": "stderr",
"SESSION_DRIVER": "cookie"
}
}
Let’s walk through these settings one by one and review what’s going on. Feel free to skip these explanations.
version
"version": 2,
There are two versions of Vercel: “1” and “2”. We want the new and fancy “2”.
functions
"functions": {
"api/index.php": { "runtime": "[email protected]" }
},
Our entire Laravel app is going to be a single serverless function (in Vercel terms).
We want the entry-point to be our newly added api/index.php
, which is really just a forwarder to the main public/index.php
file that would normally get hit when you visit a Laravel app from a web server.
Notice we specified a “runtime” of “vercel-php”. This is the key to whole set up. “vercel-php” is a community-built PHP runtime for Vercel functions. It does all the hard work for us like installing the proper dependencies and running composer install
.
Check out the repo for more info: https://github.com/juicyfx/vercel-php
routes
"routes": [{
"src": "/(.*)",
"dest": "/api/index.php"
}],
Here we tell Vercel to forward all URIs to our newly setup server less function (our Laravel app).
Think of this like an NGINX config on a normal server.
env
"env": {
"APP_ENV": "production",
"APP_DEBUG": "true",
"APP_URL": "https://bot.laravel-livewire.com",
"APP_CONFIG_CACHE": "/tmp/config.php",
"APP_EVENTS_CACHE": "/tmp/events.php",
"APP_PACKAGES_CACHE": "/tmp/packages.php",
"APP_ROUTES_CACHE": "/tmp/routes.php",
"APP_SERVICES_CACHE": "/tmp/services.php",
"VIEW_COMPILED_PATH": "/tmp",
"CACHE_DRIVER": "array",
"LOG_CHANNEL": "stderr",
"SESSION_DRIVER": "array"
}
If you didn’t see the resemblance, this is going to be our Vercel app’s .env
file.
Here you can specify any environment variables you want set. (What you would normally do in a traditional server’s .env
file).
There are two important things to note:
First, you’ll notice some new env variables you don’t normally see in a .env
file (APP_CONFIG_CACHE
, etc…).
These are typically set by default to various places in a standard Laravel app, but because a serverless app is “state-less”, the only folder we can reliably modify at run-time is Vercel’s tmp
folder.
So we’ll point all “cache/tmp” type settings here.
Second, you’ll notice there is no APP_KEY
or any other sensitive environment info.
Because this file is version controlled, it’s unsafe to store sensitive keys in it. Instead we will use Vercel’s encrypted environment variables feature. We’ll get to that in a bit.
Now that you understand the configuration, let’s actually get something up and live!
First we need the vercel
command-line tool. Let’s install it via npm
:
npm i -g vercel
Now that it’s installed, we need to connect it to your Vercel account (or create a new one if you don’t already have one):
Run vercel login
and enter your email address. Vercel will guide you through the rest. (It’s one of the best command-line login experiences out there)
Here comes the easy part. You can deploy your app by running a single command: vercel
You can basically just hit the enter
key for all the prompts because the defaults are fine for us.
Now, you can visit the provided link to view the progress of your deployment. (In our case: https://vercel.com/calebporzio/vercel-laravel/dn4r8780n
)
From the deployment page, you can “Visit” the actual deployed app. (By clicking “Visit”)
And here it is in all its glory:
This is so cool to me. With 3 small files added to any Laravel project and running a simple command, you can get a free, server-less instance of your app on the internet. It’s kind of mind-blowing.
For a more robust set up. Let’s set our deployment up as “Production”.
To deploy to “Production” with Vercel, we need to push our app to a GitHub repository and link it to our Vercel account.
This way, deployments will be triggered on push automatically.
Let’s go!
Let’s head over to GitHub and create a new repository for our Laravel app.
From your profile’s homepage click the “New” button.
We’ll name it, keep the defaults and create the repo.
Now we can copy and paste the instructions from our new repo’s homepage into the command-line:
(I’m assuming you’ve already set up a Git repo locally for your project, if not run git init && git add . && git commit -m "init"
)
And that’s it, now let’s point Vercel to this repository.
If you visit your new Vercel project’s main page, you’ll see a “Not Connected” link under “Git”. Click it.
You’ll be taken to a page that will prompt you to link your GitHub account with Vercel. I’ve already done this (and can’t undo and redo for this post because I have production code relying on it).
After you’ve linked your GH account, you can specify your new repo’s name and press “Save”.
Now, your app will “redeploy” every time your push to the main
branch on your GitHub repo.
Your app now lives on the URL generated by Vercel. In my case, it’s vercel-laravel-three.vercel.app
.
Vercel makes it easy to set up custom domains if you want something more official. Visit the “Domains” tab under your project’s “Settings”.
For more sensitive environment variables like APP_KEY
or various API keys, you can visit the “Environment Variables” tab in your project’s “Settings”:
These will now be picked up by your Laravel app in production.
So there you have it. Free, easy, serverless Laravel deployments.
This makes it incredibly easy to get proof-of-concepts online quickly, or even larger applications.
I personally use this set up for small, non-critical applications.
My most recent project was a GitHub bot for the Livewire repository. Vercel is the perfect case for something small and isolated like that.
One big hole in what I’ve laid out so far is the lack of database support.
Because Vercel is serverless, your database has to be hosted on a separate cloud platform like AWS.
Setting up a MySQL database with AWS and linking to it with Vercel is actually not that complex and I may cover it in a future post if you bug me enough on Twitter 😛.
Thanks for following along, I hope this improves your life ❤️, Caleb
I send out an email every so often about cool stuff I'm working on or launching. If you dig, go ahead and sign up!