Определить корень проекта из запущенного приложения node.js

Есть ли лучший способ, чем process.cwd() определить корневой каталог запущенного процесса node.js? Что-то вроде эквивалента Rails.root , но для Node.js. Я ищу что-то такое же предсказуемое и надежное, насколько это возможно.

Есть несколько способов приблизиться к этому, каждый со своими плюсами и минусами:

require.main.filename

Из http://nodejs.org/api/modules.html :

Когда файл запускается непосредственно из узла, require.main устанавливается в его module . Это означает, что вы можете определить, был ли файл запущен напрямую путем тестирования require.main === module

Поскольку module предоставляет свойство filename (обычно эквивалентное __filename ), точку входа текущего приложения можно получить, установив require.main.filename .

Поэтому, если вам нужен базовый каталог для вашего приложения, вы можете сделать следующее:

 var path = require('path'); var appDir = path.dirname(require.main.filename); 

За и против

Это будет работать большую часть времени, но если вы запускаете приложение с помощью пусковой установки, например pm2 или выполняете тесты мокко , этот метод не удастся.

global.X

У узла есть глобальный объект пространства имен, называемый global – все, что вы прикрепляете к этому объекту, будет доступно в вашем приложении. Итак, в вашем index.js (или app.js или любом app.js вашего основного файла приложения) вы можете просто определить глобальную переменную:

 // index.js var path = require('path'); global.appRoot = path.resolve(__dirname); // lib/moduleA/component1.js require(appRoot + '/lib/moduleB/component2.js'); 

За и против

Работает последовательно, но вы должны полагаться на глобальную переменную, что означает, что вы не можете легко повторно использовать компоненты / и т. Д.

process.cwd ()

Это возвращает текущий рабочий каталог. Не является надежным вообще, поскольку он полностью зависит от того, из какого каталога был запущен процесс:

 $ cd /home/demo/ $ mkdir subdir $ echo "console.log(process.cwd());" > subdir/demo.js $ node subdir/demo.js /home/demo $ cd subdir $ node demo.js /home/demo/subdir 

Приложение-корневой путь

Чтобы решить эту проблему, я создал модуль узла, называемый корнем-корнем . Использование прост:

 var appRoot = require('app-root-path'); var myModule = require(appRoot + '/lib/my-module.js'); 

Модуль -корневой путь использует несколько разных методов для определения корневого пути приложения с учетом установленных на глобальном уровне модhive (например, если ваше приложение запущено в /var/www/ но модуль установлен в ~/.nvm/v0.xx/lib/node/ ). Он не будет работать в 100% случаев, но он будет работать в большинстве распространенных сценариев.

За и против

Работает без конфигурации в большинстве случаев. Также предоставляет некоторые дополнительные дополнительные методы удобства (см. Страницу проекта). Самым большим является то, что он не будет работать, если:

  • Вы используете пусковую установку, например pm2
  • И , модуль не установлен внутри вашего node_modules вашего приложения (например, если вы установили его по всему миру)

Вы можете обойти это, установив APP_ROOT_PATH окружения APP_ROOT_PATH или вызвав .setPath() в модуле, но в этом случае вам, вероятно, лучше использовать global метод.

Экологическая переменная NODE_PATH

Если вы ищете способ определить корневой путь для текущего приложения, одно из вышеуказанных решений, скорее всего, будет работать лучше всего для вас. Если, с другой стороны, вы пытаетесь решить проблему загрузки модhive приложения надежно, я настоятельно рекомендую посмотреть на переменную окружения NODE_PATH .

Система модhive узла ищет модули в различных местах. Одно из этих мест – это где бы то ни было process.env.NODE_PATH . Если вы установите эту переменную окружения, то вы можете require модули со стандартным загрузчиком модhive без каких-либо других изменений.

Например, если вы установили NODE_PATH в /var/www/lib , следующее будет работать нормально:

 require('module2/component.js'); // ^ looks for /var/www/lib/module2/component.js 

Отличный способ сделать это – использовать npm :

 "scripts": { "start": "NODE_PATH=. node app.js" } 

Теперь вы можете запустить приложение с npm start а вы – золотым. Я совмещаю это с моим модулем NODE_PATH -node-path , который предотвращает случайную загрузку приложения без установки NODE_PATH . Для еще большего контроля за соблюдением переменных окружения см. Checkenv .

Один из них: NODE_PATH должен быть установлен за пределами приложения-узла. Вы не можете сделать что-то вроде process.env.NODE_PATH = path.resolve(__dirname) потому что загрузчик модуля кэширует список каталогов, которые он будет выполнять до process.env.NODE_PATH = path.resolve(__dirname) вашего приложения.

[добавлен 4/6/16] Еще один очень перспективный модуль, который пытается решить эту проблему, волнистый .

