2012-10-24 11 views
12

Ho un'applicazione Node.JS in esecuzione su Linux presso AWS EC2 che utilizza il modulo fs per leggere i file modello HTML. Ecco l'attuale struttura della domanda:Modo corretto per fare riferimento ai file relativi alla root dell'applicazione in Node.JS

/server.js 
/templates/my-template.html 
/services/template-reading-service.js 

Il codice HTML modelli saranno sempre in quella posizione, invece, il modello-lettura-servizio può muoversi in posizioni diverse (sottodirectory più profonde, ecc) all'interno della template-lettura-service che uso fs.readFileSync() per caricare il file, in questo modo:

var templateContent = fs.readFileSync('./templates/my-template.html', 'utf8'); 

Questo getta il seguente errore:

Error: ENOENT, no such file or directory './templates/my-template.html' 

sto assumendo tha t è perché il percorso './' sta risolvendosi nella directory '/ services /' e non nella root dell'applicazione. Ho anche provato a cambiare il percorso in "../templates/my-template.html" e questo ha funzionato, ma sembra fragile perché immagino che si stia risolvendo relativamente a "up one directory". Se sposto il servizio di lettura template in una sottodirectory più profonda, quel percorso si interromperà.

Quindi, qual è il modo corretto di fare riferimento ai file relativi alla radice dell'applicazione?

risposta

15

Prova

var templateContent = fs.readFileSync(path.join(__dirname, '../templates') + '/my-template.html', 'utf8'); 
+2

Non è __dirname in realtà il percorso in cui si trova lo script/modulo corrente? Quindi nel mio esempio, quando eseguo dall'interno di 'template-reading-service.js 'non risolve __dirname in'/services/'? – user1438940

+0

@ user1438940 Ho pensato che si eseguisse il codice di lettura del file in '/ server.js'. Prova "../templates/my-template.html" – InspiredJW

+0

no, il codice che esegue fs.getFileSync si trova in "template-reading-service.js". Non voglio usare "../"; questo è l'intero punto della mia domanda. Se uso "../" e successivamente sposto "template-reading-service.js" dalla directory "/ services /" a "/ services/templating /" quindi tutte le mie interruzioni di codice. Oppure, se voglio avere il percorso della directory template come un'impostazione in una configurazione globale, che sarebbe poi utilizzata da 20 diversi altri servizi, tutti situati in punti diversi nella struttura della directory, quindi "../" non funziona da ovunque – user1438940

26

Per ottenere un percorso del filesystem assoluto della directory in cui il processo di nodo è in esecuzione, è possibile utilizzare process.cwd(). Quindi, supponendo che si esegue /server.js come un processo che implementa /services/template-reading-service.js come modulo, allora si può fare quanto segue da /servizio/modello-lettura-service .js:

var appRoot = process.cwd(), 
    templateContent = fs.readFileSync(appRoot + '/templates/my-template.html', 'utf8'); 

Se questo non dovesse funzionare, allora potreste essere in esecuzione /service/template-reading-service.js come un processo separato, nel qual caso è necessario avere tutto quello che lancia processo passare il percorso che si desidera trattare come l'applicazione primaria radice. Ad esempio, se /server.js lancia /service/template-reading-service.js come processo separato, allora /server.js dovrebbe passarlo al proprio process.cwd().

+0

Quindi, pensavo che questo potesse funzionare per me, ma non lo fa lavoro in tutti i miei ambienti. Nel mio ambiente di produzione, sto usando 'per sempre' così' process.cwd' restituisce '/'. – user1438940

+0

Per le persone future che guardano queste risposte: process.cwd non è * necessariamente * la risposta che stai cercando. Su Windows, ad esempio, se si esegue un processo nodo da un file .bat, process.cwd() restituisce il percorso del file .bat, non alla radice del progetto del nodo. Credo che regole simili si applichino a Linux e Mac. – TKoL

12

La risposta accettata è errata. Hardcoding path.join(__dirname, '../templates') farà esattamente ciò che non si desidera, rendendo il file service-XXX.js interrompe l'app principale se si sposta in una posizione secondaria (come nell'esempio dato services/template).

L'utilizzo di process.cwd() restituisce il percorso di root per il file che ha avviato il processo in esecuzione (quindi, ad esempio, /Myuser/myproject/server.js restituisce /Myuser/myproject/).

Questo è un duplicato della domanda Determine project root from a running node.js application.

Su questa domanda, la risposta __dirname ha ottenuto il giusto effetto che merita. Attenzione al marchio verde, i passanti.

+2

Ho avuto un tempo orribile usando il pacchetto app-root-path. C'erano due modi per avviare la mia app, nodo lib/my_app.js o bin/my_app.js. 'path.join (__ dirname)' Ho passato molto tempo e il codice patching app-root-path per funzionare su piattaforme, in definitiva sono passato a 'path.join (__ dirname)' che funzionerà finché i file di progetto non lo faranno spostati. – Ninjaxor

+1

Per le persone future che guardano queste risposte: process.cwd non è * necessariamente * la risposta che stai cercando. Su Windows, ad esempio, se si esegue un processo nodo da un file .bat, process.cwd() restituisce il percorso del file .bat, non alla radice del progetto del nodo. Credo che regole simili si applichino a Linux e Mac. – TKoL

Problemi correlati