How to submit forms on a static website with VueJS and Netlify functions
I have already shared my setup to develop static websites with VueJS, DatoCMS and GraphQL. I recommend you read this first if you didn’t already!
This time I want to explain how you could submit forms, like a contact form, on that serverless architecture.
Please notice: this article uses Netlify functions and requires you to host your webiste on Netlify, even though, the described solutions might also work with AWS Lambda directly, because Netlify uses that internally. However I don’t have any experience with AWS Lambda itself.
TL:DR;
- Install the
netlify-lambda
package - Add the scripts
netlify-lambda serve lambda
andnetlify-lambda build lambda
to your npm config - Create a
netlify.toml
with the right path to your functions - Add the functions path as a
functions
environment variable to your nuxt config - Create your function as a JavaScript file in your
./lambda
folder, e.g../lambda/mail.js
- Export a
handler
method which receivesevent
,context
andcallback
- Make an AJAX call to
process.env.functions+"/mail.js"
in your Vue Component to call the function
Why Netlify functions?
If you created your website like I described in the article mentioned above you will likely want to have static website, which has several benefit. But one of their downsides is processing user data, because there is no server behind. So many people will probably just use a mailto
link to receive emails. Well this might work for some point, but that way you can’t really process those data. It’s hard to collect them, change their status and whatsoever. So without a server we can’t process data. Period.
So, at least for me, the main reason I want to develop static websites is simply because I don’t want to manage a server on my own. And here comes Netlify Functions! Those give you the opportunity to create server side code using JavaScript functions which is absolutely everything we need. While Netlify Functions would really work out of the box there is some setup required to test them locally.
Setting up Netlify Functions
Netlify has a great tutorial on this over here: https://www.netlify.com/docs/functions/#tools-for-building-javascript-functions. But I will go through this briefly.
The package
First install the netlify-lambda
npm package via npm install netlify-lambda --save
. At the time of writing this article I am using the 0.4.0
version of the package.
The scripts
Then add the commands to your npm scripts like so:
"scripts": {
"build": "nuxt build",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
"dev": "NODE_ENV=development nuxt & yarn functions:serve",
"start": "nuxt start",
"generate": "NODE_ENV=production nuxt generate && yarn functions:build",
"functions:serve": "netlify-lambda serve lambda",
"functions:build": "netlify-lambda build lambda",
"precommit": "npm run lint"
},
The important parts are functions:serve
to run a dev server of the functions and functions:build
to prepare them for production. The lambda
in that line is source folder of your functions. Also notice: on the line "dev": "NODE_ENV=development nuxt & yarn functions:serve"
I am starting the nuxt and the functions dev server in parallel.
The config
To make everything work we need to define where those functions will be found. Simply create a netlify.toml
and add those lines:
[build]
command = "yarn generate"
publish = "dist"
functions = "/.netlify/functions"
The publish directory is dist
because that’s the default when you create a static site with nuxt generate
. The path to functions
describes the path when building your functions.
Also you should add the url of your functions to the nuxt.config.js
to use the correct paths on development or production:
env: {
functions: config.env === 'production' ? `${config.url}/.netlify/functions` : 'http://localhost:9000',
},
Creating a function
To create a function you must simply create a file in your lambda
folder, e.g. lambda/mail.js
. Each functions must expose a handler method which will receive three arguments event
, context
and callback
.
exports.handler = function(event, context, callback) {
}
The event
contains any information about the event that triggered the function. In our case we simply need the event.body
which we can parse as JSON via JSON.parse(event.body)
. The context
contains any information about the context the function was called, like user information. The callback
is used to send a respond, like success or error messages.
Creating a mail function
I guess one of the most use cases for functions on static websites are the submission of emails. To submit an email we will also need a mail server, for this I am using Postmark, but you could also use Sendgrid, Mailgun or even your own mail server. To use Postmark we will first install their Node package via npm install postmark --save
. Then create the lambda/mail.js
file and add the following lines:
I commented the important lines in the code, I hope that’s enough for understanding everything, otherwise just let me know.
Calling the function in VueJS
To use the function you basically just have to make an Ajax call to your function and pass the right parameters. You can see an example of that in the code below. Pay special attention to the submitToServer
method! It’s using the fetch
API to make an Ajax call, will then use the data of the Vue component via JSON.stringify(this.contactForm)
and return the response as a Promise so you can use this in the handleSubmit
method.
That’s it!
If you liked please leave a clap for me! Also feel free to comment and share :)