File builder for JavaScript.


Monic is a JavaScript file builder (fork of Jossy) to one or several files. When it used properly, Monic allows not only easy to build modules, but also easy to rebuild, when changing principles of the build.

Russian documentation


npm install monic --global


Using CLI

monic [options] [file ...]


-h, --help
-V, --version
-f, --file [src]             path to the source file (meta information)
-o, --output [src]           path to the output file
--eol [char]                 EOL symbol
--flags [list]               list of flags separated by commas
--labels [list]              list of labels separated by commas
-s, --source-maps [val]      [true|false|inline]
--source-map-file [src]      path to the generated source map
--source-root [path]         root for all URLs inside the generated source map


The build result will be output to stdout, so to save it to a file you need use your shell, e.g.,

monic file.js --flags ie --labels escapeHTML > _file.js

Or you can use --output

monic file.js --flags ie --labels escapeHTML -o _file.js


Builds a file and outputs to stdout

monic myFile.js

Builds a file and saves the result to a new file

monic myFile.js > myNewFile.js

Builds a file and saves the result to a new file with SourceMap

# SourceMap will be saved as ""
monic myFile.js -s -o myFile-compiled.js

# SourceMap will be saved as "myFile-map.js"
monic myFile.js -s -o myFile-compiled.js --source-map myFile-map.js

# SourceMap will be saved into "myFile-compiled.js"
monic myFile.js -s inline -o myFile-compiled.js

Builds a text and outputs to stdout

monic '//#include foo/*.js' -f myFile.js

Over stdio

echo '//#include foo/*.js' | monic -f myFile.js

Using in NodeJS

