node package manager
Easy sharing. Manage teams and permissions with one click. Create a free org »

bundler

Bundler

На сайте вам нужны некоторые дополнительные файлы (например, JS или CSS) на каждой странице. Для разных страниц нужны разные файлы, но некоторые файлы нужны сразу на нескольких страницах. Вы можете объединить несколько файлов в один 'бандл'.

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

Но, если пользователь, например, зайдет только на одну страницу сайта, то такой метод приведет к сильному увеличению времени загрузки для этой конкретной страницы, что плохо.

Если не объединять ничего, то пользователю точно не придется загружать никаких лишних данных, но на каждой странице будет загружаться куча файлов, а это нехорошо.

Таким образом, нужен некоторый компромиссный вариант - что-то объединять, что-то нет. Этот модуль ищет такой вариант с помощью генетического программирования.

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

Кроме того, между файлами могут быть зависимости: файл2 может зависет от файла1, что означает, что на странице файл1 должен быть раньше чем файл2. Если найденный бандлинг не удовлетворяет зависимостям, то модуль об этом сообщает, но не пытается исправить ситуацию. Для более удобной работы с зависимостями есть "метафайлы", которые не соответствуют реальным файлам, но могут иметь зависимости. Зависимости могут быть разными для разных страниц.

Формат ввода-вывода

  • Данные по странице с названием 'PAGE' должны лежать в файле 'PAGE.deps-sets.js' в следующем формате:
exports.depsSets = {
    "file1": {
        'deps': ['file2', 'metafile1'],
        'size': 1000,
    },
    "file2": {
        'deps': [],
        'size': 666,
    },
    'file3': {
        'deps': [],
        'size': 13
    },
    'metafile1': {
        'deps': ['metafile2'],
    },
    'metafile2': {
        'deps': ['file3'],
    },
}

Что означает: страница состоит из 3х файлов 'file1', 'file2' и 'file3'. Причем 'file1' зависит (после раскрытия зависимостей) от 'file2' и 'file3'. Метафайлы характеризуются тем, что для них не задано поле 'size'.

Размер указывается в байтах.

  • Логи по сессиям должны быть в следующем формате:
exports.sessions = [
    ['user1', 'page1', 0],
    ['user2', 'page2', 3],
    ['user1', 'page3', 5],
];

Где каждый элемент имеет формат [ID пользователя, посещенная страница, время визита (timestamp).

  • Запуск в следующем формате:

bundler [--file-cost=FILE_COST] [--kb-cost=KB_COST] [--max-pause=MAX_PAUSE] [--debug] -s|--sessions=SESSIONS [-o|--output=OUTPUT] page1.deps-sets.js page2.deps-sets.js

  • FILE_COST - стоимость загрузки одного файла в тугриках; по умолчанию 10.
  • KB_COST - стоимость загрузки одного килобайта в тугриках; по умолчанию 2.
  • MAX_PAUSE - время жизни сессии в секундах; по умолчанию 3600 (один час). Считается, что если юзер никуда не заходил в течении этого времени, то кеш сбрасывается.
  • --debug - выводит отладочную информацию: стоимости "наивных" бандлингов, стоимости лучших вариантов по поколениям, и т.д.
  • OUTPUT - файл для вывода результата; если не задан, или указан '-', то используется stdout. Учитывается только если не задан параметр 'debug'.
  • SESSIONS - модуль с сессиями в оговоренном формате.
  • page.deps-sets.js - файлы с данными по страницам. HINT: если они лежат в одной директории и Вы используете, например, bash, то можно указывать pages/*.
  • Формат вывода (при выключенном режиме отладки):
exports.bundling = {
    "bundles": [
        ['file1', 'file2'],
        ['file1', 'file3'],
        ['file4'],
    ],
    "pages": {
        "page1" : [0, 2],
        "page2": [2],
        "page3": [1, 0, 2],
    }
};

Бандлы выводятся в таком порядке, чтобы не были нарушены зависимости. Если найденный бандлинг невозможно упорядочить с удовлетворением зависимостей - скрипт бросает исключение 'Bundles are not consistent'.

API

Модуль bundler.js предоставляет функцию get_bundling(config, args, main_generator, return_result). config - это объект следующего вида:

config = {
    sessions: [...],
    file_cost: 10,
    kb_cost: 2,
    max_pause: 3600,
    output: ...
};

Опции соответствуют опциям при запуске из командной строки, только sessions должно быть массивом, а не файлом, и output должен быть объектом файла. args - список страниц в виде

[
    ['page1', depsSets1],
    ['page2', depsSets2],
]

Где depsSets - объекты в описанном выше формате. main_generator - может быть mega для запуска генетического алгоритма, или all, none, every для получения "наивного" результата. all - слить все файлы в один бандл, none - каждый файл соответствует бандлу, every - для каждый страницы свой один бандл, содержащий в точности файлы с этой страницы. Если return_result истинно, то вместо вывода результата работы он возвращается в виде словаря с полями cost и bundling.