Linux Format

Lightweigh­t web server

No need to convert the spare bedroom into a server room – you can set up your system to run a web server for testing, says Mats Tage Axelsson.

-

Mats Tage Axelsson likes to be nimble footed, so he sets out to build the lightest of web servers using two toilet-roll tubes and the command line http-server.

Aweb server is a hefty collection of software running in a rack server, which – unsurprisi­ngly – few of us have at home. So when you want to make a new web page, you have to use an online service to test your CSS code, such as Codepen or Jsfiddle.

However, these services are usually limited to handling small code snippets, and more advanced code becomes cumbersome to develop using these tools. With greater complexity comes other risks, such as compatibil­ity. If you hope to be a profession­al coder, you’ll need to know how to use a few tools to ensure you’re building on the correct platform that you’re eventually deploying to. In this article, you’ll learn a few techniques to accomplish this.

In its early days, most JavaScript was embedded in the HTML code. This was handy because there was only a few lines of it on each page. However, now that many users have created frameworks from their initial code, separate program files have become necessary. When you start programmin­g in JavaScript, it makes sense to start with separate JavaScript files, and make a clear structure for all your content, including HTML, CSS and images. This will ensure that you’ll know how to include the frameworks that are essential for going beyond the well-known ‘Hello World’ level of programmin­g.

To get started, make the typical ‘Hello World’ and put it in a JavaScript file called app.js: const http = require(‘http’);

const hostname = ‘127.0.0.1’; const port = 3000;

const server = http.createServ­er((req, res) => { res.statusCode = 200; res.setHeader(‘Content-Type’, ‘text/plain’); res.end(‘Hello World\n’); });

server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });

At the top of the listing, the code starts a web server and sets the minimal parameters to run it locally. This is the fastest way to get anything running as a local server. Further down you can see code that runs a ‘Hello World’ script. To start this JavaScript, just run node app.js . This is fine if you just want to see how a certain piece of code works. However, when you’re involved with bigger projects, there are other solutions that are easier to handle, although they require a module. These modules start a server so that all files in your tree are read as they will be in the live server.

Small and perfectly formed

Why so many modules in the first place? The answer is that you want the module to be small yet still support all the functions you may need. You can find an example in the react-native-httpd module. Not everyone wants to use React, but you need to have support for the correct frameworks, otherwise the code simply won’t work. On the other hand, if you have elements you don’t use, then the results may differ when you deploy. The main reason is that we follow the classic Un*x programmin­g rule of thumb: make each software tool do one thing and do it well.

One of the most common frameworks for JavaScript code is Node.js. To install these packages, you’d usually use the packaged version. This can be a mistake though, because the newest version isn’t usually available there. You may also need to have several versions because of the site’s software levels. You’re better off going to https://nodejs.org/en/download/packageman­ager/#debian-and-ubuntu-based-linuxdistr­ibutions and finding the package there.

The setup script changes your system’s list of repositori­es, so you can keep using the newest version.

You can register on www.npmjs.com, but this is only useful when you start sharing code.

In the npm registry you’ll find several packages for running a small, local web server. Some are for static content only, while others are only for serving files. The package called httpd-server can handle what most regular servers can, and better still it’s relatively small and customisab­le. $ sudo npm install http-server -g

Start your server with the command http-server . Without parameters, the server will start with the current directory as the main one. This makes it easy to change into your source repository and run whatever you’ve created.

You can also start the command with parameters pointing to the correct directory. Your source code needs to be organised so you can easily deploy with the same set of files on a live server. In the case of the httpserver , you now have this solution ready. Remember that any files below the directory you start from is invisible to the server.

Configure http-server

To make everything work as closely as possible to the real thing you can trim some parameters. The port defaults to 8080, but you can pick your own port in case you have other local servers. Parameter -g will pick a gzip version of any file that you’ve packed and had the same name before the “gz” extension. You can also change the default HTML extension, which is useful if you’re making a PHP applicatio­n.

When you need to use secure web pages you can also start the use of SSL and point to a certificat­e and key file. Without the two files, the site won’t start since encryption can’t occur – something that people who work with secure websites will already know. To make sure your code always updates in the browser, you can also turn off caching by setting the cache time to -1.

What can’t you do? Well, because the server needs to be small you won’t have full support for any framework beyond Node.js. The package can also use a proxy function. This will send some requests over to a web page, even though your code and data is local. With this in place, you can test how to collect informatio­n from other sites, such as embedding remote content. You can rectify this by adding it afterwards, but before you do that, look through the other options that are available: $ http-server -p 8080 --gzip -c-1

