这有点老了,但我遇到了这个要求,所以这是我想出的解决方案。
问题:
我们的开发团队维护着许多.NET Web应用程序产品,我们正在将其迁移到AngularJS / Bootstrap。 VS2010不容易适应自定义构建流程,我的开发人员通常在多个产品的发布上工作。我们的版本控制系统是Subversion(我知道,我知道。我正在尝试转换到Git,但我的顽固营销人员如此苛刻),一个单独的VS解决方案将包括几个独立的项目。我需要我的员工拥有一种通用方法来初始化他们的开发环境,而无需在同一台机器上多次安装相同的Node软件包(gulp、bower等)。
简而言之:
需要“npm install”安装全局的Node/Bower开发环境以及.NET产品的所有本地所需包。
仅当未安装时才应安装全局软件包。
必须自动创建到全局包的本地链接。
解决方案:
我们已经拥有一个所有开发人员和所有产品共享的通用开发框架,因此我创建了一个NodeJS脚本,在需要时安装全局软件包并创建本地链接。该脚本位于相对于产品根文件夹的“....\SharedFiles”中。
var exec = require('child_process').exec;
var fs = require('fs');
var path = require('path');
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",
"bower-main" : "git+https://github.com/Pyo25/bower-main.git"
}
var run = function(cmd, cb)
{
exec(cmd, { maxBuffer: 1000*1024 }, function(err, stdout)
{
if (!err) cb(stdout);
else if (err.code | 0 == -4082) run(cmd, cb);
else throw err;
});
};
var runCommand = function(cmd, cb)
{
console.log(cmd);
run(cmd, cb);
}
var doLinks = (process.argv[2] || "").toLowerCase() == 'links';
var names = Object.keys(packages);
var name;
var installed;
var links;
console.log('Configuring global Node environment...')
run('npm ls -g --json', function(stdout)
{
installed = JSON.parse(stdout).dependencies || {};
doWhile();
});
var doWhile = function()
{
if (name = names.shift())
doWhile0();
}
var doWhile0 = function()
{
var current = (installed[name] || {}).from;
var required = packages[name];
if (!current)
runCommand('npm install -g '+required, doWhile1);
else if (current != required)
{
delete installed[name];
runCommand('npm remove -g '+name, function()
{
runCommand('npm remove '+name, doWhile0);
});
}
else
doWhile1();
};
var doWhile1 = function()
{
if (doLinks && !fs.existsSync(path.join('node_modules', name)))
runCommand('npm link '+name, doWhile);
else
doWhile();
};
现在,如果我想为我们的开发人员更新全局工具,我会更新“packages”对象并提交新脚本。我的开发人员将其检出,并使用“node npm-setup.js”或在任何正在开发的产品下使用“npm install”来更新全局环境。整个过程只需要5分钟。
此外,要为新开发人员配置环境,他们必须先安装NodeJS和适用于Windows的GIT,然后重新启动计算机,检查“Shared Files”文件夹和任何正在开发的产品,然后开始工作。
对于.NET产品的“package.json”调用此脚本以进行安装:
{
"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": {}
}
注意事项
编辑 1/29/16
上面更新的 npm-setup.js
脚本已被修改如下:
var packages
中的软件包 "version" 现在是命令行传递给 npm install
的 "package" 值。这样更改是为了允许从其他位置安装软件包。
如果软件包已经安装但不是所请求的软件包,则删除现有软件包并安装正确的软件包。
由于原因未知,当执行安装或链接时,npm 偶尔会抛出 EBUSY 错误 (-4082)。此错误被捕获,然后重新执行命令。该错误很少第二次发生,而且似乎总是清除。
"preferGlobal": true
选项来实现类似的效果。 - Raynos"preferGlobal":true
更多的内容,那就太好了......但我不知道在package.json文件中应该放在哪里。根据NPM文档:preferGlobal是针对您自己的包的,设置后将使您的包被安装为全局包。不过看起来更像是一份指南。 - PPPaul