NodeJS ต้องการโมดูล / แพ็คเกจโกลบอล


160

ฉันพยายามติดตั้งทั่วโลกจากนั้นใช้foreverและforever-monitorเช่นนี้:

npm install -g forever forever-monitor

ฉันเห็นเอาต์พุตปกติและการดำเนินการที่คัดลอกไฟล์ไปยังพา ธ โกลบอล แต่ถ้าฉันพยายามrequire("forever");ฉันได้รับข้อผิดพลาดที่บอกว่าไม่พบโมดูล

ฉันใช้ทั้งรุ่นล่าสุดของโหนดและ npm และฉันรู้แล้วเกี่ยวกับการเปลี่ยนแปลงที่เกิดขึ้นในการติดตั้งทั่วโลกกับท้องถิ่น แต่ฉันไม่ต้องการที่จะติดตั้ง localy ในทุกโครงการและฉันกำลังทำงานบนแพลตฟอร์มที่ไม่ 'T สนับสนุนlinkดังนั้นnpm linkหลังจากที่มีการติดตั้งทั่วโลกเป็นไปไม่ได้สำหรับฉัน

คำถามของฉันคือ: ทำไมฉันไม่ต้องการแพ็คเกจที่ติดตั้งทั่วโลก? นั่นเป็นคุณสมบัติหรือข้อบกพร่องหรือไม่? หรือฉันกำลังทำอะไรผิดพลาด?

PS: เพียงเพื่อให้มันชัดเจน: ฉันไม่ต้องการติดตั้งในเครื่อง




ดังนั้น~/.config/yarn/globalสำหรับเส้นด้าย
localhostdotdev

คำตอบ:


216

ใน Node.js ไม่จำเป็นต้องดูในโฟลเดอร์ที่ติดตั้งโมดูลร่วม

คุณสามารถแก้ไขได้โดยการตั้งค่าตัวแปรสภาพแวดล้อม NODE_PATH ใน Linux นี่จะเป็น:

export NODE_PATH=/usr/lib/node_modules

หมายเหตุ: ขึ้นอยู่กับตำแหน่งที่ติดตั้งโมดูลโกลบอลของคุณจริง

ดู: โหลดจากโฟลเดอร์โลก


24
บนเครื่อง Ubuntu 13.10 ของฉันเส้นทางทั่วโลกสำหรับโมดูลแตกต่างจากที่คุณแสดงที่นี่ ฉันต้องใช้export NODE_PATH=/usr/local/lib/node_modulesแทน
Drew Noakes

11
หากคุณใช้ Windows 7/8 และยังไม่ได้ลบล้างค่าเริ่มต้นการติดตั้งใด ๆ ของ Node การตั้งค่าNODE_PATHตัวแปรสภาพแวดล้อมC:\Users\{USERNAME}\AppData\Roaming\npm\node_modulesจะเป็นไปได้
Wes Johnson

5
@WesJohnson %AppData%\npm\node_modulesจะทำงานบน Windows 10
theblang

6
หากฉันตั้งค่าฉันNODE_PATHสามารถใช้โมดูลทั้งในระดับโลกและระดับท้องถิ่นพร้อมกันได้หรือไม่
เปาโลโอลีฟราลีรา

6
อีกทางเลือกหนึ่งแทนที่จะเป็นเส้นทางแบบคงที่เช่นหากคุณใช้ NVM:NODE_PATH=$(npm root -g)
ธันวาคม

98

หลังจากที่คุณติดตั้งแพคเกจทั่วโลกคุณจะต้องเชื่อมโยงโครงการท้องถิ่นกับแพคเกจทั่วโลก

npm install express -g
cd ~/mynodeproject/
npm link express  

ดูที่นี่


2
ฉันทำงานบนแพลตฟอร์มที่ไม่สนับสนุนลิงก์ (ตามสถานะคำถามของฉัน) blog.nodejs.org/2011/04/06/npm-1-0-link
alexandernst

