NodeJS yêu cầu một mô-đun / gói toàn cầu


158

Tôi đang cố gắng cài đặt trên toàn cầu và sau đó sử dụng foreverforever-monitornhư thế này:

npm install -g forever forever-monitor

Tôi thấy đầu ra thông thường và cả các hoạt động sao chép các tệp vào đường dẫn chung, nhưng sau đó nếu tôi cố gắng require("forever");tôi gặp lỗi nói rằng mô-đun không được tìm thấy.

Tôi đang sử dụng phiên bản mới nhất của cả nút và npm và tôi đã biết về sự thay đổi mà npm thực hiện trong cài đặt toàn cầu so với cài đặt cục bộ, nhưng tôi thực sự không muốn cài đặt cục bộ trên mọi dự án và tôi đang làm việc trên nền tảng không Không hỗ trợ linknên npm linksau khi cài đặt toàn cầu là không thể đối với tôi.

Câu hỏi của tôi là: tại sao tôi không thể yêu cầu gói cài đặt toàn cầu? Đó là một tính năng hay một lỗi? Hay tôi đang làm gì đó sai?

PS: Chỉ để làm cho nó rõ ràng: Tôi không muốn cài đặt cục bộ.




vì vậy nó ~/.config/yarn/globaldành cho sợi
localhostdotdev

Câu trả lời:


215

Trong Node.js, yêu cầu không tìm trong thư mục nơi các mô-đun toàn cầu được cài đặt.

Bạn có thể khắc phục điều này bằng cách đặt biến môi trường NODE_PATH. Trong Linux, điều này sẽ là:

export NODE_PATH=/usr/lib/node_modules

Lưu ý: Điều này phụ thuộc vào nơi các mô-đun toàn cầu của bạn thực sự được cài đặt.

Xem: Tải từ các thư mục toàn cầu .


24
Trên máy Ubuntu 13.10 của tôi, đường dẫn toàn cầu cho các mô-đun khác với bạn hiển thị ở đây. Tôi đã phải sử dụng export NODE_PATH=/usr/local/lib/node_modulesthay thế.
Drew Noakes

11
Nếu bạn đang sử dụng Windows 7/8 và chưa ghi đè bất kỳ cài đặt mặc định nào của Node, hãy đặt NODE_PATHbiến môi trường thành C:\Users\{USERNAME}\AppData\Roaming\npm\node_modulescó thể sẽ hoạt động.
Wes Johnson

5
@WesJohnson Chỉ %AppData%\npm\node_modulessẽ hoạt động trên Windows 10.
theblang

6
Nếu tôi đặt tôi NODE_PATHcó thể sử dụng đồng thời các mô-đun toàn cầu và cục bộ không?
Paulo Oliveira

6
Thay vào đó, thay vì đường dẫn tĩnh, tức là nếu bạn đang sử dụng NVM:NODE_PATH=$(npm root -g)
holmberd

96

Sau khi bạn cài đặt gói trên toàn cầu, bạn phải liên kết dự án địa phương với gói toàn cầu

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

Xem tại đây


2
Tôi đang chạy trên một nền tảng không hỗ trợ liên kết (như câu hỏi của tôi) blog.nodejs.org/2011/04/06/npm-1-0-link
alexandernst

1
bạn đang sử dụng nền tảng nào?
dùng568109

1
Tôi thực sự không muốn gây rối với liên kết (cũng không phải liên kết tượng trưng). Tôi chỉ muốn cài đặt các gói trên toàn cầu và yêu cầu chúng. Tôi biết NPM được thiết kế lại để tránh điều này, nhưng làm thế nào khó để đạt được thứ gì đó như thế này?
alexandernst

13
Nếu tôi không có dự án thì sao? Nói ~/some-stand-alone-random-nodejs-test.js. Tôi không muốn biến thư mục nhà của tôi thành một thư mục dự án. Tôi không muốn tạo các thư mục mới cho mọi thử nghiệm nhỏ.
AnnanFay

1
Hoạt động hoàn hảo trên Windows 8.1. Từ dòng lệnh nút cd đến thư mục node_modules cục bộ của dự án của tôi sau đó được thực thi npm link <module>Sau đó, bạn sẽ thấy một lối tắt (liên kết) được tạo trong thư mục node_module của dự án của bạn tham chiếu mô-đun nút chung.
Dynamiclynk

26

Xin lỗi về sự cần thiết nhưng tôi có thể chỉ định các đường dẫn được mã hóa cứng cho các mô-đun được cài đặt trên toàn cầu:

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

Điều này không hoàn hảo nhưng xem xét rằng Unity3d cố gắng "biên dịch" tất cả các javascript có trong thư mục dự án Tôi thực sự không thể cài đặt bất kỳ gói nào.


