h5bp / server-configs-node

Express / Connect middleware for websites. Goes well with HTML5 Boilerplate.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

concatenation & minification

ngryman opened this issue · comments

First todo in my list is this feature.

With node we could do this on-the-fly without any build step involved.

Concatenation

Convention over configuration

As the Apache version, we could say that every js file in a given directory should be automatically concatened to a given filename. We could default libs.js and app.js. This would be an automatic process.

I think we can do much better with node. The only thing I find usefull is that this is very simple for beginners. In fact this could even be a default configuration for any other approach.

Configuration over convention

We could let the user configure exactly which scripts to concatenate and in what order. As the previous approach, we could propose two defaults targets libs.js and app.js.

I think this is better that the previous approach because we don't loose any best practice value by defaulting the configuration. We let the user refine the order of the scripts and define additional targets.
But I also think that maintaining a configuration like this is painful, error prone ... and so 2010...

Dependency management

CommonJS or AMD could (and should) be our friends for client-side scripts. There is a lot of good libraries offering a client-side implementation and I think this should be a 2013 best practice for font-end developers, with Harmony incoming.

With node we could easily get this done server-side (i.e. Browserify) on-the-fly.

The user could configure target scripts like this:

app.use(h5bp({
  root: __dirname + '/public',
  scripts: ['app.js', 'libs.js']
}));

Internally h5bp will start watching for file changes (Browserify does this well) and compile if needed. The static middleware will simply serve compiled files.

Minification

For minification, we could use the same approach of concatenation (i.e. UglifyJS 2) by proxying requests to javascripts, cache local minified version and internal redirect to it.

The user could enable minification like this:

app.use(h5bp({
  root: __dirname + '/public',
  scripts: ['app.js', 'libs.js'],
  minify: true
}));

In the future we could also default minification when NODE_ENV=production is defined for example.

@paulirish, do you think we could go with something like this ?

EDIT: we could also always minify and use source maps when NODE_ENV!=production

We could do more with the dependency management, offer regular concatenation, browserify, and even ender.js

app.use(h5bp({
  scripts: {
    order: ['app.js', ...],
    concat: 'browserify | ...',
    minify: true
  }
});

Let's go for it.

Ok, I'll begin w/ the Browserify impl.

Here is a first draft of script concatenation using CommonJS : feature/concat

I am using Webmake instead of Browserify because it seems the last one removed their native express middleware and the API is not very comfy...
Webmake seems to be pretty reliable and well maintained.

I will wait until we implement the cache feature before merging it to develop. Actually it concatenates the file on-the-fly for each request ... which is not what we want.

Another thing, internally h5bp has now layers which are much like middlewares.

A good thing is that we can handle these layers internally like we want and we do not pollute the application with a bunch of internal middlewares. Also the idea that the h5bp middleware could register other middlewares is strange.

But, it makes me think that, at some point, this project could mutate into a collection of several category middlewares that could be configured together correctly with the createServer function. h5bp would become something like an express superset.

For now, I think the one-multi-purpose-middleware is a good approach because it is just simple for the user :-)

CommonJS done. I have embeded a basic file caching system for now, to avoid concatenation on each request.
So this is meant to be used w/ cache busting to reflect file changes.

This expiry project has the good idea of including a url helper for connect / express apps. I think we should also propose something like this.

Now I'll go with other types of concatenations:

  • AMD
  • basic: a list of files w/ globs supported (/**/*.js).

I'm not very sure what the syntax is. Can someone help?

@D10 What do you mean?

If you have a few files and you want to concat it to main.js, how do you specify it?

I've just finished AMD impl.

@D10
Well for now you should have a main.js file that requires its dependencies itself like this:

In the h5bp config you would just specify the path of your main script:

scripts: {
  concat: ['scripts/main.js'],
  method: 'amd'
}

There will also be a more basic concatenation method more or like grunt-contrib-concat task.

I will make a PR before integrating all these changes to master to discuss it w/ you guys :)