Çalışan bir node.js uygulamasından proje kökünü belirleme


315

process.cwd()Çalışan bir node.js işleminin kök dizinini belirlemekten daha iyi bir yol var mı ? Eşdeğeri gibi bir şey Rails.root, ancak Node.js için. Mümkün olduğunca öngörülebilir ve güvenilir bir şey arıyorum.


1
Kabul edilen yanlış yanıtı kabul etme şansın var mı?
Dave Newton

9
dene process.env.PWD... aşağıdaki cevabımı gör.
Alexander Mills

Yanıtlar:


624

Buna yaklaşmanın birkaç yolu vardır, her birinin kendi artıları ve eksileri vardır:

require.main.filename

Gönderen http://nodejs.org/api/modules.html :

Bir dosya doğrudan Düğümden çalıştırıldığında, require.mainonun olarak ayarlanır module. Bu, bir dosyanın test edilerek doğrudan çalıştırılıp çalıştırılmadığını belirleyebileceğiniz anlamına gelirrequire.main === module

Çünkü modulebir sağlar filenameözelliği (normal eşdeğer __filename), o andaki uygulamanın giriş noktası kontrol edilmesiyle elde edilebilir require.main.filename.

Uygulamanız için temel dizini istiyorsanız, şunları yapabilirsiniz:

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

Artılar ve eksiler

Bu çoğu zaman harika sonuç verir, ancak uygulamanızı pm2 gibi bir başlatıcıyla çalıştırıyorsanız veya mocha testleri çalıştırıyorsanız , bu yöntem başarısız olur.

global.X

Düğüm adında genel bir ad alanı nesnesi vardır global- bu nesneye eklediğiniz her şey uygulamanızın her yerinde kullanılabilir olacaktır. Bu nedenle, index.js(veya app.jsana uygulama dosyanızın adı ne olursa olsun) bir global değişken tanımlayabilirsiniz:

// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);

// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');

Artılar ve eksiler

Tutarlı bir şekilde çalışır ancak global bir değişkene güvenmeniz gerekir, bu da bileşenleri / vb. Kolayca yeniden kullanamayacağınız anlamına gelir.

process.cwd ()

Bu, geçerli çalışma dizinini döndürür. O süreç başlatıldı hangi dizin tamamen bağlıdır yöntem olduğu hiç değil güvenilir dan :

$ 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

app-kök-yolu

Bu sorunu çözmek için app-root-path adlı bir düğüm modülü oluşturdum . Kullanımı basit:

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

App-kök yolu modülü uygulama içinde çalışıyorsa, örneğin (hesaba küresel yüklü modülleri alarak uygulamanın kök yolunu belirlemek için birkaç farklı teknikler kullanan /var/www/ancak modül yüklü~/.nvm/v0.x.x/lib/node/ ). Zamanın% 100'ü çalışmaz, ancak çoğu yaygın senaryoda çalışacaktır.

Artılar ve eksiler

Çoğu durumda konfigürasyon olmadan çalışır. Ayrıca bazı hoş ek kolaylık yöntemleri sağlar (proje sayfasına bakınız). En büyük con, şu durumlarda işe yaramayacağıdır:

  • PM2 gibi bir başlatıcı kullanıyorsunuz
  • VE , modül uygulamanızın node_modulesdizinine yüklenmez (örneğin, global olarak yüklediyseniz)

APP_ROOT_PATHÇevresel bir değişken belirleyerek veya .setPath()modülü arayarak bu sorunu çözebilirsiniz , ancak bu durumda, muhtemelenglobal yöntemi .

NODE_PATH çevresel değişken

Mevcut uygulamanın kök yolunu belirlemenin bir yolunu arıyorsanız , yukarıdaki çözümlerden birinin sizin için en iyi sonucu vermesi muhtemeldir. Öte yandan, uygulama modüllerini güvenilir bir şekilde yükleme sorununu çözmeye çalışıyorsanız, NODE_PATHçevresel değişkene bakmanızı şiddetle tavsiye ederim .

Düğümün Modüller sistemi çeşitli konumlardaki modülleri arar. Bu konumlardan biri nereye process.env.NODE_PATHişaret ediyorsa odur . Bu çevresel değişkeni ayarlarsanız require, standart modül yükleyicili modülleri başka bir değişiklik yapmadan yapabilirsiniz.

Örneğin, ayarlarsanız NODE_PATHiçin /var/www/libaşağıdaki iyi çalışacak:

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

Bunu yapmanın harika bir yolu npm:

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