4
Unity3D không hỗ trợ JavaScript. Nó hỗ trợ cú pháp giống như JS cho trình biên dịch / trình biên dịch Boo của nó (Boo là ngôn ngữ giống như Python cho .NET) , được tiếp thị một cách giả tạo dưới dạng JavaScript JavaScript . Tên chính xác hơn cho ngôn ngữ mà Unity hỗ trợ là UnityScript . Bởi vì nó thậm chí không gần với cùng một ngôn ngữ, bên cạnh không có bất kỳ JS nào được viết cho web hoặc cho Node.js sẽ hoạt động trong Unity. Nhiều thông tin hơn về sự khác biệt trên wiki Unity chính thức: wiki.unity3d.com/index.php/UnityScript_versus_JavaScript
Slipp D. Thompson

19

Tôi biết đây là một câu hỏi cũ, nhưng tôi đã gặp phải vấn đề này khi cố gắng thực hiện một số phiên bản kiểm tra bằng cách sử dụng semvermột preinstalltập lệnh trong package.json. Vì tôi biết tôi không thể phụ thuộc vào bất kỳ mô-đun cục bộ nào được cài đặt, tôi đã sử dụng điều này để yêu cầu semvertừ node_modulesthư mục toàn cầu ( npmtùy thuộc vào nó tôi biết nó ở đó):

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);
}

Tôi thích cách tiếp cận này vì nó không yêu cầu cài đặt bất kỳ mô-đun đặc biệt nào để sử dụng.

Tôi đã không đi với một NODE_PATHgiải pháp như những người khác đã đề xuất vì tôi muốn làm cho nó hoạt động trên máy của bất kỳ ai, mà không phải yêu cầu cấu hình / thiết lập bổ sung trước khi chạy npm installcho dự án của tôi.

