Skip to content

Latest commit

 

History

History
513 lines (367 loc) · 15.4 KB

README.ru.md

File metadata and controls

513 lines (367 loc) · 15.4 KB

Monic

Monic — сборщик JS-файлов (форк Jossy) в один или несколько модулей. При правильном использовании позволяет не только легко собирать модули, но и также легко пересобирать их при изменении принципов сборки.

🇬🇧 Документация на английском

NPM version NPM dependencies NPM devDependencies Build Status Coverage Status

Установка

npm install monic --global

Плагины

Использование в командной строке

monic [options] [file ...]

options

-h, --help                   Вызов справки
-V, --version                Вернуть версию Monic
-f, --file [string]          Задать путь к исходному файлу (мета-информация)
-o, --output [string]        Задать путь для сохранения сгенерированного файла
-m, --mode [string]          Задать режим для создания папок
                             при сохранении сгенерированного файла
--eol [char]                 Задать разделитель строки (EOL)
--flags [list]               Задать список флагов через запятую
--labels [list]              Задать список меток через запятую
-s, --source-maps [string]   [true|false|inline]
--source-map-file [string]   Задать путь для сохранения SourceMap
--source-root [string]       Задать корень для всех ссылок в SourceMap

Дополнение

Результат сборки выводится в output, поэтому для сохранения в файл нужно использовать возможности командной оболочки, например,

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

Или можно использовать --output

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

Примеры

Сборка файла с выводом результата в консоль

monic myFile.js

Сборка файла с сохранением результата в другой файл

monic myFile.js > myNewFile.js

Сборка файла с сохранением результата в другой файл и генерацией SourceMap

# SourceMap сохранится как "myFile-compiled.js.map"
monic myFile.js -s -o myFile-compiled.js

# SourceMap сохранится как "myFile.map"
monic myFile.js -s -o myFile-compiled.js --source-map myFile.map

# SourceMap сохранится внутри "myFile-compiled.js"
monic myFile.js -s inline -o myFile-compiled.js

Сборка текста с выводом результата в консоль

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

Использование поверх stdio

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

Использование в NodeJS

var monic = require('monic');
monic.compile(
  'myFile.js',

  {
    // Путь к рабочей директории
    // (опционально, по умолчанию module.parent)
    cwd: 'myDir/',

    // Разделитель строки (опционально, по умолчанию \n)
    eol: '\r\n',

    // Таблица задаваемых меток (опционально)
    labels: {
      escapeHTML: true
    },

    // Таблица задаваемых флагов (опционально)
    flags: {
      ie: true
    },

    // Если true, то сгенерированные файлы будут сохранены
    // (опционально, по умолчанию false)
    saveFiles: true,

    // Режим для создания папок при сохранении сгенерированного файла
    // (опционально, по умолчанию 0777)
    mode: '0666',

    // Путь к сгенерированному файлу (опционально)
    file: 'myFiled-compiled.js',

    // Если true или 'inline', то будет сгенерирован source map
    // (опционально, по умолчанию false)
    sourceMaps: true,

    // Объект source map на основе которого будет идти генерация
    // (опционально)
    inputSourceMap: null,

    // Путь к сгенерированному source map (опционально, по умолчанию ${file}.map)
    sourceMapFile: 'myFiled.map',

    // Корень для всех ссылок в SourceMap (опционально)
    sourceRoot: 'myDir/'
  },

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

    console.log(data);
  }
);

Использование Promise API (When)

var monic = require('monic');
monic.compile('myFile.js')
  .then(function ([data, {map, decl, url, isExternal}]) {
    ...
  })

  .catch(function (err) {
    ...
  });

Явное указание текста файла

var monic = require('monic');
monic.compile(
  'myFile.js',

  {
    content: '...'
  },

  function (err, result) {
    ...
  }
);

Задание функций предварительной обработки

var monic = require('monic');
monic.compile(
  'myFile.js',

  {
    replacers: [
      // Замена require конструкций на #include
      function (text, file) {
        return text.replace(/^\s*require\('(.*?)'\);/gm, '//#include $1');
      }
    ]
  },

  function (err, result) {
    ...
  }
);

Синтаксис и возможности

Подключение файлов

Включить содержимое внешнего файла в текущий можно директивой #include ....

//#include file.js

Путь к файлу указывается относительно расположения текущего файла или в абсолютной форме. В пути к файлу можно также использовать шаблоны.

//#include lib/*.js

Технически, вместо строки с директивой просто вставляется содержимое указанного файла. Однако, если указанный файл уже подключен в текущем модуле ранее, то повторно он включен не будет. Например,

f1.js

alert(1);

