Giter VIP home page Giter VIP logo

charge's Introduction

Charge

npm tests coverage dependencies

A collection of useful middleware and tools for serving static sites.

Note: This project is in early development, and versioning is a little different. Read this for more details.

Why should you care?

If you are serving a static site through node, we all know you can use connect or express's static serving capabilities. In both cases, this is actually the serve-static module behind the scenes. And while this does a wonderful job of quickly serving up a directory, for those heavily using static sites in production, there are many other utilities still to be desired. For example, imagine if:

  • You didn't have to use .html at the end of each url
  • You could add in custom routes and redirects (very handy for SPA)
  • You could slot in a custom error page if there was a 404
  • You could easily add http basic auth for a site in staging mode
  • You could tightly control browser cacheing
  • You could make certain files are inaccessible via the server, but still exist in the project
  • You could inject a piece of markup or a script into any page before it's served

All of these things would be great, but are conveniences you usually expect from a dynamic, not a static site. These are just some of the capabilities of charge, a server for those who are serious about static sites.

Installation

npm install charge -g

Usage

Charge is represented by three different interfaces, each of which can be utilized independently or together. The charge module itself is a function that you can either access pieces of middleware from, or execute to generate a decorated connect instance. The decorated connect instance can be passed in to http.createServer as you usually would do with connect, or you can call a start function on it, which will create and start a server for you and decorate it with a few additional methods intended for working with websockets. This might sound confusing at first, but there is a diagram below as well as detailed explanations of each level that will make this more clear ๐Ÿ˜€.

charge structure

Now we'll review each level with a little more detail!

The charge module itself is a function you can call to get a decorated connect instance, as you know. But you can also access each of the middleware packages charge uses on the module itself if you'd like to use and configure them entirely on your own. For example:

var charge = require('charge');

charge.hygienist
charge.pathologist
charge.escapist
charge.publicist
charge.archivist
charge.minimist
charge.journalist
charge.columnist
charge.alchemist
charge.apologist

Each of these are middleware functions, compatible with connect, express and similar middleware stacks. More details on each piece of middleware below:

You can also call charge function, which returns a connect instance with all the middleware described previously already added. The function takes a root path and an options object which represents options for each of the middleware merged together. As is the case with any connect object, you can pass this to http.createServer to create a server:

var charge = require('charge'),
    http = require('http');

// the charge function returns a connect instance, so you can add more
// middleware or do anything else you would with a connect app here if you want
var app = charge('/path/to/public', { option: 'value' });
app.use(some_other_middleware);

http.createServer(app).listen(1111);

Options

Charge accepts options for each piece of middleware that it unifies (which is a bunch). Since this can end up being a large options object, you can alternately structure your options in a json file that you pass as a string. Below is an example of a json object representing all of the possible options:

{
  "clean_urls": true,
  "spa": true,
  "error_page": "error.html",
  "auth": "username:password",
  "exclude": ['some_file', '*/another.file'],
  "cache_control": { '**': 3600000 },
  "routes": { "**": "index.html" },
  "write": { content: "hello!" },
  "url": "/static",
  "gzip": true,
  "log": "tiny"
}

To load a file like this, you can pass the path as a second argument to charge instead of an object. Alternately, you can name the file charge.json, and if it's in the same directory as the project root, it will be loaded automatically. Below is an example of manually loading a custom path:

var app = charge('./public', '/path/to/config.json' );

All the options the charge takes are interoperable with divshot.io's configuration interface so that it can be seamlessly deployed to their wonderful static hosting environment. In addition, if you name your config file either superstatic.json or divshot.json, it will also be auto-loaded.

For the most up-to-date reference of options for each middleware be sure to check out their individual project repos.

Note: if you attempt to use journalist to write content into your response, we will automatically turn off gzip.

You can also start a new server using app.start, which will create and start a server for you and return a decorated node http server instance.

var app = charge('path/to/public');
var server = app.start(); // you can pass a port as an argument, or it defaults to 1111

This decorated server will also initialize websockets and exposes a couple additional events and methods, documented below:

server.send(message)

Sends a string or object of your choice via websockets. If you pass an object, it will be stringified, so you'll want to run it through JSON.parse on the other end. You can add a websocket listener at ws://host (or wss://host if https) to recieve these messages. If you have multiple windows or devices open to the same page, charge keeps track of all sockets and sends messages to all of them.

server.sockets

An array of all sockets that are open with connected clients. Each of the sockets conform to this api, if you are looking for very tight control.

server.on('client_open', fn)

Fired when a socket connection is established between a client and the server. This can happen multiple times.

server.on('client_close', fn)

Fired when a socket connection is disconnected by the client. This can happen multiple times.

