-
Notifications
You must be signed in to change notification settings - Fork 1
02. Setting up a basic KoaJS server
Now that you have created a package.json file, you can use npm to install more Node modules. These modules are software which helps you do common tasks such as setting up a server, connecting to web services, and changing formats. People write Node modules for themselves, but publishing them on NPMJS.com allows them to be shared with and improved by others.
Koa is a popular framework for writing a web server using NodeJS. There are many ways to write web servers with other frameworks or with Node's built-in modules. When I first started in Node and when I started 1batch, Express was a major part of understanding how Node works. Over time, the Express development team created Koa as a new framework, embracing the very latest features of the JavaScript language (known formally as ECMAScript 7 / ES7).
You can install Koa v2.0 and record it in package.json by running npm install koa@next --save
Here's their hello world example, with comments added:
// app.js
// load KoaJS
const Koa = require('koa');
// create the web app
const app = new Koa();
// when someone contacts your server, call this unnamed function:
app.use(ctx => {
ctx.body = 'Hello World';
});
// make the homepage available on your computer at http://localhost:3000
app.listen(3000);You'll notice two new language features: the arrow function => { } to make an unnamed function, and const instead of var. Using const speeds up code in the latest versions of JavaScript and NodeJS. You can read some different ideas about using it on StackOverflow.
Koa splits its components up into several modules. Even simple apps will want to include these modules.
- Use '@next' to specify the 2.0 beta version of Koa
- Note that I'm using koa-router and not the standard module koa-route
- As of this writing, koa-static doesn't have an updated module for Koav2, so install koa-convert with it
npm install koa-bodyparser@next koa-compress@next koa-router@next koa-static koa-convert --save
Your app.js file doesn't know about these modules automatically, so you need to require() them and pass them into the app variable.
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const compression = require('koa-compress');
const router = require('koa-router')();
const kstatic = require('koa-static');
const convert = require('koa-convert');
const app = new Koa();
// make a directory called "static" and link directly to the files inside there
// use koa-convert to make it compatible with Koa v2.0
app.use(convert(kstatic(__dirname + '/static')));
// read POST requests and cookies
app.use(bodyParser());
// use common features to make uploads and downloads smaller
app.use(compression());
// support different functions for different pages on the server
app.use(router.routes())
.use(router.allowedMethods());
// start the server
app.listen(3000);It was a little cool to use ctx.body = 'hello world'; to respond to the user, but on a real website, you will want to send back an HTML webpage, with CSS styles and JavaScript code. A "hello world" page might look like this:
<!DOCTYPE html>
<html>
<head>
<!-- this is a comment in HTML -->
<meta charset="utf-8"/>
<title>Hello World</title>
</head>
<body>
<!-- this is the content visible on the page -->
<h1>Hello World</h1>
<p>You've done it!</p>
</body>
</html>A lot of the lines of an HTML file are the same from one page to another. Also, a lot of lines are taken up by matching every tag (<html>) with a closing tag (</html>).
When we create Jade templates, we condense the HTML syntax into a more condensed layout:
doctype
html
head
// this is a comment in Jade
meta(charset="utf-8")
title Hello World
body
// this is the content visible on the page
h1 Hello World
p You've done it!Using Jade format becomes more helpful when we introduce templates, loops, and embedded content. If you've used Ruby's HAML before, it's similar. If you're more familiar with ERB, there's an analogue in the NodeJS world called EJS, but I'm going to continue using Jade templates.
The main issue with Jade is that whitespace is very important. Make sure to keep everything on the right level in your app.
To enable Jade templates in your Koa server, install the module and create a separate folder for templates:
npm install koa-jade-render --save
mkdir views
Then in app.js, add:
const jade = require('koa-jade-render');
...
app.use(jade('./views'));Create a template file (named index.jade) and save it into the views directory. You can use the "hello world" example from above.
Then tell your router how to respond with a template:
router.get('/', ctx => {
ctx.render('index');
});That's actually all of the server-side code needed for the 1batch.co homepage! If you look at views/index.jade you can see that the page is static... it doesn't change based on server-side content.
There are some lines that are useful to look at if you haven't used Jade or HTML much before:
head
// use the viewport tag to make your app have a full-screen mobile web experience
meta(name="viewport", content="width=device-width, initial-scale=1, user-scalable=no")
// use the <link> tag to include a CSS stylesheet (Bootstrap is a popular CSS framework)
link(rel="stylesheet", type="text/css", href="/lib/bootstrap.min.css")
body
// when a line begins with . # or (, Jade assumes it is a <div>.
// . represents a class, # an ID, and () contain attributes
// these should be somewhat familiar if you know HAML or jQuery
.navbar.navbar-fixed-top
// nest divs together
.containerKoa v2 supports new language features including async and await, which NodeJS itself can't handle natively. You'll need BabelJS to compile and run your next-generation JavaScript.
First, create a file called .babelrc
{
"env": {
"development": {
"presets": ["es2015-node5"],
"plugins": ["transform-async-to-generator"]
}
}
}
Next, install a lot of BabelJS packages
npm install -g babel-cli
npm install --save-dev babel-core babel-cli babel-preset-es2015-node5 babel-plugin-transform-async-to-generator
Once you have babel installed, you should start your server (and change npm start or any other script) by calling:
babel-node app.js