นี่เก่าไปหน่อย แต่ฉันวิ่งไปตามข้อกำหนดดังนั้นนี่คือทางออกที่ฉันคิดขึ้นมา
ปัญหา:
ทีมพัฒนาของเราดูแลผลิตภัณฑ์เว็บแอปพลิเคชั่น. NET จำนวนมากที่เราย้ายไปยัง AngularJS / Bootstrap VS2010 ไม่ได้ยืมตัวเองอย่างง่ายดายไปยังกระบวนการสร้างที่กำหนดเองและนักพัฒนาของฉันกำลังทำงานเป็นประจำในผลิตภัณฑ์หลายรุ่นของเรา VCS ของเราคือการโค่นล้ม (ฉันรู้ฉันรู้ฉันกำลังพยายามย้ายไปที่ Git แต่เจ้าหน้าที่การตลาดที่น่ารำคาญของฉันกำลังเรียกร้องมาก) และโซลูชัน VS เดียวจะรวมโครงการแยกต่างหากหลายโครงการ ฉันต้องการให้พนักงานของฉันมีวิธีการทั่วไปในการเริ่มต้นสภาพแวดล้อมการพัฒนาโดยไม่ต้องติดตั้งแพคเกจโหนดเดียวกัน (อึก, ซุ้ม, ฯลฯ ) หลายครั้งในเครื่องเดียวกัน
TL; DR:
ต้องการ "npm install" เพื่อติดตั้งสภาพแวดล้อมการพัฒนา 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" "การพึ่งพา"
แก้ไข 1/29/16
npm-setup.js
สคริปต์ที่อัพเดตด้านบนได้รับการแก้ไขดังนี้:
แพ็คเกจ "version" in var packages
ตอนนี้เป็นค่า "package" ที่ส่งไปยังnpm install
บนบรรทัดคำสั่ง นี่เป็นการเปลี่ยนแปลงเพื่ออนุญาตให้ติดตั้งแพคเกจจากที่อื่นนอกเหนือจากที่เก็บที่ลงทะเบียน
หากแพ็กเกจถูกติดตั้งแล้ว แต่ไม่ใช่แพ็คเกจที่ร้องขอแพ็กเกจที่มีอยู่จะถูกลบและแพ็กเกจที่ถูกต้องจะถูกติดตั้ง
ด้วยเหตุผลที่ไม่ทราบสาเหตุเอ็นพีพีจะโยนข้อผิดพลาด EBUSY (-4082) เป็นระยะเมื่อทำการติดตั้งหรือลิงก์ ข้อผิดพลาดนี้ติดอยู่และคำสั่งดำเนินการอีกครั้ง ข้อผิดพลาดเกิดขึ้นน้อยครั้งที่สองและดูเหมือนจะชัดเจนขึ้นเสมอ
"preferGlobal": true
ใน package.json สำหรับโมดูล