Как я профессионально структурирую проекты Javascript с модульным шаблоном?

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

Итак, как управляются проекты с большими модульными шаблонами?

Ответы

Ответ 1

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

File1 определяет модуль M.n

var M = M || {};
M.n = M.n || {};

(function (self) {
    self.doSomething = function () {
        console.log("something");
    };
})(M.n);

File2 определяет модуль M.n.p

var M = M || {};
M.n = M.n || {};
M.n.p = M.n.p || {};

(function (self) {
    self.doSomethingElse = function () {
       console.log("something else");
    };
})(M.n.p);

Теперь в вашем "основном" script вы можете свободно использовать члены этих модулей.

M.n.doSomething();
M.n.p.doSomethingElse();

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

 var namespace = function(path, context, args) {
  var finalLink = namespace._generateChain(path, window);
  context.apply(finalLink, [finalLink].concat(args));
 };

 namespace._generateChain = function(path, root) {
  var segments = path.split('.'),
      cursor = root,
      segment;

  for (var i = 0; i < segments.length; ++i) {
   segment = segments[i];
   cursor = cursor[segment] = cursor[segment] || {};
  }

  return cursor;
 };

Для использования:

namespace("M.n.p", function (self) {
   self.doSomethingElse = function () {
      console.log("something else");
   };
});

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

namespace("M.n.p", function (self, $) {
   self.doSomethingElse = function () {
      $("p").text("something else");
   };
}, jQuery);

Ответ 2

Используйте RequireJS для организации вещей. Для общей логики общие методы должны храниться в глобально доступном пространстве имен или доступны через require(). Мне не нравилось делать много вызовов require() для кода приложения, поэтому я включаю модули в куски и каждый прикрепляю их к определенному пространству имен через определение включения.

//Core.js
define(function(){
  return {
    ns: 'global namespace'
  };
});

//newMethod.js
define(['core'], function( ns ){
  ns.newMethod = function(){ console.log( 'my new method ' ); }
});

//Application code
require(['newMethod'], function( namespace ) {
   console.log( namespace.ns ); //global namespace
   namespace.newMethod(); //'my new method'
});