Şimdi uygulamanızı başlatabilirsiniz npm startve siz de altınsınız. Bunu , uygulama ayarlanmadan yanlışlıkla yüklenmesini önleyen zorlama düğümü yol modülümle birleştiriyorum NODE_PATH. Çevresel değişkenlerin uygulanması üzerinde daha fazla kontrol için bkz. Checkenv .

Bir yakaladım: NODE_PATH zorundadır set olmak dışında düğümü uygulamasının. Gibi bir şey yapamazsınprocess.env.NODE_PATH = path.resolve(__dirname)Modül yükleyici, uygulamanız çalışmadan önce arayacağı dizinlerin listesini önbelleğe aldığı için .

[eklenen 4/6/16] Bu sorunu çözmeye çalışan gerçekten umut vaat eden başka bir modül dalgalı .


1
@ Kevin bu durumda, mocha uygulamanızın giriş noktasıdır. Bu sadece "proje kökünü" bulmanın neden bu kadar zor olduğuna bir örnektir - duruma ve "proje kökü" ile ne demek istediğinize çok bağlıdır.
inxilpro

1
@Kevin Tamamen anlıyorum. Demek istediğim, "proje kökü" kavramının bir insan için anlaması bir bilgisayardan çok daha kolay olmasıdır . Kusursuz bir yöntem istiyorsanız, yapılandırmanız gerekir. Kullanmak çoğu zaman işe yarar , ama her zaman işe yaramaz . require.main.filename
inxilpro

2
Teğetsel olarak ilgili: Bu, Düğüm projenizi düzenlemenin inanılmaz derecede akıllı bir yoludur, böylece bu sorun hakkında çok endişelenmenize gerek kalmaz
inxilpro

1
PM2'de bir değişiklik veya Node.js ile bir değişiklik olup olmadığını bilmiyorum ama pm2 require.main.filenameile çalışıyor gibi görünüyor. Mocha hakkında bilmiyorum.
Justin Warkentin

8
path.parse(process.mainModule.filename).dir
Cory Robinson

53

__dirnameküresel değil; her modül kendi yerel, farklı değerine sahiptir.

Çalışan işlemin kök dizinini istiyorsanız, muhtemelen kullanmak istersiniz process.cwd().

Öngörülebilirlik ve güvenilirlik istiyorsanız, muhtemelen uygulamanız için belirli bir ortam değişkeninin ayarlanmış olması gerekir. Uygulamanız arar MY_APP_HOME(ya da her neyse) ve eğer oradaysa ve uygulama bu dizinde mevcutsa, o zaman her şey yolunda demektir. Tanımlanmamışsa veya dizin uygulamanızı içermiyorsa, kullanıcıdan değişkeni oluşturmasını isteyen bir hata ile çıkmalıdır. Bir yükleme işleminin parçası olarak ayarlanabilir.

Düğümdeki ortam değişkenlerini benzer bir şeyle okuyabilirsiniz process.env.MY_ENV_VARIABLE.


2
Dikkatli kullanılırsa, bu oldukça iyi çalışabilir. Ama bin/server.jsvs yaparken farklı sonuçlar verir cd bin && server.js. (bu js dosyalarının yürütülebilir olarak işaretlendiğini varsayarsak)
Myrne Stol

1
Kullanılması process.cwd()mocha testler bile, benim için bir cazibe gibi çalıştı. Teşekkür ederim!
Diogo Eichert

49

1- proje kök çağrısında bir dosya oluşturmak settings.js

2- Bu dosyanın içine bu kodu ekleyin

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

3- node_modules içinde yeni bir modül adı "ayarları" oluşturun ve index.js modülünün içine şu kodu yazın:

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

4- ve istediğiniz zaman proje dizininizi kullanın

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

bu şekilde bu dosyaya göre tüm proje dizinlerine sahip olacaksınız;)


33
-1: Ayarlar dosyasını yüklemek için bir yola ihtiyacınız var, o zaman bu dosyaya referans yolu almak için? Hiçbir şey
çözmüyor

2
İncelemek ve düzenlemek için zaman ayırdığınız için oy verildi. Hala kırılgan hissediyor, ama bunun için daha iyi bir yol olmadığı için olabilir
goliatone

8
Kullanıcıların bu yaklaşımla akılda tutmak isteyecekleri bir şey node_modules, genellikle sürüm kontrolünün dışında tutulmasıdır. Bu nedenle, bir ekiple çalışıyorsanız veya deponuzu klonlamanız gerekiyorsa, bu ayarlar dosyasını senkronize tutmak için başka bir çözüm bulmanız gerekir.
Travesty3

