Điều này hơi cũ nhưng tôi gặp phải yêu cầu nên đây là giải pháp tôi đưa ra.
Vấn đề:
Nhóm phát triển của chúng tôi duy trì nhiều sản phẩm ứng dụng web .NET mà chúng tôi đang chuyển sang AngularJS / Bootstrap. VS2010 không dễ dàng cho vay các quy trình xây dựng tùy chỉnh và các nhà phát triển của tôi thường xuyên làm việc trên nhiều bản phát hành sản phẩm của chúng tôi. VCS của chúng tôi là Subversion (tôi biết, tôi biết. Tôi đang cố gắng chuyển sang Git nhưng nhân viên tiếp thị phiền phức của tôi rất khắt khe) và một giải pháp VS duy nhất sẽ bao gồm một số dự án riêng biệt. Tôi cần nhân viên của mình có một phương pháp chung để khởi tạo môi trường phát triển của họ mà không phải cài đặt cùng các gói Node (gulp, bower, v.v.) nhiều lần trên cùng một máy.
TL; DR:
Cần "npm install" để cài đặt môi trường phát triển Node / Bower toàn cầu cũng như tất cả các gói yêu cầu cục bộ cho một sản phẩm .NET.
Các gói toàn cầu chỉ nên được cài đặt nếu chưa được cài đặt.
Liên kết cục bộ đến các gói toàn cầu phải được tạo tự động.
Giải pháp:
Chúng tôi đã có một khung phát triển chung được chia sẻ bởi tất cả các nhà phát triển và tất cả các sản phẩm vì vậy tôi đã tạo một tập lệnh NodeJS để cài đặt các gói toàn cầu khi cần và tạo các liên kết cục bộ. Tập lệnh nằm trong ".... \ SharedFiles" liên quan đến thư mục cơ sở của sản phẩm:
/*******************************************************************************
* $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();
};
Bây giờ nếu tôi muốn cập nhật một công cụ toàn cầu cho các nhà phát triển của mình, tôi sẽ cập nhật đối tượng "gói" và kiểm tra tập lệnh mới. Các nhà phát triển của tôi kiểm tra nó và chạy nó với "nút npm-setup.js" hoặc bằng "npm install" từ bất kỳ sản phẩm nào đang được phát triển để cập nhật môi trường toàn cầu. Toàn bộ điều mất 5 phút.
Ngoài ra, để định cấu hình môi trường cho nhà phát triển mới, trước tiên họ phải cài đặt NodeJS và GIT cho Windows, khởi động lại máy tính của họ, kiểm tra thư mục "Tệp chung" và bất kỳ sản phẩm nào đang được phát triển và bắt đầu hoạt động.
"Gói.json" cho sản phẩm .NET gọi tập lệnh này trước khi cài đặt:
{
"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": {}
}
Ghi chú
Lưu ý tham chiếu tập lệnh yêu cầu dấu gạch chéo về phía trước ngay cả trong môi trường Windows.
"npm ls" sẽ cung cấp các thông báo "npm ERR! ngoại lai:" cho tất cả các gói được liên kết cục bộ vì chúng không được liệt kê trong "phụ thuộc" "gói.json".
Chỉnh sửa 1/29/16
npm-setup.js
Kịch bản cập nhật ở trên đã được sửa đổi như sau:
Gói "phiên bản" var packages
hiện là giá trị "gói" được truyền npm install
vào dòng lệnh. Điều này đã được thay đổi để cho phép cài đặt các gói từ một nơi khác ngoài kho lưu trữ đã đăng ký.
Nếu gói đã được cài đặt nhưng không phải là gói được yêu cầu, gói hiện có sẽ bị xóa và gói chính xác được cài đặt.
Vì những lý do không rõ, npm sẽ định kỳ đưa ra lỗi EBUSY (-4082) khi thực hiện cài đặt hoặc liên kết. Lỗi này bị mắc kẹt và lệnh được thực thi lại. Lỗi hiếm khi xảy ra lần thứ hai và dường như luôn luôn rõ ràng.
"preferGlobal": true
bên trong pack.json cho một mô-đun.