__dirname не является глобальным; он локален для текущего модуля, поэтому каждый файл имеет свое локальное, другое значение.

Если вам нужен корневой каталог запущенного процесса, вы, вероятно, захотите использовать process.cwd() .

Если вы хотите предсказуемость и надежность, то, вероятно, вам необходимо сделать это требование вашего приложения, чтобы была установлена ​​определенная переменная среды. Ваше приложение ищет MY_APP_HOME (или что-то еще), и если оно есть, и приложение существует в этом каталоге, тогда все будет хорошо. Если он не определен или каталог не содержит ваше приложение, он должен выйти с ошибкой, предлагающей пользователю создать переменную. Он может быть установлен как часть процесса установки.

Вы можете читать переменные среды в узле с чем-то вроде process.env.MY_ENV_VARIABLE .

1- создать файл в корне проекта, вызвать его settings.js

2- внутри этого файла добавить этот код

 module.exports = { POST_MAX_SIZE : 40 , //MB UPLOAD_MAX_FILE_SIZE: 40, //MB PROJECT_DIR : __dirname }; 

3- внутри node_modules создать новое имя модуля, это «настройки» и внутри модуля index.js записать этот код:

 module.exports = require("../../settings"); 

4- и в любое время, когда вы хотите, чтобы ваш каталог проекта просто использовал

 var settings = require("settings"); settings.PROJECT_DIR; 

таким образом у вас будут все каталоги проектов относительно этого файла;)

самый простой способ получить глобальный корень ( если вы используете NPM для запуска приложения node.js «npm start» и т. д. ),

 var appRoot = process.env.PWD; 

Если вы хотите перекрестно проверить вышеуказанные

Предположим, вы хотите перекрестно проверить process.env.PWD с настройками приложения node.js. если вы хотите, чтобы некоторые тесты времени выполнения проверяли правильность process.env.PWD , вы можете перекрестно проверить его с помощью этого кода (который я написал, который, похоже, работает хорошо). Вы можете перекрестно проверить имя последней папки в appRoot с именем npm_package_ в файле package.json, например:

  var path = require('path'); var globalRoot = __dirname; //(you may have to do some substring processing if the first script you run is not in the project root, since __dirname refers to the directory that the file is in for which __dirname is called in.) //compare the last directory in the globalRoot path to the name of the project in your package.json file var folders = globalRoot.split(path.sep); var packageName = folders[folders.length-1]; var pwd = process.env.PWD; var npmPackageName = process.env.npm_package_name; if(packageName !== npmPackageName){ throw new Error('Failed check for runtime string equality between globalRoot-bottommost directory and npm_package_name.'); } if(globalRoot !== pwd){ throw new Error('Failed check for runtime string equality between globalRoot and process.env.PWD.'); } 

вы также можете использовать этот модуль NPM: require('app-root-path') который работает очень хорошо для этой цели

Я нашел, что это работает для меня последовательно, даже когда приложение вызывается из подпапки, как это может быть с некоторыми тестовыми фреймворками, такими как Mocha:

 process.mainModule.paths[0].split('node_modules')[0].slice(0, -1); 

Почему это работает:

На узле выполнения создается реестр полных путей для всех загруженных файлов. Сначала загружаются модули и, таким образом, в верхней части этого реестра. Выбрав первый элемент реестра и вернув путь до каталога «node_modules», мы можем определить корень приложения.

Это всего лишь одна строка кода, но для простоты (ради меня) я черным помещал ее в модуль NPM:

https://www.npmjs.com/package/node-root.pddivine

Наслаждайтесь!

