Argumenty linii poleceń w Node.js

Przy okazji korzystania z forever natknąłem się na małą przeszkodę: używając paczki nie da się ustawić zmiennych środowiskowych dla każdej zarządzanej aplikacji oddzielnie. Rozwiązaniem było uruchamianie aplikacji z argumentami linii poleceń zamiast zmiennych środowiskowych.

W „normalnej” sytuacji uruchamiałbym aplikację Node.js w taki sposób:

$ NODE_ENV=production PORT=8001 node bin/www

Jak widać, przed komendą zawieram tu zmienne środowiskowe. Niestety, gdy nie korzystamy z terminala albo uruchamiany wiele aplikacji jedną komendą (jak ma to miejsce w przypadku forever i konfiguracji wielu aplikacji w pliku JSON), korzystanie ze zmiennych środowiskowych przestaje mieć sens.

Jeśli nie chcemy na sztywno wpisywać w kodzie każdej aplikacji takich informacji jak środowisko czy port (a raczej nie chcemy), warto w takiej sytuacji przyjrzeć się argumentom linii poleceń. Można przecież aplikację uruchomić tak:

$ node bin/www --port=8001 --env=production

Powstaje oczywiście pytanie: ale jak odczytać argumenty z linii poleceń?

Użyte części polecenia dostępne są w zmiennej process.argv i dla przykładowego polecenia przytoczonego powyżej wartość ta będzie wyglądała tak:

[
    "node",
    "bin/www",
    "--port=8001",
    "--env=production"
]

Oczywiście wersje formatu argumentów mogą być różne, np:

$ node bin/www -p8001 -e production --host 127.0.0.1

Brak spacji w -p8001 jest zamierzony. Taki format również jest prawidłowy. Jak zatem rozprawić się z wszystkimi możliwościami bez przemęczania się?

Rozwiązaniem może być minimist. Paczka nie ma żadnych zależności, nie trzeba więc martwić się, że przeładuje katalog node_modules megabajtami niepotrzebnego kodu. A użycie minimist jest bardzo łatwe, wystarczy przekazać mu tablicę z argumentami do sparsowania:

const minimist = require("minimist");
const argv = minimist(process.argv.slice(2));

Wynikiem jest obiekt ze wszystkimi argumentami, jakie zostały przekazane do aplikacji (według powyższego przykładu):

{
    p: "8001",
    e: "production",
    host: "127.0.0.1"
}

Pozwoliłem sobie zatem napisać taki malutki modulik:

const minimist = require("minimist");

const argv = minimist(process.argv.slice(2));

const hostname = argv.h || argv.host || "127.0.0.1";
const port = argv.p || argv.port || process.env.PORT || 8000;
const environment = argv.e || argv.env || process.env.NODE_ENV || "development";

module.exports = {
    hostname,
    port,
    environment
};

Jak widać powyżej, moduł parsuje argumenty za pomocą minimist, a następnie decyduje, jaki jest port, nazwa hosta i środowisko aplikacji. Bierze przy tym pod uwagę pełne i skrócone wersje argumentów linii poleceń, ale także zmienne środowiskowe. Argumenty mają pierwszeństwo przed zmiennymi środowiskowymi, a jeśli żadne nie są dostępne, używane są wartości domyślne.

Wyeksportowanego obiektu można użyć np. do uruchomienia serwera:

const http = require("http");
const {port, hostname} = require("./args");

http
    .createServer((req, res) => {
        res.statusCode = 200;
        res.write("Hello world");
        res.end();
    })
    .listen(port, hostname);

Napisz komentarz


Szukaj wpisów


Chmura tagów