flegall / monopack

A JavaScript bundler for node.js monorepo-codebased applications.
MIT License
54 stars 2 forks source link
bundler deterministic lerna monorepo nodejs tool webpack yarn

Monopack

A JavaScript bundler for node.js monorepo-codebased applications.

Build Status Build Status Build status

Quality lerna code style: prettier

This tool comes to fill a gap for node.js developpers who :

Monopack aims to build a static deterministic deliverable bundle from your application's entrypoint main.js.

It will build:

Usage

Requirements

Installation

It can be installed globally and locally

Global installation

Using yarn

yarn global add monopack

Or npm

npm install -g monopack

You can then use it with

$ monopack

Local installation

Using yarn

yarn add -D monopack

Or npm

npm install --save-dev monopack

You can then use it on your project

With yarn

$ yarn run monopack

With npm

./node_modules/.bin/monopack

CLI

monopack <command>

Commands:
  monopack build main  Builds an application
  monopack run main    Runs an application
  monopack debug main  Runs an application in debug mode (Node >= v8 only)

Options:
  --help                          Show help                            [boolean]
  --version                       Show version number                  [boolean]
  --watch, -w                     Enable watch mode   [boolean] [default: false]
  --out-dir, -d                   Output directory (default into a temp dir)
                                                                        [string]
  --no-packages-installation, -n  Do not install packages after build  [boolean]
  --install-packages, -i          Install packages after build         [boolean]
  --with-extra-module, -m         Adds an extra module to the dependencies.
                                  It can be useful for dynamically required
                                  dependencies that monopack cannot detect
                                  (e.g.: an sql driver).

                                  It expects the package name without the
                                  version. (e.g: 'mysql' not 'mysql@2.16.0).
                                  It can be use multiple times "monopack build
                                  main.js -m mysql -m postgresql" in order to
                                  provide multiple dependencies.

                                  Make sure to install it in the same package as
                                  the main file, otherwise another version might
                                  be picked up.                         [string]
  --debug-host-port               [host:]port setting to pass to node --inspect
                                  option.
                                  It must be used with the debug command.
                                                                        [string]
  --debug-break                   Break at start of main script.
                                  This option is required when you want to debug
                                  something that gets immediately executed when
                                  starting.
                                  It triggers the --inspect-brk node option.
                                  It must be used with the debug command.
                                                                      [boolean]

Default configuration

By default monopack will use babel 7 to compile your code into js code that node.js 6.14.4 understands. It supports flow and stage-2 features.

const baseBabelConfig = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: '6.14.4',
        },
      },
    ],
    '@babel/preset-flow',
  ],
  plugins: [
    ['@babel/plugin-proposal-decorators', { legacy: true }],
    '@babel/plugin-proposal-function-sent',
    '@babel/plugin-proposal-export-namespace-from',
    '@babel/plugin-proposal-numeric-separator',
    '@babel/plugin-proposal-throw-expressions',
    '@babel/plugin-syntax-dynamic-import',
    '@babel/plugin-syntax-import-meta',
    ['@babel/plugin-proposal-class-properties', { loose: false }],
    '@babel/plugin-proposal-json-strings',
  ],
};

Monopack will use webpack 4 to produce the bundle. The bundle is produced in 'development' mode in order not to obfuscate the code. Source maps are included.

Configuration file

You can include an optional configuration file : monopack.config.js

This configuration file can be used to :

You can use multiple configuration files, have a top-level one that the top of the monorepo and have a more specific one per package. More specific entries will override the ones from the root. If you would like to combine then, you have to require the parent configuration file and implement the merge operation on your own.

The config file can export the following entries :

For example :

module.exports.monorepoRootPath = '../..';
module.exports.outputDirectory = './build';
module.exports.babelConfigModifier = defaultBabelConfiguration => {
  return babelConfiguration(defaultBabelConfiguration);
};
module.exports.webpackConfigModifier = defaultWebpackConfig => {
  return webPackConfiguration(defaultWebpackConfig);
};
module.exports.installPackagesAfterBuild = true;
module.exports.extraModules = ['mysql', 'postgresql'];
module.exports.modifyPackageJson = pkg => ({ ...pkg, private: false });
module.exports.afterBuild = async buildDirectory => {
  return triggerActionAfterBuild(buildDirectory);
};

I encourage you not to modify the webpack configuration, as I intend to keep in track with latest webpack versions, having a custom webpack configuration will be difficult to update on your side. If you have specific needs that require a customization please open an issue

Dependencies handling

Monopack will collect:

All the dependencies are collected, a package.json with the collected dependencies will be compiled.

Your project's yarn.lock will be copied if it exists. If you are using multiple yarn.lock files, only the top-most one will be copied.

The dependencies collection is deterministic only if you have a single yarn.lock file. In order to achieve that you can :

Why such a tool ?

As far as I know such a tool does not exist so far.

Monorepos and node.js

Many developpers (me included) tend to consider that the only viable way of performing continous integration is to use a monorepo.

I personally find it very practical :

Unfortunately, this is not currently a very popular trend amongst many Node.JS developpers and micro-services developpers.

The classical tooling in Node.JS is designed for delivering open-source libraries and not organizing for mono-repos :

When deploying a node.js application (either within a container, or within a PAAS or on physical/virtual machine), you would like to rely on NPM/Yarn to install the application dependencies and rely on your "start" script to execute your application.

But how to bundle your application from your mono-repo sources to a static deliverable package ?

That's the purpose of monopack !

Some alternatives

You can usedversions and make LernaJS manage versions :

You could bring your whole monorepo in your application release :

Contributing

See CONTRIBUTING

Roadmap

See issues labelled as enhancement