Управление зависимостями JavaScript - PullRequest
26 голосов
/ 08 июля 2010

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

Это я бы хотел автоматизировать. Например, если у меня есть функция F

Array.prototype.f = function() {};

, на который ссылается другая функция g

MyObject.g = function() {
    var a = new Array();
    a.f();
};

Я хочу быть в состоянии обнаружить, что g ссылается на f.

Как мне это сделать? С чего мне начать? Нужно ли мне писать компилятор или я могу настроить Spidermonkey, например? Кто-нибудь еще делал это?

Любые указатели, чтобы начать меня очень ценится

Спасибо Dok

Ответы [ 6 ]

18 голосов
/ 08 июля 2010

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

JavaScript - это язык с динамической типизацией, поэтому для любого инструмента нет практического способа узнать, что a, если он передан из функции g, является Array, и поэтому, если вызывается f(), естьзависимость.Определяется только то, какие переменные содержат типы во время выполнения, поэтому чтобы выяснить, нужен ли вам интерпретатор, и вы поставили перед собой задачу полной Тьюринга.

Не говоря уже о других динамических аспектахJavaScript, который полностью игнорирует статический анализ, такой как выборка свойств с помощью записи в квадратных скобках, страшных eval или строк в тайм-аутах или атрибутах обработчика событий.

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

Хорошей идеей также является пространство имен каждого модуля, поэтому очень ясно, куда направляется каждый вызов, делая еголегко контролировать зависимости вручную (например, с помощью комментария // uses: ThisModule, ThatModule вверху).

Поскольку расширения встроенных прототипов сложнее отслеживать, сводите их к минимуму,Расширение например.Array Включение методов ECMAScript Fifth Edition (например, indexOf) в браузеры, у которых их еще нет, является хорошей вещью в качестве базового исправления, которое будут использовать все сценарии.Добавление совершенно новой произвольной функциональности к существующим прототипам сомнительно.

10 голосов
/ 22 февраля 2012

Вы пытались использовать менеджер зависимостей, например RequireJS или LabJS ? Я заметил, что никто не упомянул их в этой теме.

С http://requirejs.org/docs/start.html:

Внутри main.js вы можете использовать require () для загрузки любых других скриптов, которые вы нужно запустить:

require(["helper/util"], function(util) {
    //This function is called when scripts/helper/util.js is loaded.
    //If util.js calls define(), then this function is not fired until
    //util's dependencies have loaded, and the util argument will hold
    //the module value for "helper/util".
});

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

8 голосов
/ 09 июля 2010

Как уже предположил @bobince, выполнение статического анализа на JavaScript-программе - это почти невозможная проблема. Компилятор Google Closure делает это до некоторой степени, но затем он также полагается на внешнюю помощь от JSDoc комментариев.

У меня была похожая проблема изнайти порядок, в котором JS-файлы должны быть объединены в предыдущем проекте, и поскольку были загружены JS-файлы, ручное обновление порядка включения казалось слишком утомительным.Вместо этого я придерживался определенных соглашений о том, что представляет собой зависимость для моих целей, и, основываясь на этом, используя простой regexp :), я смог сгенерировать правильный порядок включения.

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

  1. Когда класс расширял какой-то другой класс.
  2. Когда класс Реализовал какой-то другой класс.
  3. Когда класс создал экземпляр объекта какого-либо другого класса, используя ключевое слово new.

Это было просто,и определенно сломанное решение для общего пользования, но оно мне хорошо послужило.Если вы заинтересованы в решении, вы можете увидеть код здесь - он в Ruby.

Если ваши зависимости более сложны, то, возможно, вы могли бы вручную перечислить зависимости в каждом JSсам файл, используя комментарии и некоторый собственный синтаксис, такой как:

// requires: Array
// requires: view/TabPanel
// requires: view/TabBar

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

5 голосов
/ 16 августа 2011

Было бы неплохо иметь инструмент, который может автоматически определять эти зависимости и выбирать, как они загружаются.Лучшие решения сегодня немного грубоваты.Я создал менеджер зависимостей для своих конкретных нужд, который я хочу добавить в список ( Pyramid Dependency Manager ).Он имеет некоторые ключевые функции, которые решают некоторые уникальные сценарии использования.

  1. Обрабатывает другие файлы (включая вставку html для представлений ... да, вы можете разделять свои представления во время разработки)
  2. Объединяетфайлы для вас в javascript, когда вы будете готовы к выпуску (не нужно устанавливать внешние инструменты)
  3. Имеет общее включение для всех HTML-страниц.Вам нужно обновить только один файл, когда зависимость добавлена, удалена, переименована и т. Д.

Некоторые примеры кода, чтобы показать, как он работает во время разработки.

Файл: dependencyLoader.js

//Set up file dependencies
Pyramid.newDependency({
    name: 'standard',
    files: [
    'standardResources/jquery.1.6.1.min.js'
    ]
});

Pyramid.newDependency({
name:'lookAndFeel',
files: [
    'styles.css',
    'customStyles.css',
    'applyStyles.js'
    ]
});

Pyramid.newDependency({
name:'main',
files: [
    'createNamespace.js',
    'views/buttonView.view', //contains just html code for a jquery.tmpl template
    'models/person.js',
    'init.js'
    ],
    dependencies: ['standard','lookAndFeel']
});

HTML-файлы

<head>
    <script src="standardResources/pyramid-1.0.1.js"></script>
    <script src="dependencyLoader.js"></script>
    <script type="text/javascript">
        Pyramid.load('main');
    </script>
</head>

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

1 голос
/ 29 ноября 2011

JSAnalyse использует статический анализ кода для обнаружения зависимостей между файлами javascript: http://jsanalyse.codeplex.com/

Он также позволяет вам определять разрешенные зависимости и обеспечивать их, например, во время сборки.Конечно, он не может обнаружить все зависимости, потому что javascript - это динамический язык интерпретации, который не является типобезопасным, как уже упоминалось.Но это, по крайней мере, информирует вас о вашем графике зависимостей javascript и помогает держать его под контролем.

0 голосов
/ 03 октября 2013

Я написал инструмент для чего-то вроде этого: http://github.com/damonsmith/js-class-loader

Это наиболее полезно, если у вас есть веб-приложение на Java и вы структурируете свой JS-код в стиле Java.Если вы сделаете это, он сможет обнаружить все ваши зависимости кода и связать их вместе с поддержкой зависимостей как во время выполнения, так и во время разбора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...