Все эти «корневые директории» в основном должны решить какой-то виртуальный путь к реальному пути свай, так что, может быть, вы должны смотреть на path.resolve ?

 var path= require('path'); var filePath = path.resolve('our/virtual/path.ext"); 

Возможно, вы можете попробовать __filename вверх от __filename до __filename пор, пока не найдете package.json и не решите, что это главный каталог, к которому принадлежит ваш текущий файл.

Метод, который я нашел полезным при использовании express, заключается в том, чтобы добавить следующее в app.js до того, как будут установлены какие-либо другие маршруты

 // set rootPath app.use(function(req, res, next) { req.rootPath = __dirname; next(); }); app.use('/myroute', myRoute); 

Не нужно использовать глобальные переменные, и у вас есть путь к корневому каталогу как свойство объекта запроса.

Это работает, если ваш app.js находится в корне вашего проекта, который, по умолчанию, есть.

На самом деле, я нахожу, возможно, тривиальное решение также наиболее надежным: просто добавьте следующий файл в корневой каталог вашего проекта: root-path.js, который имеет следующий код:

import * as path from 'path' const projectRootPath = path.resolve(__dirname) export const rootPath = projectRootPath

Я использую это.

Для моего модуля с именем mymodule

var BASE_DIR = __dirname.replace(/^(.*\/mymodule)(.*)$/, '$1')

Создать функцию в app.js

/*Function to get the app root folder*/

 var appRootFolder = function(dir,level){ var arr = dir.split('\\'); arr.splice(arr.length - level,level); var rootFolder = arr.join('\\'); return rootFolder; } // view engine setup app.set('views', path.join(appRootFolder(__dirname,1),'views')); 

В верхней части основного файла добавьте:

 mainDir = __dirname; 

Затем используйте его в любом файле, который вам нужен:

 console.log('mainDir ' + mainDir); 
  • mainDir определяется глобально, если вам это нужно только в текущем файле – вместо этого используйте __dirname .
  • Основной файл обычно находится в корневой папке проекта и имеет имя main.js , index.js , gulpfile.js .

Сделайте его сексуальным 💃🏻.

 const users = require('../../../database/users'); // 👎 what you have // OR const users = require('$db/users'); // 👍 no matter how deep you are const products = require('/database/products'); // 👍 alias or pathing from root directory 

Три простых шага для решения проблемы уродливого пути.

  1. Установите пакет: npm install sexy-require --save
  2. Включите require('sexy-require') один раз в верхней части основного файла приложения.

     require('sexy-require'); const routers = require('/routers'); const api = require('$api'); ... 
  3. Необязательный шаг. Конфигурация пути может быть определена в файле .paths в корневой директории вашего проекта.

     $db = /server/database $api-v1 = /server/api/legacy $api-v2 = /server/api/v2 
 process.mainModule.paths .filter(p => !p.includes('node_modules')) .shift() 

Получите все пути в основных модулях и отфильтруйте их с помощью «node_modules», а затем получите первый из оставшихся списков путей. Неожиданное поведение не будет вызывать ошибку, просто undefined .

Хорошо работает для меня, даже при вызове ie $ mocha .

Вы можете просто добавить корневой путь каталога в переменной express-приложения и получить этот путь из приложения. Для этого добавьте app.set('rootDirectory', __dirname); в файле index.js или app.js. И используйте req.app.get('rootDirectory') для получения корневого каталога в вашем коде.

для получения имени текущего файла:

определите в этом файле:

     var get_stack = function () {
         var orig = Error.prepareStackTrace;
         Error.prepareStackTrace = function (_, stack) {
             стек возврата;
         };
         var err = new Ошибка;
         Error.captureStackTrace (err, arguments.callee);
         var stack = err.stack;
         Error.prepareStackTrace = orig;
         стек возврата;
     };

использование в этом файле:

     console.log (get_stack () [0] .getFileName ());

API:
Трассировки стека

Попробуйте path._makeLong('some_filename_on_root.js');

пример:

 cons path = require('path'); console.log(path._makeLong('some_filename_on_root.js'); 

Это вернет полный путь из корня вашего приложения-узла (то же самое положение package.json)

  • Как рисовать с помощью Mongoose в Node.js?
  • Экспресс следующая функция, для чего это действительно нужно?
  • Как заставить SSL / https в Express.js
  • Как создать streamи в nodejs
  • nodejs, как читать нажатия клавиш от stdin
  • Что такое Node.js 'Connect, Express и «промежуточное ПО»?
  • Узел: войдите в файл вместо консоли
  • Расширить объект Express Request с помощью TypScript
  • Node.js: Разница между req.query и req.params
  • Node.js - Mongoose - проверьте, существует ли коллекция
  • Загрузите модуль node.js из строки в памяти
  • Interesting Posts

    Каков наилучший способ прочитать весь файл в std :: string в C ++?

    Количество слов в строке Swift для вычисления количества слов

    Почему gridview: true используется и что это значит?

    Аутентификация пользователя в веб-интерфейсе ASP.NET

    NumLock совершенно бесполезен, и я хочу полностью отключить его в Linux

    В чем разница между шаблоном Singleton и статическим classом в Java?

    Готовый сервер для создания WebSockets в Java?

    Как конвертировать UTF-8 в US-Ascii в Java

    Как скопировать список коллекций Java

    Как получить параметры запроса для внутренней ссылки на страницу в JQuery Mobile

    Как сделать текст доски более понятным с помощью MATLAB?

    Android Gradle plugin 0.7.0: «дубликаты файлов при упаковке APK»

    Понимание ошибок ограничения значения F #

    Отсутствует опция «извлечения» на USB-накопителях в Windows 7?

    Невозможно создать JDBC-драйвер classа ” для подключения URL-адреса ‘null’: я не понимаю это исключение

    Давайте будем гением компьютера.