smartes

Ingenious server for native ES projects

Usage no npm install needed!

<script type="module">
  import smartes from 'https://cdn.skypack.dev/smartes';
</script>

README

SmartES

Ingenious server for native ES projects

Nowhere near a beta.

Traditional way of deploying JS websites (apps/pwa/spa) typically bundles all files together into a single JS file. This is inefficient as everything has to be downloaded again, even if only a single line of code was changed. It slows down the website and incurrs unnecessary data costs.

The SmartES approach is vastly different. Each file is versioned and servered independently. Each versioned file is immutable. This means caching optimizations can be done to eliminate fetching a file more than once.

SmartES uses Git directly to track file history, and also have support for hosting many tracking points of Git in parallel.

Key points

  • Built for production, but is encouraged to be used as a dev-server as well (use special branch ':')
  • Committed files have a 1 year client-side hard cache. Each deployed file is immutable and safe to cache forever.
  • Use regex to determine what branches should be deployed
  • Uncommited changes, unstaged or staged, are given an etag

Word of advice

Using SmartES, make sure no one ever force-pushes to Git

Because dependencies are calculated based on the Git history, if the history were to change that could result in inconsistent states.

Install

npm install -g mikabytes/smartes

Example usage

Create a configuration file smartes.js in the base directory of your Git repository (can be bare), then run the command: smartes

Serve everything (including git hashes, tags, branches)

export default {
  entry: './index.js',
  branches: [/.*/],
  port: 3000,
}

// The file ./index.js will be available at http://localhost:3000/[tag/hash/branch]/index.js

Change base folder

export default {
  entry: './index.js',
  base: './src',
  port: 3000,
  branches: [/.*/],
}

// The file ./src/index.js will be available at http://localhost:3000/[tag/hash/branch]/index.js

Serve the master branch, with start.js as entry point

export default {
  entry: './start.js',
  base: './',
  port: 3000,
  branches: [/master/],
}

// http://localhost:3000/master/start.js

Serve any branch starting with the word "release"

export default {
  entry: './start.js',
  port: 3000,
  branches: [/release.*/],
}

// http://localhost:3000/releaseInitial/start.js
// http://localhost:3000/release20200202/start.js
// etc.

Extracting file location information

SmartES provides an endpoint "smartes.js" which provides a manifest. This can be especially useful if you have some external projects that need to import a subpart of the JS application.

curl http://localhost:3000/someBranch/smartes.js
{
  "entry": "./index.js",
  "files": {
    "./index.js": {
      "version": 1,
      "githash": "8cc6a",
      "dependencies": {
        "./pages/redux-saga/effects.js": 1
      },
      "url": "./index-1.js"
    }
  }

Working locally

If HEAD is specified as branch, then SmartES turns off all caching headers. This is only meant to be used for developing locally, and only works if the repository is not bare.

curl http://localhost:3000/:/index.js
# fetches index.js from foo branch

Also, detection of unstaged and staged changes is enabled. Such files will be served directly from the hard-drive as-is.

Importing assets and having an index file as entry

If SmartES seens the phrase smartes(...) anywhere in a file, it will replace the ... string with the appropriate file location everywhere. This enables the use of assets, and also to have an HTML file as entry point:

<!DOCTYPE html>
<!-- smartes(./index.js) -->
<script src="./index.js"></script>

Let's say the version of index.js is 9, then SmartES will rewrite this file as:

<!DOCTYPE html>
<!-- smartes(./index-9.js) -->
<script src="./index-9.js"></script>

Roadmap

Planned upcoming features are:

  • Enable HTTP/2 support with excellent PUSH support.