@ Travesty3 ayarlar modülü aslında proje kökündeki bir dosyanın içeriğini dışa
aktaran

@goliatone Onun çözümü ile yolunu bilmeden dosyayı her yerden alabilirsiniz, bilmeniz gereken tek şey "ayarlar". Bu olmadan, proje dizinine ulaşıncaya kadar kaç klasörden geri çekileceğini açıkça bilmeniz gerekir. Düğüm otomatik olarak düğüm_modüllerini aradığı ve her zaman bunun nerede olduğunu bildiği için çalışır.

26

global root almanın en kolay yolu ( node.js uygulamanızı 'npm start' vb. çalıştırmak için NPM kullandığınızı varsayarsak )

var appRoot = process.env.PWD;

Yukarıdakileri çapraz doğrulamak istiyorsanız

Diyelim ki process.env.PWDnode.js uygulamanızın ayarlarını kontrol etmek istiyorsunuz. bazı çalışma zamanı testlerinin geçerliliğini kontrol etmesini process.env.PWDistiyorsanız, bu kodla (hangi iyi çalışıyor gibi yazdım) çapraz kontrol edebilirsiniz. AppRoot'taki son klasörün adını package.json dosyanızdaki npm_package_name ile çapraz kontrol edebilirsiniz, örneğin:

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

bu NPM modülünü de kullanabilirsiniz: require('app-root-path')bu amaç için çok iyi çalışır


5
Bu, (çoğu) unix sistemlerde harika çalışıyor. Npm modülünüzün / uygulamanızın Windows üzerinde çalışmasını istediğiniz PWDanda tanımsızdır ve bu başarısız olur.
Jeremy Wiebe

1
process.cwd()
Muhammed Umer

@MuhammadUmer neden process.cwd()her zaman proje kökü ile aynı olurdu ?
Alexander Mills

kök dosyada çağırırsanız, o zaman olurdu
Muhammed Umer

14

Mocha gibi bazı test çerçeveleriyle olabileceği gibi, uygulama bir alt klasörden çağrıldığında bile bu benim için tutarlı bir şekilde çalıştığını gördüm:

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

Neden çalışıyor:

Çalışma zamanında düğüm, yüklenen tüm dosyaların tam yollarını içeren bir kayıt defteri oluşturur. Modüller önce yüklenir ve bu nedenle bu kayıt defterinin en üstüne yüklenir. Kayıt defterinin ilk öğesini seçerek ve 'node_modules' dizininden önceki yolu döndürerek uygulamanın kökünü belirleyebiliriz.

Sadece bir kod satırı, ama basitlik uğruna (benim uğrum), bunu bir NPM modülüne kara kutuya koydum:

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

Zevk almak!


1
process.mainModule kullanımdan beri: v14.0.0 - require.main.paths[0].split('node_modules')[0].slice(0, -1);bunun yerine kullanın.
RobC

10

Tüm bu "kök dirs" çoğunlukla gerçek bir yığın yolu için bazı sanal yolu çözmek gerekir, bu yüzden bakmak gerekir olabilir path.resolve?

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

9

Bu satırı modülünüze root olarak eklemek kadar basit, genellikle app.js

global.__basedir = __dirname;

Daha sonra _basedir tüm modüllerinize erişilebilir olacaktır.


8

Belki bir __filenamebulana kadar yukarı doğru hareket etmeyi deneyebilir package.jsonve mevcut dosyanızın ait olduğu ana dizin olduğuna karar verebilirsiniz.


7

Aslında, belki de en önemsiz çözümü de en sağlam bulmak: sadece aşağıdaki dosyayı projenizin kök dizinine yerleştirin: aşağıdaki kodu olan root-path.js:

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

4

Express kullanırken yararlı bulduğum bir teknik, diğer rotalarınızdan herhangi biri ayarlanmadan önce aşağıdakileri app.js dosyasına eklemektir.

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

app.use('/myroute', myRoute);

Globalleri kullanmanıza gerek yoktur ve istek nesnesinin bir özelliği olarak kök dizininin yoluna sahipsiniz.

Bu, app.js dosyanız varsayılan olarak projenizin kökündeyse çalışır.


4

Bunu ana uygulama dosyanızın başına doğru bir yere ekleyin (örn. App.js):

global.__basedir = __dirname;

Bu, her zaman uygulamanızın temel dizinine eşdeğer olacak global bir değişken belirler. Diğer değişkenler gibi kullanın:

const yourModule = require(__basedir + '/path/to/module.js');

Basit...



3

INIT_CWDÜzerinde bir mülk var process.env. Projemde şu anda birlikte çalışıyorum.

const {INIT_CWD} = process.env; // process.env.INIT_CWD 
const paths = require(`${INIT_CWD}/config/paths`);

İyi şanslar...


1
Sonradan yükleme adımı olarak çağrıldığı projeyi manipüle eden bir paket için bir cazibe gibi çalıştı. Bununla birlikte, bir projenin paketimi kullanan bir bağımlılık kullandığı başka bir bağımlılık katmanında henüz test etmedim.
JamesDev

1
@JamesDev, INIT_CWDgerçekleştirildiği directoryyerden giderir npm-script.
Akash

2

çalışan bir node.js uygulamasından proje kökünü belirlemek istiyorsanız, bunu da yapabilirsiniz.

process.mainModule.path

1

Ana dosyanın üstüne şunu ekleyin:

mainDir = __dirname;

Sonra ihtiyacınız olan herhangi bir dosyada kullanın:

console.log('mainDir ' + mainDir);
  • mainDiryalnızca geçerli dosyada ihtiyacınız varsa global olarak tanımlanır - __dirnamebunun yerine kullanın.
  • Ana dosya projenin kök klasöründe genellikle ve benzeri adlandırılır main.js, index.js, gulpfile.js.

1

Bunu kullanıyorum.

Adlı modülüm için mymodule

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


1

Seksi olun 💃🏻.

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


Çirkin yol sorununu çözmek için üç basit adım.

  1. Paketi yükleyin: npm install sexy-require --save
  2. require('sexy-require')Ana uygulama dosyanızın üstüne bir kez ekleyin .

    require('sexy-require');
    const routers = require('/routers');
    const api = require('$api');
    ...
  3. İsteğe bağlı adım. Yol yapılandırması .pathsprojenizin kök dizinindeki dosyada tanımlanabilir .

    $db = /server/database
    $api-v1 = /server/api/legacy
    $api-v2 = /server/api/v2

İyi görünüyor, çok kötü, çok saçma bir isme sahipti.
JHH

@JHH şey ... Daha iyi bir isim bulmak zorunda kaldım
Sultan

1

Bu, dizin ağacını node_modules, genellikle proje kökünüzü gösteren bir dizin içerene kadar aşağı çeker:

const fs = require('fs')
const path = require('path')

function getProjectRoot(currentDir = __dirname.split(path.sep)) {
  if (!currentDir.length) {
    throw Error('Could not find project root.')
  }
  const nodeModulesPath = currentDir.concat(['node_modules']).join(path.sep)
  if (fs.existsSync(nodeModulesPath) && !currentDir.includes('node_modules')) {
    return currentDir.join(path.sep)
  }
  return this.getProjectRoot(currentDir.slice(0, -1))
}

Ayrıca node_modules, iç içe bir paket yüklemesinde yer aldığından, döndürülen yolda hiç olmadığından emin olur .


1

process.mainModuleolduğu kaldırılan v 14.0.0 beri. Cevaba atıfta bulunurken, lütfen kullanın require.main , gerisi hala tutar.

process.mainModule.paths
  .filter(p => !p.includes('node_modules'))
  .shift()

Ana modüllerdeki tüm yolları alın ve "node_modules" olanları filtreleyin, ardından kalan yol listesinin ilkini alın. Beklenmeyen davranışlar hata atmaz, sadeceundefined .

Yani aradığımda bile benim için iyi çalışıyor $ mocha .


0

App.js'de bir işlev oluşturun