var monic = require('monic');

    // The path to the working directory
    // (optional, by default module.parent)
    cwd: 'myDir/',

    // EOL symbol (optional, by default \n)
    eol: '\r\n',

    // The map of Monic labels (optional)
    labels: {
      escapeHTML: true

    // The map of Monic flags (optional)
    // The flags can have different values, for example
    flags: {
      ie: true,
      ieVersions: [7, 8, 9],
      needInclude({flags}) {
        return && flags.ieVersions.includes(7);

    // If is true, then generated files will be saved
    // (optional, by default false)
    saveFiles: true,

    // The path to the generated file (optional)
    file: 'myFiled-compiled.js',

    // If is true or 'inline', then will be generated a source map
    // (optional, by default false)
    sourceMaps: true,

    // The base source map object for the output source map
    // (optional)
    inputSourceMap: null,

    // The path to the generated source map (optional, by default ${file}.map)
    sourceMapFile: '',

    // The root for all URLs in the generated source map (optional)
    sourceRoot: 'myDir/'

  function (err, result, {map, decl, url, isExternal}) {
    if (err) {
      throw err;


Using Promise API

var monic = require('monic');
  .then(function ({result, sourceMap: {map, decl, url, isExternal}}) {

  .catch(function (err) {

Building from a string

var monic = require('monic');

    content: '...'

  function (err, result) {

Using replacers

var monic = require('monic');

    replacers: [
      // Replaces require to #include
      // ("this" refers to the instance of the compiler)
      function (text, file) {
        return text.replace(/^\s*require\('(.*?)'\);/gm, '//#include $1');

  function (err, result) {

The syntax and capabilities

Including files

To include an external file into the current need to use the #include directive.

//#include file.js

The file path is relative to the location of the current file, but also you can use an absolute path. In the file path can also be used templates.

//#include lib/*.js

Technically, the line with the directive is simply replaced to a text of the attached file. However, if the specified file is already included to the current module before, then it won't be included again. For example:




//#include f1.js


//#include f1.js
//#include f2.js

Build f3.js

monic f3.js > result.js



Excluding files

The #without indicates Monic exclude from the build all the files that are used in the specified (including specified, of course).


Our project has several dozen widgets. The code for each widget is inside a separate file. Each widget indicated its dependence with the #include. Some widgets are used on most pages, and is logical to place their code in a separate file, for example common.js. Select frequently-used widgets, create the file common.js and write back:

//#include widget1.js
//#include widget2.js
//#include widget3.js

On one of the pages the widget is used, large enough not to include it in the common.js, let's call it big widget. In the file big-widget.js its dependencies, and many of those who already in the common.js. If we will simply build the big-widget.js we will get a lot of duplicated code. Therefore, next to the common.js create a file feature.js with the code:

//#without common.js
//#include big-widget.js

Now the code in the common.js, misses the feature.js. Most importantly don't forget to include to a page not only the feature.js, but the common.js too.

The path format in the directive is the same as in the #include.

Conditional build

In the build process can be defined special flags that define whether or not to include selected code sections.

//#set flag

//#if flag
/*? Or //#end if */

//#unset flag

//#unless flag
alert('not flag');
/*? Or //#end unless */

Flags can take values.

//#set ie 7

//#if ie = 7

//#unless ie = 7

More examples:

//#set foo

//#if foo

//#unset foo

//#unless foo
alert('foo !=');

//#set ie 7

//#if ie = 7
alert('ie = 7');

//#if ie != 8
alert('ie != 8');

//#if ie > 6
alert('ie > 6');

//#if ie >= 7
alert('ie >= 7');

//#if ie < 8
alert('ie < 8');

//#if ie <= 7
alert('ie <= 7');

// If flag is an array or a table,
// then can be used "has" statement
//#set ie [7, 8]
//#if ie has 7
alert('ie = 7');

// It's possible to add data to an existing array
//#set ie. 9
//#if ie has 9
alert('ie = 7');

// It's possible to add or create nested fields on tables
//#set runtime.offlineMode
//#if runtime has offlineMode
alert('Offline mode enabled!');

// If flag is a regular expression
// then can be used "like" statement
//#set ie /[7-9]/
//#if ie like 7
alert('ie = 7');

// If flag is a function
// then can be used "call" statement
//#set ieVersions [7, 8, 9]
//#set ie function (o) { return o.flags.ieVersions.includes(o.value); }
//#if ie call 7
alert('ie = 7');

All the flags are declared globally. To set it in your code, you should use the directives #set and #unset, and also you can specify it when you run Monic. For example:


//#if ie
alert('IE only');


//#include file.js


//#set ie
//#include file.js

Similarly, you can create a debug flag and write debug code within //#if debug ... //#endif, that code never gets to production server.

Using the flags inside path patterns

The flags that were specified as a build parameter or in the global scope of a file can be used inside #include and #without with using a special syntax.

//#set lang en
//#include lang/${lang}.json

If the flag is a function, then it will be executed and the result will be inserted to the template. If the flag doesn't exist, then will be inserted an empty string.

Including chunks of files

This functionality is very useful for development of libraries and frameworks. For example, in your library there is a file String.js containing several dozens of functions for working with strings. Isolate each function in a separate file somehow wrong, but attach a few hundred lines of code for only one function is also not desirable. To solve this problem Monic can can mark the file String.js on specific areas. Names in areas can be arbitrary, but it is better to coincide with the names of functions.

var String = {};

//#label truncate
String.truncate = function () {

/*? Or //#end label */
//#endlabel truncate

//#label escapeHTML
String.escapeHTML = function () {

//#endlabel escapeHTML

Now, if we only need the escapeHTML, when you include a file String.js write

//#include String.js::escapeHTML

As a result, the build will get only

var String = {};

String.escapeHTML = function () {


If you want to include several areas, you need to write something like this

//#include String.js::trim::truncate

If you want to include everything except the marked areas (for example, we need only String namespace), then

//#include String.js::

If some area needed another area of the current file, use the #include without specifying a file.

//#label truncate
//#include ::trim
String.truncate = function () {};
//#endlabel truncate

Please note that the marked-thus the area of the file in built code can change the order between it and may receive another code.

For example:

//#include String.js::escapeHTML
//#include String.js::truncate

After build will receive

var String = {};

String.escapeHTML = function () {



String.truncate = function () {


Therefore, don't use #label inside functions and expressions because it can break your JavaScript.

In addition, #without also watching for these areas. So, for example, escapeHTML can get into common.js and truncate into feature.js.


The MIT License.





  • set-harmonic-interval

    set-harmonic-interval Works similar to setInterval, but calls all callbacks scheduled using setHarmo...

    5 个月前
  • gulp-monic

    Using Monic with Gulp. gulp-monic Using Monic with Gulp. Install npm install monic gulp-monic -...

    21 天前
  • bitcore-mnemonic

    BIP39 Mnemonics implemented for Bitcore. Bitcore Mnemonics BIP39 Mnemonics for bitcore A module f...

    1 年前


扫码加入 JavaScript 社区