Вселенная npm

в 8:07, , рубрики: javascript, node.js, npm, визуализация данных, граф

Привет, Друзья!

Хотел поделиться с вами своим последним мини-проектом: трехмерной визуализацией всего npm. Вселенная выглядит примерно так:

весь npm

Можно летать клавишами WASD, или если вы смотрите ее из телефона — просто вращая телефон вокруг (телефон должен поддерживать WebGL).

Много пакетов в центре, зависят от монстров типа lodash, request. Много изолированных пакетов, которые образуют кольцо астероидов:

астероиды

Все исходники тут:  github.com/anvaka/allnpmviz3d/
Интерактивная версия доступна здесь: anvaka.github.io/allnpmviz3d/

Видео демонстрация:

Надеюсь, вам понравится! Под катом немножко технических деталей о том, как это сделано

Как это сделано?

Проект построен на основе angular.js, twitter bootstrap и three.js. Все исходники проекта написаны в CommonJS стиле, что позволяет легко структурировать программу и использовать готовые модули из npm'a. Я использую gulp для создания финального файла. В gulpfile запускается browserify для обработки commonjs пакетов, и less для построения стилей бутстрапа.

Весь граф изначально укладывается на сервере, при помощи модулей из ngraph'a и утилит из пакета allnpm.

Отсылаем граф клиенту

Отослать граф с информацией о 100 тысячах узлах и 200+ тысячах связей в лоб (например как JSON) оказалось дорого — слишком большой размер графа. Потому придумал специальный двоичный формат для компактного хранения графа.

В этом формате каждый узел задается тремя 32-битным целыми: координаты узла x, y, z. Позиция узлов шлется сплошным потоком клиенту. Клиент читает тройки и запоминает их индекс:

Index  Position
1      x1, y1, z1
2      x2, y2, z2

Как только клиент получил эти данные он начинает рисовать узлы в пространстве. Но как же передать связи? Связи хранятся в отдельном двоичном файле. Файл состоит из последовательно записанных int32. Некоторые числа отрицательные, некоторые положительные. Отрицательными числами я маркирую начало следующего узла, а положительные говорят с какими индексами связан последний отрицательный.

Например:

-1 2 -3 4 5 

Это означает что вершина 1 связана с вершиной 2, а вершина 3 связана с вершинами 4 и 5. В итоге весь граф помещается в 2.5 MB.

Ну и наконец, отдельным json массивом шлется информация обо всех именах. Индекс в массиве соответствует индексу в файле с позициями.

Разве angular не медленный?

Смотря для чего. Angular.js прекрасная библиотека для создания UI. Я использую angular лишь для отображения результатов поиска и подсказок в интерфейсе. Сама сцена рисуются совершенно независимо от angular.

Многие мои коллеги говорят, что выбирая angular вы выбираете все или ничего. Сложно отказаться/заменить angular если уже начал писать на нем. Думаю они правы, ведь внедрение зависимостей и система модулей в angular чрезвычайно узконаправленная.

Но, если отказаться от использования angular.module() код внезапно перестает выглядеть angular кодом. Это обычные javascript функции, с обычными параметрами. А раз так, их тоже можно легко создавать и делиться ими на npm'e.

Так я и поступил. Заменил angular.module на простой пакет который «накапливает» анугляроподобные функции:

module.exports = require('an').controller(myController);

function myControlelr($scope) {
  $scope.message = "Привет!";
}

и потом одним махом регистрирует накопленные функции когда запускается сайт:

var ngApp = angular.module('allnpmviz3d', []);
require('an').flush(ngApp);
angular.bootstrap(document, [ngApp.name]);
// Теперь myController - вполне закономерный житель в мире angular.js

Финальные заметки

Благодаря npm'у и commonjs'у проект состоит из примерно 1,700 моих строк кода и 63,300 не моих:

мое и не мое

Я знаю, мерять код строками — так себе научно, но в целом, восприятие сложности проекта было значительно улучшено при помощи модульного подхода.

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

:i love npm

и звезды должны вам ответить.

Надеюсь, вам понравилось! Буду рад вашим советам и комментариям!

Автор: anvaka

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js