/*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'));

0

Basitçe, ekspres uygulama değişkenine kök dizin yolunu ekleyebilir ve bu yolu uygulamadan alabilirsiniz. Bunun app.set('rootDirectory', __dirname);için index.js veya app.js dosyanızı ekleyin . req.app.get('rootDirectory')Kodunuzda kök dizin yolunu almak için kullanın .


0

Eski soru, biliyorum, ancak kullanmak için herhangi bir soru söz progress.argv. Argv dizisi, düğüm tarafından yürütülecek parametre olarak kullanılan bir tam yol adı ve dosya adı (.js uzantısıyla veya uzantısız) içerir. Bu da bayrak içerebileceğinden, bunu filtrelemeniz gerekir.

Bu doğrudan kullanabileceğiniz bir örnek değil (kendi çerçevemi kullandığım için), ancak bunun nasıl yapılacağı hakkında size bir fikir verdiğini düşünüyorum. Ayrıca, özellikle bir uzantı belirtildiğinde (ve bir dosya var denetimi gerekli olduğunda), bu işlevi çağırmanın sistemi çok fazla vurgulamasını önlemek için bir önbellek yöntemi kullanın:

node myfile

veya

node myfile.js

Bu yüzden önbelleğe almamın yanı sıra aşağıdaki koda da bakınız.


function getRootFilePath()
{
        if( !isDefined( oData.SU_ROOT_FILE_PATH ) )
        {
            var sExt = false;

            each( process.argv, function( i, v )
            {
                 // Skip invalid and provided command line options
                if( !!v && isValidString( v ) && v[0] !== '-' )
                {
                    sExt = getFileExt( v );

                    if( ( sExt === 'js' ) || ( sExt === '' && fileExists( v+'.js' )) )
                    {

                        var a = uniformPath( v ).split("/"); 

                         // Chop off last string, filename
                        a[a.length-1]='';

                         // Cache it so we don't have to do it again.
                        oData.SU_ROOT_FILE_PATH=a.join("/"); 

                         // Found, skip loop
                        return true;
                    }
                }
            }, true ); // <-- true is: each in reverse order
        }

        return oData.SU_ROOT_FILE_PATH || '';
    }
}; 

0

Bir elektron uygulamasının kök yolunu bulmak zor olabilir. Çünkü kök yolu, üretim, geliştirme ve paketlenmiş koşullar gibi farklı koşullar altında ana işlem ve oluşturucu için farklıdır.

Bir elektron uygulamasının kök yolunu yakalamak için bir npm paketi elektron-kök-yolu yazdım .

$ npm install electron-root-path

or 

$ yarn add electron-root-path


// Import ES6 way
import { rootPath } from 'electron-root-path';

// Import ES2015 way
const rootPath = require('electron-root-path').rootPath;

// e.g:
// read a file in the root
const location = path.join(rootPath, 'package.json');
const pkgInfo = fs.readFileSync(location, { encoding: 'utf8' });

0

Bu yapacaktır:

path.join(...process.argv[1].split(/\/|\\/).slice(0, -1))


0

önsöz

Bu çok eski bir soru ama 2012'de olduğu gibi hala 2020'de sinire çarpıyor gibi görünüyor. Diğer tüm cevapları kontrol ettim ve bir teknik bulamadım (bunun sınırlamaları olduğunu unutmayın, ancak diğerlerinin hepsi değil her durumda uygulanabilir).

GIT + alt süreci

Sürüm kontrol sisteminiz olarak GIT kullanıyorsanız, proje kökünü belirleme sorunu azaltılabilir (bu da projenin uygun kökünü düşünürüm - sonuçta, VCS'nizin mümkün olan en iyi görünürlük kapsamına sahip olmasını istersiniz) :

depo kök yolunu alma

Bunu yapmak için bir CLI komutu çalıştırmanız gerektiğinden, bir alt süreç oluşturmamız gerekecektir. Ayrıca, proje kökünün çalışma zamanı ortasında değişme olasılığı düşük olduğundan child_process, başlangıçta modül API'lerinin senkronize sürümünü kullanabiliriz .

spawnSync()İş için en uygun buldum . Gerçek komutun çalıştırılmasına gelince, git worktree( --porcelainayrıştırma kolaylığı seçeneği ile ) mutlak kök yolunu almak için ihtiyacımız olan tek şey.

Örnekte, bir yol dizisi döndürmeyi seçtim çünkü sadece emin olmak için birden fazla çalışma ağacı (ortak yollara sahip olmaları muhtemel olsa da) olabilir. Bir CLI komutu kullandığımızda, shellseçeneğintrue gerektiğini unutmayın (güvenilmeyen bir girdi olmadığı için güvenlik bir sorun olmamalıdır).

Yaklaşım karşılaştırması ve yedekler

VCS'nin erişilemediği bir durumu anlayarak, dokümanları ve diğer cevapları analiz ettikten sonra birkaç geri dönüş ekledim. Özetlemek gerekirse, önerilen çözümler kaynaşacaktır (üçüncü taraf modülleri ve pakete özgü olanlar hariç):

| Çözüm | Avantajı | Ana Sorun |
| ------------------------ | ----------------------- | -------------------------------- |
| `__filename` | modül dosyasını gösteriyor | modüle göre |
| `__dirname` | dir modülünü gösteriyor | __filename` ile aynı |
| node_modules ağaç yürüyüşü | neredeyse garantili kök | eğer karmaşık ağaç yürüme |
| `path.resolve (". ")` | kök ise kök | process.cwd () `ile aynı |
| `process.argv [1]` | __filename` ile aynı | __filename` ile aynı |
| `process.env.INIT_CWD` | 'npm run' dir gösteriyor | `npm` && CLI lansmanı gerektirir |
| `süreç.env.PWD` | geçerli dir için puan | ile ilgili başlatma dir |
| `process.cwd ()` | ENV.PWD` ile aynı | çalışma zamanında `process.chdir (yol)` |
| `gerektirir.main.filename` | === modül 'kökü | "zorunlu" modüllerde hata |

Yukarıdaki karşılaştırma tablosundan, en evrensel olan iki yaklaşımdır:

  • require.main.filenamerequire.main === modulekarşılanırsa root almanın kolay bir yolu olarak
  • node_modulesSon zamanlarda önerilen ağaç yürüyüşü başka bir varsayım kullanıyor:

eğer modül node_modulesdizini içinde dir varsa, muhtemelen kök

Ana uygulama için uygulama kökünü ve modül için - proje kökünü alacak.

Fallback 1. Ağaç yürüyüşü

Uygulamam, belirli bir modülün kökünün proje kökü olduğu gibi bir hedef dizin bulunduğunda durdurarak daha gevşek bir yaklaşım kullanır. Arama derinliğini yapılandırılabilir hale getirmek için aramaları zincirleyebilir veya genişletebilirsiniz:

/**
 * @summary gets root by walking up node_modules
 * @param {import("fs")} fs
 * @param {import("path")} pt
 */