1
คุณใช้แพลตฟอร์มไหน
user568109

1
ฉันไม่ต้องการยุ่งกับลิงค์ (หรือลิงค์สัญลักษณ์เลย) ฉันแค่ต้องการติดตั้งแพ็คเกจทั่วโลกและต้องการมัน ฉันรู้ว่า NPM ได้รับการออกแบบใหม่เพื่อหลีกเลี่ยงปัญหานี้ แต่มันยากแค่ไหนที่จะทำสิ่งนี้ให้สำเร็จ
alexandernst

13
จะทำอย่างไรถ้าฉันไม่มีโครงการ ~/some-stand-alone-random-nodejs-test.jsพูด ฉันไม่ต้องการเปลี่ยนโฟลเดอร์บ้านของฉันเป็นไดเรกทอรีโครงการ ฉันไม่ต้องการสร้างโฟลเดอร์ใหม่สำหรับการทดสอบขนาดเล็กทุกครั้ง
AnnanFay

1
ทำงานได้สมบูรณ์แบบบน Windows 8.1 จากโหนดบรรทัดคำสั่งcdไปยังโฟลเดอร์ node_modules โลคัลโครงการของฉันจากนั้นถูกเรียกใช้งานnpm link <module>จากนั้นคุณจะเห็นทางลัด (ลิงค์) ที่สร้างขึ้นในโฟลเดอร์node_moduleของโครงการของคุณซึ่งอ้างอิงโมดูลโหนดส่วนกลาง
dynamiclynk

26

ขอโทษสำหรับความลึกลับ แต่ฉันสามารถระบุเส้นทางแบบฮาร์ดโค้ดไปยังโมดูลที่ติดตั้งทั่วโลก:

var pg = require("/usr/local/lib/node_modules/pg");

สิ่งนี้ไม่สมบูรณ์แบบ แต่การพิจารณาว่า Unity3d พยายามที่จะ "รวบรวม" จาวาสคริปต์ทั้งหมดที่รวมอยู่ในไดเรกทอรีโครงการฉันไม่สามารถติดตั้งแพ็คเกจใด ๆ ได้


4
Unity3D ไม่รองรับ JavaScript มันสนับสนุน JS-เช่นไวยากรณ์สำหรับล่าม Boo / ของคอมไพเลอร์(Boo เป็นงูใหญ่เช่นภาษาสำหรับ NET) ที่จะออกวางตลาด deceptively เป็น“JavaScript” ชื่ออื่น ๆ ที่ถูกต้องสำหรับภาษาสามัคคีสนับสนุนคือUnityScript เนื่องจากมันไม่ได้ใกล้เคียงกับภาษาเดียวกันถัดจาก JS ที่เขียนขึ้นสำหรับเว็บหรือสำหรับ Node.js จะใช้งานได้ใน Unity ข้อมูลเพิ่มเติมเกี่ยวกับความแตกต่างของ wiki Unity อย่างเป็นทางการ: wiki.unity3d.com/index.php/UnityScript_versus_JavaScript
Slipp D. Thompson

19

ฉันรู้ว่านี้เป็นคำถามที่เก่า แต่ฉันวิ่งเข้าไปในนี้เมื่อพยายามที่จะทำบางการตรวจสอบรุ่นที่ใช้semverในสคริปต์ในpreinstall package.jsonเนื่องจากฉันรู้ว่าฉันไม่สามารถพึ่งพาโมดูลในพื้นที่ที่ติดตั้งไว้ฉันจึงใช้สิ่งนี้เพื่อต้องการsemverจากnode_modulesโฟลเดอร์ทั่วโลก(ตามnpmที่ฉันรู้ว่ามีอยู่)

