Подтвердить что ты не робот

Лучшая практика для структурирования библиотек требуется в node.js

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

Я немного смущен, потому что есть несколько способов сделать это, и я не уверен, что является лучшим/более подходящим/более надежным. Вот два варианта, но мне интересно, являются ли они лучшими (например, я видел фрагменты, которые используют module.exports = exports = function(){} и т.д.)

//option1.js


"use strict";

module.exports =  function(){

     exports.test1 =  function(){ console.log('hi I'm test1')};
     exports.test2 =  function(){ console.log('hi I'm test2')};
     return exports;
};

//option2.js

"use strict";

module.exports =  {

     test1 : function(){ console.log('soy test1')},
     test2 :  function(){ console.log('soy test2')}

};

//test_controller.js

/* Requiring helpers in different ways */
var option1 = require('./option1.js')();
var option2 = require('./option2.js');
4b9b3361

Ответ 1

Я думаю о своих файлах в трех разделах:

Раздел 1: Зависимости CommonJS

var lib1 = require("lib1");
var lib2 = require("lib2");

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

Раздел 2: Обычный код JavaScript

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

var MY_CONST = 42;

function helper1() {
    //excellent code here
}

function helper2() {
    //excellent code here
}

Держите секцию 2 чистой JS. Не используйте идиомы commonJS в этом среднем "чистом" разделе. Не используйте module, exports, require и т.д. Это только моя личная рекомендация, поскольку сам JS стабилен, но упаковка в модули все еще находится под большим изменением, и лучше сохранить биты CommonJS, которые являются посторонними и могут быть изменены отдельно от интересных битов кода. Модули ECMAScript 6, скорее всего, заменят CommonJS через несколько лет, поэтому сделайте это проще для себя, сохранив в чистом ECMAScript 5 раздел 2 и сделав "CommonJS Sandwich ™", как мне нравится называть его.

Раздел 3: Экспорт CommonJS

exports.helper1 = helper1;
exports.helper2 = helper2;
  • Включение всего вашего экспорта в конце также дает вам быстрый способ понять, что представляет собой ваш публичный API, и предотвращает случайную экспорт свойств из-за неосторожного копирования/вставки.
  • Я предпочитаю вышеупомянутый синтаксис exports.foo = foo; в отличие от назначения module.exports для нового литерала объекта. Я считаю, что это позволяет избежать проблемы с конечной запятой с последним свойством объектного литерала.
  • Выполнение чего-либо еще с вашими инструкциями require или exports почти бесполезно и излишне гладко или волшебно. Пока вы не будете продвинуты, не делайте ничего интересного здесь. (даже тогда, если вы не TJ Holowaychuk, вы, вероятно, просто глупы)

Что мне следует экспортировать

Одна функция (стиль @substack)

function degreesToRadians(degrees) {}

module.exports = degreesToRadians;

Держите его маленьким и простым.

Объект функций

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

var foo = require("foo");

function doubleFoo(value) {
  return foo(value) * 2;
}

function tripleFoo(value) {
  return foo(value) * 3;
}

exports.doubleFoo = doubleFoo;
exports.tripleFoo = tripleFoo;

Функция конструктора

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

function GoCart() {
  this.wheels = 4;
}

GoCart.prototype.drive = function drive() {
  //vroom vroom
}

module.exports = GoCart;

A Factory/Конфигурация закрытия

Как только вы освоите вышеприведенные 2 шаблона (действительно!) и убедитесь, что экспортируете функцию factory, которая принимает параметры и, возможно, делает некоторые другие динамические вещи, идите на это, но если у вас есть сомнения, придерживайтесь первых 2, более простые варианты.

//do-stuff.js
function doStuff(howFast, what) {
   return "I am doing " + what + " at speed " + howFast;
}

function setup(options) {
  //The object returned by this will have closure access to options
  //for its entire lifetime
  return {doStuff: doStuff.bind(null, options.howFast)};
}

module.exports = setup;

Итак, вы можете использовать это как

var doStuff = require("./do-stuff")({howFast: "blazing speed"});
console.log(doStuff.doStuff("jogging"));
//"I am doing jogging at speed blazing speed"

Ответ 2

Для библиотек-утилит без ограничений опция2.js - это путь, потому что нет необходимости в том, чтобы код в module.exports выполнялся каждый раз, когда вы require, что происходит, когда вы вызываете require('./option1.js')() для использования option1.js.

Если, с другой стороны, ваши модули подвергаются конструкторам, которые создавали объекты, которые содержали состояние, тогда вам понадобится option1.js. Например,

person.js:

module.exports = function(firstName,lastName){
    this.firstName = firstName;
    this.lastName = lastName;
};

а затем использовать его:

var Person = require("./person");

var person1 = new Person("Foo","Bar");
var person2 = new Person("Joe","Shmoe");

Другим преимуществом опции1.js(как показано выше) является то, что он позволяет передавать параметры в модуль.