Статьи

NPM для всего

Экосистема JS известна своим широким спектром пакетов и инструментов. Помимо менеджера пакетов по умолчанию, который поставляется с Node.js — NPM (менеджер пакетов узлов), есть Bower.js, Jam.js и многие другие.

В течение довольно длительного периода моей настройкой по умолчанию был NPM для всех серверных компонентов и Bower.js для клиентской части. Это работало довольно хорошо вместе, особенно в сочетании с Require.js.

Но недавно я перешел на настройку только NPM . Это позволило мне использовать стиль CommonJS как для внешнего, так и для внутреннего интерфейса, и избавилось от таких исполнителей, как Grunt и Gulp.

CommonJS

Делая много серверного кода, я действительно привык к стилю CommonJS, который прост, практичен и силен. CommonJS модульность проста, как,

var module = {
};
// export the module
module.exports = module;

и

// use the module
var module = require('./module');

Node.js очень популяризировал подход Common.js. И NPM оказался одним из лучших когда-либо созданных менеджеров пакетов.

Но для фронт-энда NPM был не совсем подходящим. Прежде всего, из-за браузеров не понимают стиль модулей Common.js. Во-вторых, модули npm помещаются в папку ./node_modules, обычно это корень проекта, что усложняет обращение к этим скриптам из index.html и настройку статических ресурсов сервера для сервера из папки ./node_modules.

Browserify пришел, чтобы изменить это.

Browserify

Browserify — это JavaScript-инструмент, позволяющий:

  1. Используйте стиль Common.js для интерфейсных приложений.
  2. Разрешено использовать различные пакеты npm прямо в браузере.

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

Конечно, ничего не приходит бесплатно. Стоимость Browserify — это шаг сборки . Вы должны представить, чтобы преобразовать приложение Common.js в пакет, который загружается и выполняется браузером.

Более того, некоторые пакеты по-прежнему размещаются на Bower. Даже, возможно использовать пакеты Bower вместе с пакетами NPM (посредством преобразования debowerify). Я быстро понял, что этот подход очень непрактичен.

Итак, в течение последних нескольких месяцев моим основным вкладом в GitHub было принятие некоторых интерфейсных пакетов, соответствующих стандарту Common.js, и публикация их в NPM после.

Настройка

Теперь NPM — единственный менеджер пакетов, который можно использовать как для внешнего интерфейса, так и для внутреннего интерфейса.

Все зависимости упоминаются в одном файле package.json вместо нескольких файлов … и вы никогда не забудете запустить bower install, так как npm install все установит.

  "dependencies": {
    "async": "^0.9.0",
    "babelify": "^5.0.4",
    "body-parser": "^1.9.0",
    "colors": "^1.0.2",
    "cors": "^2.4.2",
    "envify": "^3.4.0",
    "express": "^4.9.5",
    "method-override": "^2.2.0",
    "moment": "^2.8.3",
    "morgan": "^1.3.2",
    "node-logentries": "^0.1.4",
    "react": "^0.13.1",
    "respawn": "^1.0.1"
  }

Код на стороне сервера,

var express = require('express');
// configurations...
app.listen(port, function () {
    logger.info('editor-app listening on port ' + port + ' ' + env);
});

Код на стороне клиента,

var React = require('react');
var Component = React.create({
});
module.exports  = Component;

Тот же стиль, чувствует себя красиво и чисто.

Нет бегунов задач

NPM не только менеджер пакетов. Это также очень простой бегун задач (или скрипты бегун). За это есть специальный раздел, который называется «скрипты». Первоначально он использовался для запуска некоторых задач, связанных с пакетами (запуск тестов, выполнение настроек до и после установки).

Традиционно Grunt.js и Gulp.js используются для компиляции статических проверок. Но интерфейс CLI многих инструментов и потоковых трубопроводов может заменить их.

В качестве примера я покажу довольно типичные настройки:

  • создать JavaScript с помощью browserify и применить минификацию
  • собрать Sass с помощью node-sass и применить минификацию
  • запустить наблюдатель и восстановить измененные активы

Сборка JavaScript

Browserify должен быть установлен глобально,

$ npm install -g browserify

В package.json, в разделе скриптов, добавим такой скрипт,

  "scripts": {
    "build-js": "browserify public/js/app.js -o public/build/app.js",

Поскольку я также использую несколько преобразований в своих приложениях, Browserify должен быть правильно настроен для этого. Он проверяет, содержит ли package.json раздел browserify, и если он это делает — будет использовать его содержимое в качестве собственных параметров.

  "browserify": {
    "transform": [
      "babelify",
      "envify"
    ]
  },

Building Sass

Как и с Browserify, node-sass должен быть установлен глобально,

$ npm install -g node-sass

Затем пакет.json меняется,

  "scripts": {
    "build-js": "browserify public/js/app.js -o public/build/app.js",
    "build-sass": "node-sass public/sass/main.scss public/build/main.css",

минификация

Теперь давайте минимизируем оба актива, используя одну из лучших концепций — Unix pipe.

Нам нужны еще два пакета, uglifyjs и cleancss.

$ npm install -g uglifyjs clean-css

И соответствующие сценарии,

  "scripts": {
    "build-js": "browserify public/js/app.js -o public/build/app.js",
    "build-sass": "node-sass public/sass/main.scss public/build/main.css",
    // minifying
    "build-min-js": "browserify public/js/app.js | uglifyjs -o public/build/app.min.js",
    "build-min-sass": "node-sass public/sass/main.scss | cleancss -o public/build/main.min.css",

наблюдение

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

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

  "scripts": {
    "build-js": "browserify public/js/app.js -o public/build/app.js",
    "build-sass": "node-sass public/sass/main.scss public/build/main.css",
    "build-min-js": "browserify public/js/app.js | uglifyjs -o public/build/app.min.js",
    "build-min-sass": "node-sass public/sass/main.scss | cleancss -o public/build/main.min.css",
    // watching
    "watch-js": "nodemon -e js -w public/js -x 'npm run build-js'",
    "watch-sass": "nodemon -e scss -w public/sass -x 'npm run build-sass'",

Complex tasks

Typically, you need to run few tasks simultaneously, e.g. build all scripts or watch all application. We can combine commands, by running background tasks,

"build": "npm run build-js & npm run build-sass",
"watch": "npm run watch-js & npm run watch-sass",

To build full app,

$ npm run build

or to watch it,

$ npm run watch

Using dev-dependencies

Глобальные пакеты — это не круто, потому что они могут отсутствовать в окне разработчика, где клонируется приложение. Более того, управление зависимостями становится немного сложнее, если вам нужно работать над разными проектами в зависимости от разных версий инструментов. Как правильно заметил @bcomnes , все инструменты, такие как browserify, uglify и т. Д., Могут быть установлены как локальные dev-зависимости, которые выбираются во время установки npm и будут доступны для вызова из папки проекта в виде глобальных команд,

$ npm install --save-dev browserify uglifyjs node-sass clean-css

Итак, package.json получил такое обновление,

"devDependencies": {
  "browserify": "^9.0.7",
  "clean-css": "^3.1.9",
  "node-sass": "^2.1.1",
  "uglifyjs": "^2.4.10"
},

Takeaways

  • Once you implement front end library, consider UMD so your modules are reusable in any environment.
  • Embrace CommonJS, use Browserify/Webpack/Whatever to use CommonJS (or ES6) on client.
  • For many cases, you really don’t need Grunt or Gulp, all is easily doable with NPM scripts.

As example, please refer to brick, the project I currently use as boilerplate for new applications.