It's often recommended in the JAMstack best practices to delegate to serverless cloud functions the dynamic parts of an app. To that end, let me introduce you WarpJS, a new serverless approach. It's a JavaScript engine to develop back ends, to bridge the gap with the front end and to deploy it as serverless functions in no time. Made for JavaScript developers with love!
Without any further ado, let's get started!
(If you don't feel like reading, we've also created a video tutorial for this!)
1. Initialize project
Starting from scratch, with a freshly created Vue.js project.
$ npm install -g @vue/cli @vue/cli-service-global
$ vue create <project-name>
Alternatively, you can fork the project right here and skip all the code source copy/pasting steps.
2. Create the back end
Let's create a server
directory at the root of your main project and initialize a new Node.js project inside it:
$ cd <project-name>
$ mkdir server
$ cd server
$ npm init
Here we will create a Basic HTTP Proxy in Node.js in order to:
- Fetch data from a REST API (https://jsonplaceholder.typicode.com/users)
- Filter data to avoid to request too much data as client side
- Add random avatar in response
To do so, we first need to install the Axios library we need:
$ npm install axios
3. Create a serverless function
Then I create an index.js
, and I retrieve first with Axios the flow. I will reduce the attributes, keeping only the id, the email… and a couple of others. I've also added a Lego random portrait (because.).
const axios = require("axios");
const getUsers = async () => {
// fetch users from API
const { data } = await axios.get("https://jsonplaceholder.typicode.com/users");
// Pick attributes and add photo
return data.map(({ id, name, email, phone, company, address }) => ({
id,
name,
email,
phone,
city: address.city,
work: company.name,
photo: "https://randomuser.me/api/portraits/lego/" + (id % 10) + ".jpg",
}));
};
But most importantly I export this function:
// getUsers will be the function that you will can call directly in the framework
module.exports = { getUsers };
This will tell WarpJS: "okay, I need this function to be turned serverless and to be hosted as a serverless function". That way we don't have at all to deal with HTTPS, we don't deal with the arguments, the errors, the endpoints, or anything else.
So now let's see how to set it up!
4. Configure WarpJS
In my server project, I need to create a WarpJS configuration file, warp.config.js
as follows:
module.exports = {
project: "project-server-name",
output: {
format: "node-module",
// path to the "node_modules" directory of your main project
projectPath: "../",
// module name to import it in your main project
name: "warp-server",
},
};
Thanks to the node-module
output format, WarpJS will generate an npm package named warp-server
.
Why this option?
node\_modules
is a safe directory: each framework uses tools like Babel
, ESLint
, … and here, you are sure that the generated code will not be transpiled or something else.
- Really easy to import: no relative path to know, you can directly do:
import WarpServer from "warp-server"
;
5. Setup WarpJS in project
We now need the WarpJS CLI in the main project to:
- Start the WarpJS emulator in development mode to simulate serverless function on localhost
- Build the WarpJS client helper module in order to call the serverless function
- Deploy the serverless function and optionally the static build of the main project
In the client project, you can now install the engine with all the dependencies.
You can request a WarpJS account by following this [link]https://scaledynamics.io/warpjs) 😬
$ npm install @warpjs/engine
$ npm install warp npm-run-all --save-dev
About the parent project, I want to change the way the project is served for local run, and built for deployment. To do this, I add scripts in package.json
.
So we will go from this :
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
To this:
"scripts": {
"postinstall": "cd ./server && npm install",
"serve:client": "vue-cli-service serve",
"serve:server": "warp start-emulator -w ./server",
"serve": "run-p serve:*",
"build:client": "vue-cli-service build",
"build:server": "warp build ./server",
"build": "run-s build:server build:client",
"deploy": "warp deploy --asset-dir dist/ ./server",
"lint": "vue-cli-service lint"
},
Let's break it down a bit to understand it clearly:
I'm turning the existing serve
command to serve:client
, because now I will basically build at once the server and client.
"build:client": "vue-cli-service build",
So here I have the warp emulator, helping me to emulate the serverless function:
"serve:server": "warp start-emulator -w ./server",
And here, I have the serve
command, that will serve both the client and server on two distinct HTTP ports:
"serve": "run-p serve:*",
Then I'm adding whatever is needed to build the clients and the server for deployment:
"build:client": "vue-cli-service build",
"build:server": "warp build ./server",
"build": "run-s build:server build:client",
The client doesn't change, it's still my Vue project. The server will build with Warp because it's Warp serverless function.
I'm finally adding the "deploy" command, we'll how it works a bit later
"deploy": "warp deploy --asset-dir dist/ ./server",
6. Create the front end
Let's see now how we can call this serverless function from our front-end project.
First, you have to import the WarpJS engine, once for all in the app. We recommend to initialize it in the entry point of your main project:
// src/main.js
import "@warpjs/engine";
Now we create a new component — let's call this users.vue
— and paste the template that you can find right here.
There is a CSS and a bit of JavaScript which will do the trick for us. So the only part of JavaScript we need is this:
<script>
// init WarpJS
import WarpServer from 'warp-server'
const { getUsers } = new WarpServer()
export default {
name: 'Users',
data: function() {
return {
users: null
}
},
mounted: function() {
getUsers().then((data) => {
this.users = data
})
}
}
</script>
And actually the very part of WarpJS is
const { getUsers } = new WarpServer()
and
getUsers().then((data) => {
where we are actually calling the function. It feels like we're calling a local function but it's not, we are calling the serverless function.
Last thing I need to do is to call that component in my application, so I just replace the "HelloWorld" component from the template project, by my users component, I import the component itself, and I call the JavaScript.
<script>
import Users from './components/Users.vue'
export default {
name: 'App',
components: {
Users
}
}
</script>
So last thing to log in into WarpJS to be able to build and deploy this!
$ npx warp login
7. Run locally
It's pretty easy as we prepared the command line, we just have to type npm run serve
, and then we serve both client and server. It opens a browser tab, and it's working!
We got everything, our users, filtered by the proxy, with the email addresses, the names…
8. Deploy front on CDN and back on Serverless
Let's see out deployed is now online. Actually, this is one of the simplest things to do with WarpJS. You just need to build, first, your project with the build command line we prepared
$ npm run build
and then we type in another command:
$ npm run deploy
We prepared it just before in be package.json. Let's have another look to that one:
"deploy": "warp deploy --asset-dir dist/ ./server",
This means I want WarpJS to deploy the server part from the "server" directory, and the asset directory to a CDN from the "dist" folder, which has just been built.
The server project is obviously deployed with WarpJS, on the cloud, here on Google functions, the front-end is deployed on a Google CDN (more options with AWS and Cloudflare are coming though)
Your project is now live!
So we got a URL, with our client and server: everything is hosted. We did not have to deal with the HTTPS security, the CORS, anything. Everything is just under control there.
You can find the full project code on GitHub under WarpJS/samples.
So we have examples with Angular as well with REACT, and obviously the full code for Vue.js I just did with you!
I hope you enjoyed this tutorial, and if you have any questions, please feel free to ask in the comment section!
Next in this series is a REACT and an Angular tutorial! So stay tuned ;)
Credits
Big thanks to Nicolas Pennec who developed the app we took as an example. He is a JavaScript Expert in ScaleDynamics. He co-organizes RennesJS, a French JavaScript Meetup, so if you come by Brittany you're more than welcome to join us!
Top comments (0)