Это немного устарело, но я столкнулся с требованием, поэтому вот решение, которое я нашел.
Эта проблема:
Наша команда разработчиков поддерживает множество продуктов для веб-приложений .NET, которые мы переносим на AngularJS / Bootstrap. VS2010 нелегко поддается пользовательским процессам сборки, и мои разработчики постоянно работают над несколькими выпусками наших продуктов. Наша VCS - это Subversion (я знаю, я знаю. Я пытаюсь перейти на Git, но мой надоедливый маркетинговый персонал так требователен), и одно решение VS будет включать несколько отдельных проектов. Мне нужно, чтобы у моего персонала был общий метод инициализации среды разработки без необходимости устанавливать одни и те же пакеты Node (gulp, bower и т. Д.) Несколько раз на одной машине.
TL; DR:
Требуется «установка npm» для установки глобальной среды разработки Node / Bower, а также всех локально необходимых пакетов для продукта .NET.
Глобальные пакеты должны быть установлены, только если они еще не установлены.
Локальные ссылки на глобальные пакеты должны создаваться автоматически.
Решение:
У нас уже есть общая среда разработки, общая для всех разработчиков и всех продуктов, поэтому я создал скрипт NodeJS для установки глобальных пакетов при необходимости и создания локальных ссылок. Сценарий находится в ".... \ SharedFiles" относительно базовой папки продукта:
/*******************************************************************************
* $Id: npm-setup.js 12785 2016-01-29 16:34:49Z sthames $
* ==============================================================================
* Parameters: 'links' - Create links in local environment, optional.
*
* <p>NodeJS script to install common development environment packages in global
* environment. <c>packages</c> object contains list of packages to install.</p>
*
* <p>Including 'links' creates links in local environment to global packages.</p>
*
* <p><b>npm ls -g --json</b> command is run to provide the current list of
* global packages for comparison to required packages. Packages are installed
* only if not installed. If the package is installed but is not the required
* package version, the existing package is removed and the required package is
* installed.</p>.
*
* <p>When provided as a "preinstall" script in a "package.json" file, the "npm
* install" command calls this to verify global dependencies are installed.</p>
*******************************************************************************/
var exec = require('child_process').exec;
var fs = require('fs');
var path = require('path');
/*---------------------------------------------------------------*/
/* List of packages to install and 'from' value to pass to 'npm */
/* install'. Value must match the 'from' field in 'npm ls -json' */
/* so this script will recognize a package is already installed. */
/*---------------------------------------------------------------*/
var packages =
{
"bower" : "bower@1.7.2",
"event-stream" : "event-stream@3.3.2",
"gulp" : "gulp@3.9.0",
"gulp-angular-templatecache" : "gulp-angular-templatecache@1.8.0",
"gulp-clean" : "gulp-clean@0.3.1",
"gulp-concat" : "gulp-concat@2.6.0",
"gulp-debug" : "gulp-debug@2.1.2",
"gulp-filter" : "gulp-filter@3.0.1",
"gulp-grep-contents" : "gulp-grep-contents@0.0.1",
"gulp-if" : "gulp-if@2.0.0",
"gulp-inject" : "gulp-inject@3.0.0",
"gulp-minify-css" : "gulp-minify-css@1.2.3",
"gulp-minify-html" : "gulp-minify-html@1.0.5",
"gulp-minify-inline" : "gulp-minify-inline@0.1.1",
"gulp-ng-annotate" : "gulp-ng-annotate@1.1.0",
"gulp-processhtml" : "gulp-processhtml@1.1.0",
"gulp-rev" : "gulp-rev@6.0.1",
"gulp-rev-replace" : "gulp-rev-replace@0.4.3",
"gulp-uglify" : "gulp-uglify@1.5.1",
"gulp-useref" : "gulp-useref@3.0.4",
"gulp-util" : "gulp-util@3.0.7",
"lazypipe" : "lazypipe@1.0.1",
"q" : "q@1.4.1",
"through2" : "through2@2.0.0",
/*---------------------------------------------------------------*/
/* fork of 0.2.14 allows passing parameters to main-bower-files. */
/*---------------------------------------------------------------*/
"bower-main" : "git+https://github.com/Pyo25/bower-main.git"
}
/*******************************************************************************
* run */
/**
* Executes <c>cmd</c> in the shell and calls <c>cb</c> on success. Error aborts.
*
* Note: Error code -4082 is EBUSY error which is sometimes thrown by npm for
* reasons unknown. Possibly this is due to antivirus program scanning the file
* but it sometimes happens in cases where an antivirus program does not explain
* it. The error generally will not happen a second time so this method will call
* itself to try the command again if the EBUSY error occurs.
*
* @param cmd Command to execute.
* @param cb Method to call on success. Text returned from stdout is input.
*******************************************************************************/
var run = function(cmd, cb)
{
/*---------------------------------------------*/
/* Increase the maxBuffer to 10MB for commands */
/* with a lot of output. This is not necessary */
/* with spawn but it has other issues. */
/*---------------------------------------------*/
exec(cmd, { maxBuffer: 1000*1024 }, function(err, stdout)
{
if (!err) cb(stdout);
else if (err.code | 0 == -4082) run(cmd, cb);
else throw err;
});
};
/*******************************************************************************
* runCommand */
/**
* Logs the command and calls <c>run</c>.
*******************************************************************************/
var runCommand = function(cmd, cb)
{
console.log(cmd);
run(cmd, cb);
}
/*******************************************************************************
* Main line
*******************************************************************************/
var doLinks = (process.argv[2] || "").toLowerCase() == 'links';
var names = Object.keys(packages);
var name;
var installed;
var links;
/*------------------------------------------*/
/* Get the list of installed packages for */
/* version comparison and install packages. */
/*------------------------------------------*/
console.log('Configuring global Node environment...')
run('npm ls -g --json', function(stdout)
{
installed = JSON.parse(stdout).dependencies || {};
doWhile();
});
/*--------------------------------------------*/
/* Start of asynchronous package installation */
/* loop. Do until all packages installed. */
/*--------------------------------------------*/
var doWhile = function()
{
if (name = names.shift())
doWhile0();
}
var doWhile0 = function()
{
/*----------------------------------------------*/
/* Installed package specification comes from */
/* 'from' field of installed packages. Required */
/* specification comes from the packages list. */
/*----------------------------------------------*/
var current = (installed[name] || {}).from;
var required = packages[name];
/*---------------------------------------*/
/* Install the package if not installed. */
/*---------------------------------------*/
if (!current)
runCommand('npm install -g '+required, doWhile1);
/*------------------------------------*/
/* If the installed version does not */
/* match, uninstall and then install. */
/*------------------------------------*/
else if (current != required)
{
delete installed[name];
runCommand('npm remove -g '+name, function()
{
runCommand('npm remove '+name, doWhile0);
});
}
/*------------------------------------*/
/* Skip package if already installed. */
/*------------------------------------*/
else
doWhile1();
};
var doWhile1 = function()
{
/*-------------------------------------------------------*/
/* Create link to global package from local environment. */
/*-------------------------------------------------------*/
if (doLinks && !fs.existsSync(path.join('node_modules', name)))
runCommand('npm link '+name, doWhile);
else
doWhile();
};
Теперь, если я хочу обновить глобальный инструмент для наших разработчиков, я обновляю объект «пакеты» и регистрирую новый скрипт. Мои разработчики проверили его и либо запустили с "node npm-setup.js", либо с помощью "npm install" из любого разрабатываемого продукта для обновления глобальной среды. Все это занимает 5 минут.
Кроме того, чтобы настроить среду для нового разработчика, они должны сначала только установить NodeJS и GIT для Windows, перезагрузить компьютер, проверить папку «Общие файлы» и все разрабатываемые продукты и начать работать.
«Package.json» для продукта .NET вызывает этот сценарий перед установкой:
{
"name" : "Books",
"description" : "Node (npm) configuration for Books Database Web Application Tools",
"version" : "2.1.1",
"private" : true,
"scripts":
{
"preinstall" : "node ../../SharedFiles/npm-setup.js links",
"postinstall" : "bower install"
},
"dependencies": {}
}
Ноты
Обратите внимание, что ссылка на скрипт требует косой черты даже в среде Windows.
«npm ls» выдаст «npm ERR! extraneous:» сообщения для всех локально связанных пакетов, так как они не перечислены в «package.json» «зависимости».
Редактировать 29.01.16
Обновленный npm-setup.jsскрипт выше был изменен следующим образом:
Пакет «версия» в var packagesтеперь является значением «пакета», передаваемым npm installв командной строке. Это было изменено, чтобы разрешить установку пакетов не из зарегистрированного репозитория.
Если пакет уже установлен, но не запрошен, существующий пакет будет удален, а правильный установлен.
По неизвестным причинам npm будет периодически выдавать ошибку EBUSY (-4082) при установке или ссылке. Эта ошибка перехвачена и команда повторно выполнена. Ошибка редко случается во второй раз и, кажется, всегда устраняется.
"preferGlobal": trueвнутри package.json для модуля.