f2.js

//#include f1.js
alert(2);

f3.js

//#include f1.js
//#include f2.js
monic f3.js > result.js

result.js

alert(1);
alert(2);

Исключение файлов

Директива #without указывает Monic исключить из сборки все файлы, которые используются в указанном (включая указанный, разумеется).

Пример

В проекте есть несколько десятков виджетов. Код каждого виджета лежит в отдельном файле. В каждом виджете указаны его зависимости с помощью директивы #include. Какие-то виджеты используются на большинстве страниц, и при сборке логично их код вынести в отдельный файл common.js. Выбираем часто используемые виджеты, создаём файл common.js и пишем туда:

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

На одной из страниц используется виджет, достаточно объёмный, чтобы не включать его в common.js, назовём его big-widget. В файле big-widget.js указаны его зависимости, среди которых, разумеется, много тех, которые уже есть в common.js. Если мы просто соберём файл big-widget.js, то получим много продублированного кода. Поэтому рядом с common.js создаём файл feature.js с содержимым:

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

Теперь код, попавший в common.js, не попадёт в feature.js. Главное не забыть подключить на страницу не только feature.js, но и common.js.

Формат пути в директиве такой же, как и в #include.

Условная сборка

В процессе сборки можно определять специальные флаги, в зависимости от которых выводить или не выводить строки кода.

//#set flag

//#if flag
alert('flag');
/*? Можно использовать //#end if */
//#endif

//#unset flag

//#unless flag
alert('not flag');
/*? Можно использовать //#end unless */
//#endunless

Флагам можно задавать значения.

//#set ie 7

//#if ie 7
alert('OMG!');
//#endif

//#unless ie 7
alert('Cool!');
//#endunless

Директива #match предоставляет самый гибкий интерфейс для работы с условиями.

//#set foo

//#match foo
alert('foo');
/*? Можно использовать //#end match */
//#endmatch

//#unset foo

//#match foo !=
alert('foo !=');
//#endmatch

//#set ie 7

//#match ie = 7
alert('ie = 7');
//#endmatch

//#match ie != 8
alert('ie != 8');
//#endmatch

//#match ie > 6
alert('ie > 6');
//#endmatch

//#match ie >= 7
alert('ie >= 7');
//#endmatch

//#match ie < 8
alert('ie < 8');
//#endmatch

//#match ie <= 7
alert('ie <= 7');
//#endmatch

Флаги глобальные. Указать их можно не только в коде директивами #set и #unset, но при запуске сборщика. Например,

file.js

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

common.js

//#include file.js

common-ie.js

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

Точно также можно создать флаг debug и писать отладочные строки только внутри //#if debug ... //#endif, тогда отладочный код никогда не попадёт на боевые сервера.

Использование флагов в шаблонах подключения файлов

Флаги, которые были заданы при запуске сборщика или в глобальной области файла, могут быть вызваны в директивах #include и #without через специальный синтаксис.

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

Если заданного флага не существует, то вставится пустая строка.

Подключение кусков файлов

Эта функциональность очень полезна полезна при разработке библиотек и фреймворков. Например, в нашей библиотеке есть файл String.js, содержащий несколько десятков функций для работы со строками. Выделять каждую функцию в отдельный файл как-то неправильно, но и подключать потом несколько сотен строк кода ради одной функции тоже не хочется. В случае с Monic файл String.js размечается на области. Имена у областей могут быть произвольными, но лучше, чтобы они совпадали с именами функций.

var String = {};

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

};
/*? Можно использовать //#end label */
//#endlabel truncate

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

};
//#endlabel escapeHTML

Теперь, если нам нужна только функция escapeHTML, то при подключении файла String.js пишем

//#include String.js::escapeHTML

В результате в сборку попадёт только

var String = {};

String.escapeHTML = function () {

};

Если нужно подключить несколько областей, указываем несколько

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

Если нужно подключить всё, кроме размеченных областей (например, нам нужен только namespace String), то

//#include String.js::

Если же какой-то области необходима другая область из текущего файла, то используем #include без указания файла.

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

Обратите внимание, что размеченные таким образом области файла в собранном коде могут поменять порядок и между ними может появиться другой код.

Например,

//#include String.js::escapeHTML
alert(1);
//#include String.js::truncate

После сборки получим

var String = {};

String.escapeHTML = function () {

};

alert(1);

String.truncate = function () {

};

Поэтому использовать #label внутри функций и выражений нельзя, на выходе получим поломанный JavaScript.

Кроме этого, #without тоже смотрит на эти области. Поэтому, например, escapeHTML может попасть в common.js, а truncate — в feature.js.

The MIT License.