function requireGlobal(packageName) {
  var childProcess = require('child_process');
  var path = require('path');
  var fs = require('fs');

  var globalNodeModules = childProcess.execSync('npm root -g').toString().trim();
  var packageDir = path.join(globalNodeModules, packageName);
  if (!fs.existsSync(packageDir))
    packageDir = path.join(globalNodeModules, 'npm/node_modules', packageName); //find package required by old npm

  if (!fs.existsSync(packageDir))
    throw new Error('Cannot find global module \'' + packageName + '\'');

  var packageMeta = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json')).toString());
  var main = path.join(packageDir, packageMeta.main);

  return require(main);
}

ฉันชอบวิธีนี้เพราะไม่ต้องติดตั้งโมดูลพิเศษเพื่อใช้งาน

ฉันไม่ได้ไปด้วยNODE_PATHวิธีแก้ปัญหาเหมือนที่คนอื่นแนะนำเพราะฉันต้องการให้มันทำงานบนเครื่องของทุกคนโดยไม่จำเป็นต้องมีการกำหนดค่าเพิ่มเติม / การตั้งค่าก่อนที่จะใช้npm installสำหรับโครงการของฉัน

วิธีนี้จะถูกเข้ารหัสจะรับประกันได้ว่าจะหาโมดูลระดับบนสุด (ติดตั้งโดยใช้npm install -g ...) หรือโมดูลที่ต้องการโดยnpm(แสดงรายการdependenciesที่นี่: https://github.com/npm/npm/npm/blob/master/package.json ) หากคุณกำลังใช้ NPM เวอร์ชันที่ใหม่กว่าอาจพบว่าการพึ่งพาแพ็กเกจที่ติดตั้งทั่วโลกอื่น ๆ เนื่องจากมีโครงสร้างที่ราบเรียบสำหรับnode_modulesโฟลเดอร์ในขณะนี้

หวังว่านี่จะเป็นประโยชน์กับใครบางคน


19

ตามเอกสาร Node.js จะค้นหาตามตำแหน่งต่อไปนี้ตามค่าเริ่มต้น:

  1. เส้นทางที่กำหนดไว้ในNODE_PATHตัวแปรสภาพแวดล้อม

    หมายเหตุ: NODE_PATHตัวแปรสภาพแวดล้อมถูกตั้งค่าเป็นรายการที่คั่นด้วยโคลอนของพา ธ สัมบูรณ์

  2. node_modulesโฟลเดอร์ปัจจุบัน (ท้องถิ่น)

  3. $HOME/.node_modules (ทั่วโลก)

    หมายเหตุ: $HOMEเป็นโฮมไดเรกทอรีของผู้ใช้

  4. $HOME/.node_libraries (ทั่วโลก)
  5. $PREFIX/lib/node (ทั่วโลก)

    หมายเหตุ: มีการกำหนดค่าของ$PREFIX Node.jsnode_prefix

    ในการตรวจสอบค่าปัจจุบันของnode_prefixให้รัน:

    node -p process.config.variables.node_prefix

    หมายเหตุ: คำนำหน้าสอดคล้องกับพารามิเตอร์ในระหว่างการสร้างและมันเทียบกับ--prefix process.execPathไม่ให้สับสนกับคุณค่าจากnpm config get prefixคำสั่ง แหล่ง

หากไม่พบโมดูลที่ระบุแสดงว่าไม่มีโมดูลดังกล่าวในตำแหน่งใดตำแหน่งหนึ่งดังกล่าว

ตำแหน่งของโฟลเดอร์โกลบอลรูทที่ติดตั้งโมดูลสามารถพิมพ์ได้โดย: npm root -g(โดยค่าเริ่มต้นเส้นทางจะถูกคำนวณ ณ รันไทม์เว้นแต่จะถูกแทนที่ในnpmrcไฟล์ )

สารละลาย

คุณสามารถลองวิธีแก้ไขปัญหาต่อไปนี้:

  • ระบุตำแหน่งโมดูลส่วนกลางของคุณในNODE_PATHตัวแปรสภาพแวดล้อม เช่น

    echo 'require("forever")' | NODE_PATH="$(npm root -g):$NODE_PATH" node

    หากต้องการทดสอบและพิมพ์ค่าของNODE_PATHให้รัน:

    echo 'console.log(process.env.NODE_PATH); require("forever")' | NODE_PATH="$(npm root -g):$NODE_PATH" node 
  • สำหรับวิธีการแก้ปัญหาที่ถาวรมากขึ้นเชื่อมโยง$HOME/.node_modulesโฟลเดอร์ผู้ใช้ทั่วโลกของคุณเพื่อชี้ไปที่โฟลเดอร์รูทโดยใช้คำสั่งนี้:

    ln -vs "$(npm root -g)" "$HOME"/.node_modules

    จากนั้นให้ทดสอบอีกครั้งผ่านecho 'require("forever")' | nodeคำสั่ง:

  • เปลี่ยนโฟลเดอร์ปัจจุบันเป็นตำแหน่งที่ติดตั้งส่วนขยายไว้ชั่วคราวก่อนที่จะเรียกใช้สคริปต์ เช่น

    npm install -g forever
    cd "$(npm root -g)"
    echo 'require("forever")' | node
    cd -
  • กำหนดค่าปลายทางการติดตั้งทั่วโลกในnpmไฟล์ userconfig (ดู:)npm help 5 npmrcหรือโดยuserconfigparam ( --prefix)

    npm config listเพื่อแสดงการตั้งค่าปัจจุบันทำงาน:

    npm config editแก้ไขการตั้งค่าปัจจุบันการทำงาน:

  • ระบุเส้นทางที่เต็มไปด้วยสถานที่ตั้งโหนดโมดูลrequire()เมื่อโทร เช่น

    require("/path/to/sub/module")
  • ติดตั้งแพ็คเกจไปยังตำแหน่งที่กำหนดเองเช่น

    npm install forever -g --prefix "$HOME"/.node_modules

    อย่างไรก็ตามการติดตั้งจะดำเนินต่อไป~/.node_modules/lib/node_modules/ดังนั้นจึงจำเป็นต้องเพิ่มตำแหน่ง

    โปรดดู: แพคเกจติดตั้งท้องถิ่น npm ไปยังตำแหน่งที่กำหนดเอง

  • สร้าง symlinkในโฟลเดอร์ปัจจุบันจากตำแหน่งที่ตั้งของแพคเกจส่วนกลาง เช่น

    npm link forever

ดูเหมือนว่า 4. โฟลเดอร์ node_modules ปัจจุบัน (ในพื้นที่) มีความสำคัญมากกว่า 3 $ PREFIX / lib / node (ทั่วโลก)
KirályIstván

โฟลเดอร์ node_modules โลคัลให้ความสำคัญกับโฟลเดอร์โกลบอลเสมอ!
KirályIstván

14

คุณสามารถใช้แพ็คเกจrequiregเพื่อแก้ไขปัญหานี้:

var forever = require('requireg')('forever')

จะทำเคล็ดลับ

นอกจากนี้ยังมีอีกโมดูลหนึ่งglobal-npmโดยเฉพาะกับการใช้ทั่วโลกnpmคุณสามารถดูรหัสย่อและดูว่าเทคนิคทำงานอย่างไร


น่าสนใจ แต่วิธี NODE_PATH อาจเป็นที่ยอมรับมากกว่านี้
Alexander Mills

ความสวยงามของNODE_PATHมันก็คือคุณไม่จำเป็นต้องเปลี่ยนรหัสใด ๆ (กรณีการใช้งานของฉันคือการให้คะแนนโครงการนักเรียนจำนวนมากซึ่งฉันไม่ต้องการเรียกใช้npm installสำหรับแต่ละโครงการและยังไม่ต้องการให้พวกเขามีnode_modulesไดเรกทอรี)
amenthes

ไม่มันจะไม่ทำเคล็ดลับเพราะคุณไม่ต้องการrequiregในตอนแรกนี่คือประเด็นทั้งหมด
thisismydesign

6

สำหรับยูทิลิตี้ CLI ที่ขึ้นอยู่กับโมดูลขนาดใหญ่เช่นpuppeteerฉันชอบที่จะวางไข่npm root -gและใช้มันเพื่อต้องการโมดูลระดับโลก

try {
  const root = require('child_process').execSync('npm root -g').toString().trim()
  var puppeteer = require(root + '/puppeteer')
} catch (err) {
  console.error(`Install puppeteer globally first with: npm install -g puppeteer`)
  process.exit(1)
}

3

คุณสามารถใส่บรรทัดนี้ใน.profileไฟล์ของคุณ:

ส่งออก NODE_PATH = "$ (npm config รับส่วนนำหน้า) / lib / node_modules"

สิ่งนี้จะทำให้การnodeใช้เส้นทางทั่วโลก


1
node_modulesฉบับนี้เป็นวิธีทั่วไปในการได้รับทั่วโลก นี่เป็นคำตอบเก่า แต่ฉันจำได้ว่าฉันได้จากที่ใดก็ได้ในเอกสาร อย่างไรก็ตามในเครื่องคอมพิวเตอร์ของฉัน (ในปี 2020) เดอะ NPM โลกไดเรกทอรีnode_modules usr/lib/node_modulesอย่างไรก็ตามผมเชื่อnpm config get prefixว่าเพราะมันถูกใช้ทั่วโลกโดย npm เมื่อใดก็ตามที่มีการติดตั้งแพกเกจทั่วโลกดังนั้นมันควรจะถูกต้อง
ลูอิสเปาโล

1
ไม่ว่าด้วยวิธีใด (ฉันไม่ได้พูดสิ่งนี้ในคำตอบเริ่มต้นของฉันเพราะฉันไม่ค่อยมีประสบการณ์ใน Node.JS) การใช้แพคเกจที่ติดตั้งทั่วโลกในโปรแกรมเป็นกรณีใช้งานที่ล้ำสมัยและไม่ควรทำเพราะในโครงการ ปัญหาที่เกิดขึ้นเมื่อใดก็ตามที่โครงการจะมุ่งมั่นที่จะ VCS และโคลนในสภาพแวดล้อมอื่นเนื่องจากว่าการพึ่งพาเฉพาะเจาะจงไม่ได้อยู่ในpackage.jsonไฟล์หรือใน/yarn.lock package-lock.json
ลูอิสเปาโล

1
Oh! ฉันเข้าใจแล้ว. ฉันเชื่อว่าคุณเข้าใจผิดว่า NODE_PATH ด้วย PATH PATH คือตำแหน่งที่เชลล์จะมองหาไฟล์เรียกทำงาน NODE_PATH คือตำแหน่งที่โหนดจะค้นหาแพ็คเกจ มันจะเริ่มต้นด้วยการดูที่ไดเรกทอรีปัจจุบันของnode_modulesโฟลเดอร์จากนั้นก็เป็นพาเรนต์แล้วก็เป็นพาเรนต์ ... จนกว่าจะพบnode_modulesโฟลเดอร์ที่มีโมดูลนั้น อย่างไรก็ตามหากคุณติดตั้งแพคเกจทั่วโลกจะไม่อยู่ในnode_modulesโฟลเดอร์ใด ๆเหนือไดเรกทอรีปัจจุบันของสคริปต์ดังนั้นคุณจึงใช้ NODE_PATH เป็นทางเลือกที่โหนดจะค้นหาแพ็คเกจ
ลูอิสเปาโล

1
ahahahah @Luis Paulo คุณพูดถูก !! ฉันขอโทษ! ฉันจะพยายามลบความคิดเห็นของฉันเพื่อป้องกันความสับสนงานที่ดีและขอบคุณ
Ryan Taylor

@Ryan Taylor คุณไม่ควรลบความคิดเห็นและคำถามเมื่อพวกเขาได้รับการแก้ไขเพราะคนอื่นสามารถมีเหมือนกัน ตอนนี้ดูเหมือนว่าฉันมีคนเดียวในความคิดเห็น! ahahahah
Luis Paulo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.