const getRootFromNodeModules = (fs, pt) =>

    /**
     * @param {string} [startPath]
     * @returns {string[]}
     */
    (startPath = __dirname) => {

        //avoid loop if reached root path
        if (startPath === pt.parse(startPath).root) {
            return [startPath];
        }

        const isRoot = fs.existsSync(pt.join(startPath, "node_modules"));

        if (isRoot) {
            return [startPath];
        }

        return getRootFromNodeModules(fs, pt)(pt.dirname(startPath));
    };

Yedek 2. Ana modül

İkinci uygulama önemsiz

/**
 * @summary gets app entry point if run directly
 * @param {import("path")} pt
 */
const getAppEntryPoint = (pt) =>

    /**
     * @returns {string[]}
     */
    () => {

        const { main } = require;

        const { filename } = main;

        return main === module ?
            [pt.parse(filename).dir] :
            [];
    };

uygulama

Daha çok yönlü olduğu için ağaç yürüteçini yedek olarak kullanmanızı öneririm:

const { spawnSync } = require("child_process");
const pt = require('path');
const fs = require("fs");

/**
 * @summary returns worktree root path(s)
 * @param {function : string[] } [fallback]
 * @returns {string[]}
 */
const getProjectRoot = (fallback) => {

    const { error, stdout } = spawnSync(
        `git worktree list --porcelain`,
        {
            encoding: "utf8",
            shell: true
        }
    );

    if (!stdout) {
        console.warn(`Could not use GIT to find root:\n\n${error}`);
        return fallback ? fallback() : [];
    }

    return stdout
        .split("\n")
        .map(line => {
            const [key, value] = line.split(/\s+/) || [];
            return key === "worktree" ? value : "";
        })
        .filter(Boolean);
};

Dezavantajları

En bariz olanı, istenmeyen / mantıksız olabilecek GIT'in kurulması ve başlatılmasıdır (yan not: GIT'in üretim sunucularına yüklenmesi nadir değildir veya güvenli değildir. ). Yukarıda tarif edildiği gibi yedeklerle aracılık edilebilir.

notlar

  1. Yaklaşım 1'in daha da genişletilmesi için birkaç fikir:
    • config işlev parametresi olarak tanıt
    • export bir modül yapma işlevi
    • GIT'in kurulu olup olmadığını ve / veya başlatıldığını kontrol edin

Referanslar

  1. git worktree referans
  2. spawnSync referans
  3. require.main referans
  4. path.dirname() referans


-1

Deneyin path._makeLong('some_filename_on_root.js');

misal:

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

Bu, düğüm uygulamanızın kökünden tam yol döndürür (package.json ile aynı konum)


-1

Sadece kullan:

 path.resolve("./") ... output is your project root directory

bu harika çalışıyor! path.resolve (".") de işe yarıyor
Noel Schenk

Bu sadece geçerli dizini verir, kök dizin olmayabilir.
orad

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.