server.on('message', fn)

Fired when a message is sent from the client to the server. The callback function takes one param which is the full message object sent by websockets. The message sent from the client can be accesed with the data property.

Using Websockets

Getting websockets set up can be a little confusing if you've never done it before. Luckily, charge abstracts away as much as is possible -- it's simple to send any message you need to any number of connected sockets using the send method seen above. All you need to do is configure your client-side javascript to recieve the messages, which is unfortunately something that charge cannot make any easier for you. However, you can see a simple example of a functional socket setup here.

Command Line Interface

Using charge from the command line will use all the default settings and fire up a server in either the current working directory or a path if provided as a positional argument. For example:

$ charge # starts a server in `pwd`
$ charge /path/to/project # starts a server at the provided path

Since charge has the ability to take a lot of options, it might be best to utilize the configuration file option when running from the command line. It is not possible to configure each option through command line flags, so if you do want to load extra config, this is the only way to do it. Note that if you have an auto-loaded config file (charge.json, superstatic.json, or divshot.json), you do not need to pass a config file option, it will be auto-loaded as expected.

Charge, of course, also plays nicely with Foreman (and it's equivalents). For example, your Procfile might look something like this:

# Procfile
web:   charge public -c config.json
redis: redis-server
CLI Options
--config, -c: path to a custom configuration file
--port, -p: port to start the server on, default 1111

Acknowledgements

Charge was enormously inspired by Divshot.io's excellent Superstatic Project. They deserve to be commended for making that project, which is core to their business, open-source and being open to outside input.

In keeping with that spirit, we've done our best to make Charge interop, wherever possible, with Divshot.io so you can easily use them as your preferred static host.

License & Contributing

charge's People

Contributors

kylemac avatar nporteschaikin avatar samccone avatar notslang avatar

Stargazers

Sasha Djolic avatar Anders Olsen Sandvik avatar kerry avatar Johan Borestad avatar Florian Rathgeber avatar  avatar Chris Ugolini avatar Ada Fairweather avatar Seth Krasnianski avatar Biko Tushinde avatar  avatar Fabien Franzen avatar Luis Faustino avatar Tyler avatar Adam Argyle avatar Robert Whitney avatar Matthew McLeod avatar M Haidar Hanif avatar Reggi avatar Jeff Escalante avatar Henry Snopek avatar Albert Abril avatar

Watchers

 avatar Kaushik avatar Daniel Lindenfelser avatar Jeff Escalante avatar James Cloos avatar  avatar Carrot avatar Bruno Germansderfer avatar Henry C. Dickson Jr. avatar Elvin G. Marmol avatar Mike Adamitey avatar  avatar Aleksandra Matiyev avatar Michael Duke avatar  avatar

Forkers

vipul261

charge's Issues

clean urls off by default

as soon as hygienist is included in the middleware stack, it begins cleaning **.html. this makes sense for hygienist itself, but from within charge, this should probably be off by default.

I'm not sure if we update hygienist to take false or something or just not include it in our charge stack by default. open for discussion.

Conform to divshot spec

We'd like for the config file/object to be able to interop cleanly with divshot, because they are wonderful, and our goals are very similar. The config will take many more options to customize in a more granular fashion, but it should at least take these values and produce the expected output:

  • root - override root passed as first arg
  • clean_urls - toggle clean urls on or off
  • routes - the options passed to pathologist
  • cache_control - the options passed to archivist
  • error_page - the arg passed to apologist
  • exclude - the args passed to escapist

ref: http://docs.divshot.io/guides/configuration

Current release is bugged

It's arbitrarily cutting off http responses. I'm sorry, not sure why, and all tests for charge and all middleware are passing. I would recommend not upgrading to 0.1.0 for now -- looking into this issue and will have it resolved and patched asap.

How can I swap out charge server for roots?

I'd like to use a custom koa (express) server instead of charge, at least for production purposes... Would be nice if I could configure/hook the app config to use a custom server somehow? a function server? Suggestions welcome...
Thanks.

Random Shutdown

So we have known about this for a bit, but occasionally when running in production, the server stops actually serving requests and just sends back blank pages. This is very strange, and we should figure out what's causing it.

Middleware Status

This ticket is just to keep track of the development of all the middleware that will be bundled with charge.

comparison with superstatic

It would be nice to get a comparison going between charge and superstatic, now that superstatic has copied over some of our decisions. If they're similar enough (which they seem to be - at least functionally), then we could look into deprecating charge and switching roots over to using superstatic.

This would, of course, be a huge win, because we could rely on a server that's much more thoroughly tested, and not even need to do all the maintenance ourselves.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.