Smooth developer experience for Express
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.vscode
babel
bin
src
.gitignore
.npmignore
README.md
expressx-logo.svg
package-lock.json
package.json
prepare-test.js

README.md

ExpressX

Smooth developer experience for Express.js

What is this

ExpressX is a build system inspired by Next.js designed to make developing Express applications a breeze. It is a litte opinionated, but everything is quite sensible. It also supports custom configurations for pretty much everything.

New in v4.x

  • Removed dependency on Watchman in favor of Chokidar
  • Improved performance
  • Added disableStyles option in config
  • Added an option to init project with flow-bin in dependencies
  • Improved exported build setup
  • Support for promise return in app initializer function
  • includeInBuild config option for copying custom assets to build directory
  • New prepareServer export in app.js for manipulating HTTP server instance
  • De-Yarn
  • Removed HTTP/2 support for now

I already have Gulp. What's in it for me?

Unlike general purpose task runners, ExpressX is designed specifically for Express applications. It can do a whole bunch of things that task runners can't.

Here's a full list of sweet stuff ExpressX handles automatically for you:

Backend

  • ES6/7/Next (Babel's stage-3)
  • Flow types handling
  • HTTP/2 support
  • Proper live reload (including server side changes)
  • Body parsing
  • Handlebars setup
  • I18n setup
  • Helmet for security
  • Gzip compression

Styles

  • Sass/SCSS compilation
  • Autoprefixing
  • Minification in production

Frontend

  • Webpack bundling
  • webpack-dev-middleware support
  • Hot Module Replacement support

Misc

  • Sweet error reporting from Babel/Webpack/Sass
  • Clean console output
  • SPEED

I'm sold! How do I get started?

To get started, first install expressx

npm install -g expressx

Then create a new direcrory and run expressx init inside:

mkdir new-project
cd new-project
expressx init

And you're good to go!

To start your app, just use npm start.

How to move around here

The main thing you should take a look at is the app.js file.

In ExpressX, this file should export a function like so:

export default (app) => {
    // "app" is an express application instance
    // Do your setup here
    app.use('/', routes);

    return app; // Important, return "app" in the end
}

This file is the main entrypoint of your app. All the configuration should be done here.

prepareServer

Besides the default export that configures Express instance, you can also export a prepareServer function, that you can use to configure HTTP server instance:

export default (app) => {
    // Express config goes here
    return app;
}

export function prepareServer(server) {
    initSocketIO(server);
    // No need for return here
}

Config

You can also configure a whole bunch of things. To do it, you can create a file called expressx.config.js in the root of your project.

Here's what this file with all default settings looks like:

module.exports = {
    babel: {
        ignore: [],
        sourceMaps: 'inline',
        presets: 'expressx/babel/server',
    },
    https: false, // { key, cert }
    port: 3000,
    poweredByHeader: 'ExpressX', // string | false
    errorHandling: true,
    i18n: {
        locales: ['en'],
        cookie: 'locale',
        path: 'locales',
        objectNotation: true,
    },
    hbs: {
        views: 'views',
        partials: 'views/partials',
        layouts: 'views/layouts',
        defaultLayout: 'views/layouts/default',
    },
    staticFolder: 'public',
    autoprefixer: {
        grid: true,
    },
    helmet: null, // helmet.js options
    styles: ['public/styles/styles.scss'],
    stylesOut: 'public/css',
    webpackMode: 'direct', // "direct" | "middleware"
    webpack: config => config,
    webpackDevMiddleware: {
        publicPath: '/js/',
    },
    disableWebpack: false,
    watchIgnore: [],
    includeInBuild: [],
    debugPort: 5858,
}

Let's break each field down.

  • babel - Babel's standard options object
  • https - HTTP/2 configuration object: { key: 'path/to/keyfile', cert: 'path/to/cert' }
  • port - Port to run the app on
  • poweredByHeader - Set custom X-Powered-By header. Set to false to disable it
  • errorHandling - Use default error handling. Set to false if you use your own handlers
  • i18n - i18n standard options object
  • hbs - Handlebars views/layouts/partials paths and default layout
  • staticFolder - Path to static files
  • autoprefixer - Autoprefixer options object
  • helmet - Helmet options object
  • styles - Array of paths to styles entrypoints
  • stylesOut - Override styles output directory
  • webpackMode - Webpack mode. Can be set to "direct" or "middleware". Direct mode is usually faster. Middleware mode will use webpack-dev-middleware and webpack-hot-middleware. (Note: Though hot reloading is supported, it's not configured by default. You still have to set it up to suit your app)
  • webpack - A function that accepts a Webpack config and returns a Webpack config. Use this to extend default configuration with your own. Scroll down to see default Webpack config
  • webpackDevMiddleware - webpack-dev-middleware options object
  • disableWebpack - Set this to false to disable Webpack altogether
  • disableStyles - Set this to false to disable SCSS compilation and PostCSS
  • watchIgnore - Specify globs for file watcher to ignore
  • includeInBuild - Specify custom paths to be included in build directory
  • debugPort - Custom port to run the debugger on when using --debug

Default Webpack config

const webpackConfig = {
    context: cwd, // context is the project root
    devtool: process.env.NODE_ENV === 'production' ? 'inline-sourcemap' : false,
    mode: process.env.NODE_ENV === 'production' ? 'development' : 'production',
    entry: {
        app: './public/js/app.js',
    },
    resolve: {
        extensions: ['.js', '.jsx'],
    },
    module: {
        rules: [
           {
                test: /\.jsx?$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader',
                query: {
                    presets: 'expressx/babel/client',
                },
           },
        ],
    },
    output: {
        path: join(cwd, '.expressx/build/public/js'),
        filename: '[name].min.js',
    },
    plugins: process.env.NODE_ENV === 'production'
        ? [new Webpack.HotModuleReplacementPlugin()]
        : [new Webpack.optimize.AggressiveMergingPlugin()],
}

Since ExpressX is using Webpack 4, minification is done automatically in production mode.

Exporting builds

In some cases you may need to separate the steps of generating the build and running it. ExpressX provides a simple way to do export your build and run it later. To build, use:

expressx build

And to run after the build is done:

expressx start

Debugging

You can attach to Node debugger by passing a --debug option to ExpressX like so:

expressx --debug

# OR

expressx start --debug