lukejacksonn / servor

Dependency free file server for single page app development
MIT License
1.05k stars 70 forks source link

Add flow support #60

Open taylorgoolsby opened 4 years ago

taylorgoolsby commented 4 years ago

I know this project comes with no dependencies at the moment, but having static typing is very important to me.

Flowtype is a nice fit for this project since flow-remove-type is a very simple tool.

I have a fork which adds support for flow: https://github.com/lukejacksonn/servor/compare/master...taylorgoolsby:master

If you still want to keep no dependencies, how do you feel about implementing a hook/plugin system? I have something like this in mind:

// Add `transform` as a parameter to `servor`:
module.exports = async ({
  root = '.',
  module = false,
  fallback = module ? 'index.js' : 'index.html',
  reload = true,
  static = false,
  inject = '',
  credentials,
  port,
  transform
} = {}) => {  

// sendFile passes files through `transform`:
const sendFile = (res, status, file, ext, encoding = 'binary') => {
  if (transform) {
    file = transform(file, ext)
  }

  if (['js', 'css', 'html', 'json', 'xml', 'svg'].includes(ext)) {
    res.setHeader('content-encoding', 'gzip');
    file = zlib.gzipSync(utf8(file));
    encoding = 'utf8';
  }
  res.writeHead(status, { 'content-type': mimeTypes(ext) });
  res.write(file, encoding);
  res.end();
};

// flowtype + servor using the transform plugin:
const flowRemoveTypes = require('flow-remove-types');
const servor = require('servor');
const instance = await servor({
  root: '.',
  fallback: 'index.html',
  module: false,
  static: false,
  reload: false,
  inject: '',
  credentials: null,
  port: 8080,
  transform: (file, ext) => {
    if (ext === 'js') {
      file = flowRemoveTypes(file).toString()
    }
    return file
  }
});
lukejacksonn commented 4 years ago

Hey Taylor 👋 this is an interesting proposal and I appreciate your want for type checking!

The conundrum here is that I'd like to keep servor both generic and dependency free. Your idea of a hook/plugin system does satisfy these requirements and although it does take away (only a little) from the simplicity of the package it does make it a much more versatile solution so I think it is worth considering.

Have you looked at https://github.com/pikapkg/snowpack orhttps://github.com/vitejs/vite and seen how they do transforms of files? It looks very similar to what you are describing.. For example:

image

What you are proposing could probably be done via a config file making it more declarative than imperative. There are a few issues/suggestions here that could be resolved in a config file.

Also curious, have you ever used flows comment types? This way you get types but don't need to do any transforms (like removing types) at build time. I still really like the idea of this "on the side" static analysis.

taylorgoolsby commented 4 years ago

Yes, I have been using flow comment types. They don't have any IDE integration, so they aren't a great solution. The poor developer experience with comment types is my motivation behind adding flow support.

I have not heard of snowpack and vite. I will check them out. Although, just from a glance, they both look like they have a lot of configuration. I do like the simplicity of servor, and I can see how once you get started down this path, it can end up turning into another snowpack or vite.