0.2.7 • Published 3 years ago

@nico-martin/spa-server v0.2.7

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

SPA Server

"SPA Server" is a NodeJS library that starts a production ready NodeJS Webserver, that mostly serves static files and also allows you to manipulate any non-static response.

This is super useful if you you want to control the response headers or meta tags of the returned html file.

Install

yarn add @nico-martin/spa-server
npm install @nico-martin/spa-server

Ok, but why?!?

I love JavaScript applications. But in general, they have one problem. If all the logic happens on the client-side, there are several negative side effects.

I know some frameworks will render everything on the server. But I never really warmed to it. Does it really make sense to have the logic for building the page on the server and then still send the same logic to the client? I doubt that.

Furthermore, frameworks like Next.JS or Nuxt.JS require a rather rigid structure of pages and components.

When I look at my projects, the requirements for server-side rendering are relatively simple. In most cases I only needed it for some meta tags (for example for social media sharing) and a clean status code designation. That's why this library follows a much simpler approach. This being said it works with any kind of framework. It just takes the public dir, serves the files and adds meta tags for routes that are defined under "routes".

API

In essence, the library provides the ability to define your own routes and create a function (synchronous or asynchronous) that returns a status code and an object of HTML metas

{
  path: '/',
  response: request => {
    return {
      metas: {
        'name-of-the-meta': 'content of the meta',
        url: '/',
      },
      statusCode: 200
    }
  },
}

Full example

import spaServer from './lib/index';
import fetch from 'node-fetch';

spaServer({
  routes: [
    {
      path: '/user/:id/',
      response: request => ({    
        metas: {
          'user-id': 'id' in request.params ? request.params.id : '',
          hello: 'world',
          custom: {
            tag: 'link',
            attributes: {
              rel: 'canonical',
              href: 'some-url'
            }       
          }         
        },
        statusCode: 200
      }),
    },
    {
      path: '/post/:id/',
      response: async request => {
        const id = 'id' in request.params ? request.params.id : 0;
        let metas = {};
        let statusCode = 200;
        try {
          const resp = await (
            await fetch(`https://sayhello.ch/wp-json/wp/v2/posts/${id}/`)
          ).json();
          metas = {
            title: resp.title.rendered,
          };
        } catch (error) {
          console.log('Error for /post/:id/');
          statusCode = 404;
        }
        return {
          metas,
          statusCode
        };
      },
    },
  ],
  redirects: [
    {
      path: '/nutzer/:id/',
      to: '/user/:id/',
    },
  ],
  port: 3000, // default 8080
  indexFile: 'index.gtml',
  serveDir: 'dist/',
  errorPagesDir: 'path/to/custom/error/templates/',
  onError: e => console.log(e),
  logLevel: 'ERROR', // 'DEBUG' | 'WARNING' | 'ERROR' | 'SYSTEM'
  serverOptions: {}, // additional options for the node-http server
});

server.config.js

"SPA Server" comes with a handy single executable. npm spa-server (or yarn spa-server) will start the server with default configurations. Additionally it looks for a server.config.js file that expects one default export with all the arguments from above.

// server.config.js
import fetch from 'node-fetch';

export default {
  routes: [
    {
      path: '/myapi/',
      response: async request => {
        const resp = await (
          await fetch(`https://myapi.com/`)
        ).json();
        return {
          metas: {
            title: resp.title,
          },
        }
      },
    },
  ],
  port: 8888,
};

Config

routes

An Array of routes. Each route consists of a path and a response.

The path is defined as a string that will be parsed to a Regex where the matches will be passed to the response.

The response is a function that returns the metas, headers and the statusCode as an object.

export default {
  routes: [
    {
      path: '/:slug/',
      response: request => {
        return {
          metas: {
            title: 'Slug ' + request.params.slug,
          },
          headers: {
            'my-header': 'Hello World'
          },
          statusCode: 200
        }
      },
    }
  ]
};

metascan also be an async function where await can be used.

redirects

With redirects sources and targets where the server immediately returns a 302 status with the target as Location header.

Both, source (path) and target (to) can contain variables:

export default {
  redirects: [
    {
      path: '/my/source/',
      to: '/my/target/',
    },
    {
      path: '/nutzer/:id/', // /nutzer/5/
      to: '/user/:id/', // /user/5/
    },
  ],
};

port

Default port is 8080 but can easily be changed to a different port.

indexFile

In general, most Single Page Applications have an index.html file as an entry point. If for whatever reason your setup has a a different file, it cn be adjusted as well.

serverDir

By default, "SPA Server" expects the whole application inside the dist/ folder. But can be any othe folder.

errorPagesDir

When the server experiences difficulties, it will throw an error page. But you can esily set a custom page yourself. Let's assume you have a page for a 500 error inside en error/ folder:

File: error/500.html:

export default {
  errorPagesDir: 'error/',
};

onError

A callback that will be called whenever anything trows and e 500 will be returned.

logLevel

"SPA Server" is riddled with different logs on specific levels: 'DEBUG' | 'WARNING' | 'ERROR' | 'SYSTEM'.
default: ERROR

serverOptions

If you want to serve your content over HTTPS (SSL) you can pass the path to the key and the cert within the serverOptions:

export default {
  serverOptions: {
    key: 'path/to/ssl/cert.key',
    cert: 'path/to/ssl/cert.crt',
  },
};
0.2.7

3 years ago

0.2.6

3 years ago

0.2.5

3 years ago

0.2.4

3 years ago

0.2.3

3 years ago

0.2.0

3 years ago

0.1.5

3 years ago

0.1.4

3 years ago

0.1.3

3 years ago

0.1.2

4 years ago

0.1.17

4 years ago

0.1.16

4 years ago