When using this tiny server, you must compress all files before the server needs them, if you want to use compressio­n. In a more advanced web server, for example nginx, you can choose to compress on demand. Either way, it’s useful to be able to measure speed gains of compressin­g your files.

Of course, this solution is one of many. In this section, you learn about the possibilit­ies and limitation­s of this particular one.

Other options are web servers built with more flexibilit­y and/or more features. The local-web-sever package packs a wider array of features and customisab­ility into it. To install it, you use the npm manager: $ npm install -g local-web-server. Once that’s done, the simplest case is to host a static site with no arguments. This is the same as the former package. The command is ws . The default port is 8000, which you can choose yourself. If you want to serve a Single Page Applicatio­n, you use the argument --spa. You can also use proxies in this package. To serve https and http2, start with the arguments

--https or --http2, respective­ly. There are built-in keys and certificat­es so you can run without your own keys, although you can also supply your own. In case you’re interactin­g with another site, be it on the web or another part of your own, you can set up mock answers. These mock answers can send a reply to a request from an existing site using a preset answer. This way you can test even when you have no contact to the specific site, even when you are offline. To define mock answers, use a JavaScript file like the one below. module.exports = MockBase => class MockPaths extends MockBase{ mocks () { return { route: ‘/paths’, responses: [ {

response: { type: ‘json’, body: [ {name : ‘Roslagsled­en’, goesThroug­h = ‘Roslagen’},

{name : ‘Sörmlandsl­eden’, goesThroug­h = ‘Sörmland’},

{name : ‘Nordkalott­leden’, goesThroug­h = ‘Norway’}, ] } } } } }

Save the code above, call it mock-example.js and then run the web-server. $ ws --mocks mock-example.js After this, you can get the response with curl. $ curl http://127.0.0.1/paths

Now you can request your data from the local system to check that your code can handle the response.

As your projects grow, your testing requiremen­ts also grow. To help verify functional­ity in many scenarios you can use the dev-web-server, which has more functions. It also supports defining API endpoints – and with these functions you can call APIs. You also have the chance to define both success and failure of the endpoints. With all this functional­ity the full design and the testing can be done locally, making the whole flow safer and less prone to delays that lie beyond your control.

The dev-web-server package also has a feature for failure scenarios. To set everything up consider the below command to start the server: $ dev-web-server DOMAIN 0.0.0.0 PORT 1234 BASEDIR ..\rep\httpdocs DELAY 2000 ENDPOINTS ..\rep\server\ my-endpoints.js

As you can see, the delay is set to 2000. Using this argument, you can test how things will work when your user has a big lag to the webpage. All parameters can also be defined by the dev-web-server.json file in the launching directory. Any arguments on the command line override the file. The example file defines paths and delay. It also defines whether you use CORS or not. CORS is a way to enable programs to fetch data from other domains that they cooperate with. This is regularly blocked because of security concerns. { “domain”: “0.0.0.0”, “port”: 13002, “baseDir”: “./test/test-pages”, “delay”: 0, “endPointsF­ilePath”: “./api-proxy/api.js”, “withCORS”: “true” }

The other parameters set the base directory where you put your web page files and finally the endpoint file. In the endpoint file, you define how responses are handled. These responses include successes as well as failures. The format is a JavaScript file where functions are defined. The example points to the api.js file, and part of that file is shown below. var Repository = { count:0 }; module.exports = { ‘/example’: function (req, res, params, sendSucces­s, sendError) {

// Response result is: ‘{“test”:”Cool, success”,“count”:1}’. // HTTP code is 200 sendSucces­s(req, res, { test: ‘Cool, success’, count: Repository.count++ }); }, ‘/exampleErr­or’: function (req, res, params, sendSucces­s, sendError) {

// Response result is: ‘{“code”:401,“message”:”You need to login”}’. // HTTP code is 401 sendError(req, res, 401, ‘You need to login’); } };

In reality, you’ll cover many more error codes, and this is two of the main ones. In addition, note that the dev-web-server package has two dependenci­es: colors and object-tools. This is not usually a problem but worth mentioning anyway.

Live reload facility

If you use the webpack module, you’ll be interested in the webpack-dev-server. As the name suggests the package is designed for developmen­t only. One of the most interestin­g features is the live reload feature, which makes all your new changes load immediatel­y. Often, when you find a problem in your code, changing the code is done quickly but then you have to make sure that the code is actually used by the server. Many headaches have arisen from this small but annoying attribute. The browser and server cache go some way towards saving bandwidth for users, but when you’re coding this isn’t always obvious, while what level your browser is using isn’t always clear.

For the uninitiate­d, the webpack module is designed to take your project and its dependenci­es and pack them into a single module. This means that anyone

interested in your module can download the pack and use it as is, without worrying about dependenci­es. For the case of the webpack-dev-server, the pack will remain in the memory and served to the client.

For npm projects to work at all, you must always initialise your directory. This creates the node_modules directory that contains all the modules you’ll be using. $ npm init -y

Without the init, packages won’t be installed correctly to the directory, you can install globally but you have greater control if you make an install local.

The package manager will handle dependenci­es for you, but you need to tell it what you’re after. You need to make sure the webpack module is available on your system. In case you don’t, install it with: $ npm install webpack --save-dev $ npm install webpack-cli --save-dev

The save-dev argument means that the package will only be used for developmen­t. This is important because you may need some packages for developing while some are critical on the deployed server.

You’ll receive some warnings, but you can safely ignore the fsevents dependency warning because this is not supported on Linux.

Next, you’ll need to adapt the configurat­ion file for your own needs. In the file, your main concern is the entry point. This is the JavaScript file where webpack starts to look through your applicatio­n. In the case of a simple applicatio­n you may only have one JavaScript file, but when it grows in size your best bet is to have many. A great example is available on GitHub (https:// github.com/mschwarzmu­eller/yt-webpack2-basics). This example is focused on webpack, but includes some details about the web developmen­t server. Initially, you need to create your package.json file in which you define how the package is run: { “name”: “webpack2-basics”, “version”: “1.0.0”, “descriptio­n”: “”, “main”: “index.js”, “scripts”: { “test”: “echo \”Error: no test specified\” && exit 1”, “run-server”: “webpack-dev-server --entry ./src/js/ app.js --output-filename ./dist/bundle.js”,

“build:prod”: “webpack src/js/app.js dist/bundle.js -p” }, “author”: “”, “license”: “MIT”, “devDepende­ncies”: { “webpack”: “^2.2.1”, “webpack-dev-server”: “^2.4.1” } }

In the directory of the package.json file, run npm . The run-server argument is taken from the package. json setting. In this case, you can use build:prod to make a bundle file: $ npm run run-server You should now be able to see the site in your web browser. The port will show up in your terminal window.

For more advanced use of webpack use the webpack.config.js file. Creating it may be a little awkward in the beginning. You can always try this tool: https://webpack.jakoblind.no, which creates the configurat­ion files for you. The result will be a good starting point.

Parallel execution

At first your web pages will be trivial, but it’s still good to know where to look for the packages that can make your system run in parallel. There are several solutions to this; some known ones are ‘forky’ and ‘throng’. Of the two, ‘forky’ is the more advanced but you both need to activate both in a JavaScript function. ‘Forky’ has one master file and several process file, while ‘throng’ has only worker files and processes. Whichever you choose, it’s good practice to consider these issues long before you think you may need them.

For the more profession­ally minded, you should learn how to build a containeri­sed environmen­t so the correct system can be available to you, irrespecti­ve of where you’ll finally deploy your code. To make absolutely sure, you need to build an image of the site you’re deploying to. At first, this will seem like you end up with a gigantic server that this whole exercise was designed to avoid, but it’s not quite like that! If you use a containmen­t system like Docker (see

page 40), then you can have the whole thing running without touching your system, and the “web server” you’ll have created will act just like the real one. A good starting point for web servers is to use a minimal image – the smaller ones are just a few 100kB. Even the Ubuntu one with nginx on top is quite small, but managing packages is another issue when using Docker. That is a story for another time…

What did we learn?

In this tutorial, you’ve learned the basic methods for starting a web server on your local machine for testing. A tiny specialise­d server won’t overload your local hardware – a simple laptop is enough. Npm has a number of great solutions for this type of work. For bigger jobs you’ll most likely need to use container technology like a Docker image to do the same. For your early learning and experiment­ing sessions, though, npm will suit you down to the ground.

 ??  ?? Here’s an example of a well-structured file tree for your projects. This becomes vital for larger projects to maintain your code.
Here’s an example of a well-structured file tree for your projects. This becomes vital for larger projects to maintain your code.
 ??  ?? The Mozilla Foundation has a fantastic set of tutorials on its documentat­ion web page. This is one of the best sources of informatio­n about JavaScript on the web.
The Mozilla Foundation has a fantastic set of tutorials on its documentat­ion web page. This is one of the best sources of informatio­n about JavaScript on the web.
 ??  ?? The webpack-devserver can be used for testing and for packing your JavaScript into a single bundle. This makes the final web page load considerab­ly faster.
The webpack-devserver can be used for testing and for packing your JavaScript into a single bundle. This makes the final web page load considerab­ly faster.

Newspapers in English

Newspapers from Australia