Cách thức này được mã hóa, nó chỉ được đảm bảo để tìm các mô-đun cấp cao nhất (được cài đặt bằng cách sử dụng npm install -g ...) hoặc các mô-đun được yêu cầu bởi npm(được liệt kê dependenciestại đây: https://github.com/npm/npm/blob/master/package.json ). Nếu bạn đang sử dụng phiên bản NPM mới hơn, nó có thể tìm thấy sự phụ thuộc của các gói được cài đặt toàn cầu khác vì hiện tại có cấu trúc phẳng hơn cho node_modulescác thư mục.

Hy vọng điều này hữu ích cho ai đó.


19

Theo tài liệu , Node.js sẽ tìm kiếm theo các vị trí sau theo mặc định:

  1. Đường dẫn quy định trong NODE_PATHbiến môi trường .

    Lưu ý: NODE_PATHbiến môi trường được đặt thành danh sách đường dẫn tuyệt đối được phân cách bằng dấu hai chấm.

  2. node_modulesThư mục hiện tại . (địa phương)

  3. $HOME/.node_modules (toàn cầu)

    Lưu ý: $HOMElà thư mục nhà của người dùng.

  4. $HOME/.node_libraries (toàn cầu)
  5. $PREFIX/lib/node (toàn cầu)

    Lưu ý: $PREFIXlà Node.js của cấu hình node_prefix.

    Để kiểm tra giá trị hiện tại của node_prefix, hãy chạy:

    node -p process.config.variables.node_prefix

    Lưu ý: Tiền tố tương ứng với --prefixparam trong quá trình xây dựng và nó liên quan đến process.execPath. Không nhầm lẫn với giá trị từ npm config get prefixlệnh. nguồn

Nếu không thể tìm thấy mô-đun đã cho, điều đó có nghĩa là nó không có ở một trong các vị trí trên.

Vị trí của thư mục gốc toàn cầu nơi các mô-đun được cài đặt có thể được in bằng cách: npm root -g(theo mặc định, đường dẫn được tính vào thời gian chạy trừ khi bị ghi đè trong npmrctệp ).

Giải pháp

Bạn có thể thử các cách giải quyết sau:

  • Chỉ định vị trí mô-đun toàn cầu của bạn trong NODE_PATHbiến môi trường. Ví dụ

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

    Để kiểm tra và in giá trị của NODE_PATH, hãy chạy:

    echo 'console.log(process.env.NODE_PATH); require("forever")' | NODE_PATH="$(npm root -g):$NODE_PATH" node 
  • Để có giải pháp lâu dài hơn, hãy liên kết $HOME/.node_modulesthư mục người dùng toàn cầu của bạn để trỏ đến thư mục gốc, bằng cách chạy lệnh này:

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

    Sau đó kiểm tra lại thông qua: echo 'require("forever")' | nodelệnh.

  • Tạm thời thay đổi thư mục hiện tại thành nơi tiện ích mở rộng đã được cài đặt trên toàn cầu, trước khi gọi tập lệnh. Ví dụ

    npm install -g forever
    cd "$(npm root -g)"
    echo 'require("forever")' | node
    cd -
    
  • Định cấu hình đích cài đặt toàn cục trong npmtệp userconfig (xem npm help 5 npmrc:) hoặc bởi userconfigparam ( --prefix).

    Để hiển thị cấu hình hiện tại, hãy chạy : npm config list.

    Để chỉnh sửa cấu hình hiện tại, hãy chạy : npm config edit.

  • Chỉ định đường dẫn đầy đủ của vị trí mô-đun nút khi gọi require(). Ví dụ

    require("/path/to/sub/module")
  • Cài đặt gói đến vị trí tùy chỉnh, ví dụ:

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

    Tuy nhiên, cài đặt sẽ đi theo ~/.node_modules/lib/node_modules/, vì vậy vị trí vẫn cần phải được thêm vào.

    Xem: npm gói cài đặt cục bộ đến vị trí tùy chỉnh

  • Tạo một liên kết tượng trưng trong thư mục hiện tại từ vị trí của gói toàn cầu. Ví dụ

    npm link forever

Nó trông giống như 4. Thư mục node_modules hiện tại. (cục bộ) được ưu tiên hơn 3. $ PREFIX / lib / nút (toàn cầu)
Király István

Các thư mục node_modules cục bộ luôn được ưu tiên hơn các thư mục toàn cầu!
Király István

14

Bạn có thể sử dụng gói requiregđể giải quyết vấn đề này:

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

sẽ thực hiện các mẹo.

Ngoài ra, có một mô-đun khác global-npm, trong khi cụ thể chỉ sử dụng toàn cầu npm, bạn có thể xem mã ngắn và xem kỹ thuật này hoạt động như thế nào.


thú vị, nhưng phương pháp NODE_PATH có lẽ hợp quy tắc hơn
Alexander Mills

cái hay của NODE_PATHnó là, bạn không cần thay đổi bất kỳ mã nào. (trường hợp sử dụng của tôi đang chấm điểm rất nhiều dự án của sinh viên, nơi tôi không muốn chạy npm installcho từng dự án và cũng không muốn họ cung cấp node_modulesthư mục).
amenthes

Không, nó sẽ không thực hiện được mánh khóe vì bạn không thể yêu cầu requiregngay từ đầu, đây là toàn bộ vấn đề.
thisismydesign

6

Đối với các tiện ích CLI phụ thuộc vào các mô-đun lớn, như puppeteer, tôi muốn sinh ra một npm root -gvà sử dụng nó để yêu cầu mô-đun toàn cầu.

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

Bạn có thể đặt dòng này trong .profiletập tin của bạn :

xuất NODE_PATH = "$ (cấu hình npm lấy tiền tố) / lib / node_modules"

Điều này sẽ làm cho nodeviệc sử dụng con đường toàn cầu.


1
Không. Đây là cách chung để có được toàn cầu node_modules. Đây là một câu trả lời cũ nhưng tôi nhớ rằng tôi đã nhận được nó từ bất cứ nơi nào trong tài liệu. Dù sao, trong máy tính của tôi (năm 2020) node_modulesthư mục npm toàn cầu là usr/lib/node_modules. Dù sao, tôi tin tưởng npm config get prefixbởi vì nó được sử dụng trên toàn cầu vào lúc npm bất cứ khi nào một gói toàn cầu được cài đặt vì vậy nó sẽ đúng.
Luis Paulo

1
Dù bằng cách nào (tôi đã không nói điều này trong câu trả lời ban đầu của mình vì tôi không có kinh nghiệm về Node.JS), sử dụng các gói được cài đặt toàn cầu trong một chương trình là trường hợp sử dụng cạnh và hiếm khi được thực hiện vì trong một dự án, nó sẽ tạo ra các vấn đề bất cứ khi nào dự án được cam kết với VCS và được nhân bản trong một môi trường khác do sự phụ thuộc cụ thể đó không có trong package.jsontệp hoặc trong yarn.lock/ package-lock.json.
Luis Paulo

1
Oh! Giờ thì tôi đã hiểu. Tôi tin rằng bạn đang nhầm lẫn NODE_PATH với PATH. PATH là nơi một shell sẽ tìm kiếm các tệp thực thi. NODE_PATH là nơi nút sẽ tìm kiếm các gói. Nó sẽ bắt đầu bằng cách xem node_modulesthư mục hiện tại cho một thư mục, sau đó là cha mẹ, sau đó là cha mẹ, ... cho đến khi tìm thấy node_modulesthư mục chứa mô-đun đó. Tuy nhiên, nếu bạn cài đặt một gói trên toàn cầu, nó sẽ không nằm trong bất kỳ node_modulesthư mục nào phía trên thư mục hiện tại của tập lệnh để bạn sử dụng NODE_PATH làm dự phòng nơi nút sẽ tìm kiếm các gói.
Luis Paulo

1
ahahahah @Luis Paulo bạn hoàn toàn đúng !! Tôi xin lỗi! Tôi sẽ thử và xóa một số bình luận của tôi để tránh nhầm lẫn, công việc tốt và cảm ơn bạn
Ryan Taylor

@Ryan Taylor Bạn không nên xóa bình luận và câu hỏi một khi chúng được giải quyết vì người khác có thể có cùng ý kiến. Bây giờ có vẻ như tôi đã độc thoại trong các bình luận! ahahahah
Luis Paulo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.