Czy istnieje sposób na uzyskanie wersji z package.json w kodzie nodejs?


586

Czy istnieje sposób na ustawienie wersji w package.jsonaplikacji nodejs? Chciałbym czegoś takiego

var port = process.env.PORT || 3000
app.listen port
console.log "Express server listening on port %d in %s mode %s", app.address().port, app.settings.env, app.VERSION

Czy ważniejsze jest uzyskanie wersji Node lub wersji zadeklarowanej w pliku package.json? Jeśli formularz, otrzymasz bieżącą wersję:console.log(process.version)
Adrian Lynch

Odpowiedzi:


957

Odkryłem, że następujący fragment kodu działa najlepiej dla mnie. Ponieważ używa requiredo ładowania package.json, działa niezależnie od bieżącego katalogu roboczego.

var pjson = require('./package.json');
console.log(pjson.version);

Ostrzeżenie, dzięki uprzejmości @Pathogen:

Robienie tego za pomocą Browserify ma wpływ na bezpieczeństwo.
Uważaj, aby nie ujawnić swojego package.jsonklienta, ponieważ oznacza to, że wszystkie numery wersji zależności, polecenia kompilacji i testowania oraz inne są wysyłane do klienta.
Jeśli budujesz serwer i klienta w tym samym projekcie, ujawniasz również numery wersji po stronie serwera. Takie określone dane mogą być wykorzystane przez atakującego, aby lepiej dopasować atak do twojego serwera.


25
jeśli wciąż się palisz, próbując złapać to z różnych miejsc (tak jak ja), możesz to zrobićrequire('root-require')('package.json').version
mikermcneil

5
Nie działa dla mojego skryptu z shebang zainstalowanym globalnie. Error: Cannot find module 'package.json'.
exebook

14
krótszy - wymaga ('./ pakiet'). wersja
Afanasii Kurakin

60
Ostrzeżenie! Robienie tego za pomocą przeglądarki może mieć wpływ na bezpieczeństwo: pakiet.json w pakiecie oznacza, że ​​wszystkie numery wersji zależności, polecenia kompilacji i testowania oraz inne są wysyłane do klienta. Jeśli budujesz serwer i klienta w tym samym projekcie, ujawniasz również numery wersji swoich serwerów.
Patogen

4
@ GenversionPathogen rozwiązuje problem po stronie klienta. Jest to narzędzie, które odczytuje wersję z pliku package.json i generuje z niej moduł do importowania. Oświadczenie: Jestem opiekunem.
Akseli Palén

348

Jeśli twoja aplikacja jest uruchomiona z „npm start”, możesz po prostu użyć:

process.env.npm_package_version

Aby uzyskać więcej informacji, zobacz vars package.json .


6
jest to prawdopodobnie najlepsza odpowiedź, ponieważ większość informacji w pakiecie.json jest dołączona do zmiennej środowiska wykonawczego procesu
Alexander Mills,

2
Tak, zgadzam się. To powinna być właściwa odpowiedź, przy użyciu zmiennej procesowej nie trzeba otwierać i ponownie czytać pliku package.json.
Juanma

12
Poza węzłem (np. Skrypty powłoki wykonywane przez npm run …) wersja będzie w zmiennej środowiskowej $npm_package_version.
Quinn Comendant,

12
W przypadku wywołania ze skryptów innego pakietu niepoprawnie zgłasza wersję pakietu wywołującego , a nie pakiet wywoływany .
jjrv

6
Działa w ramach uruchomionej aplikacji elektronowejnpm start , ale nie w wbudowanej aplikacji elektronowej: w tym celu można ją znaleźć w app.getVersion.
ChrisV

158

Za pomocą modułów ES6 możesz wykonać następujące czynności:

import {version} from './package.json';

2
Myślałem, że nie są obsługiwane w węźle: github.com/nodejs/help/issues/53
ripper234

1
Żadne moduły es6 nie są jeszcze bezpośrednio obsługiwane, ale i tak powszechnie używane, włączone przy użyciu Babel
Patrick Lee Scott

4
@ Sornii nie, cały pakiet.json będzie w kliencie. Użyłem zdefiniowanej wtyczki webPacka do przekazania tylko wybranych informacji ze środowiska węzła do przeglądarki.
doeke

2
Jakikolwiek wpływ na bezpieczeństwo, taki jak określony w stackoverflow.com/a/10855054/540144 ?
itsazzad

1
Tak, te same problemy bezpieczeństwa. Cały pakiet.json zostanie zawarty w pakiecie klienta.
Neromancer

94

Lub w zwykłej starej powłoce:

node -e "console.log(require('./package.json').version);"

Można to skrócić

node -p "require('./package.json').version"

Chociaż nie jest to dokładnie to, o co pytano, jest przydatne, jeśli chcesz użyć wersji w package.jsonsobie, na przykład zalogować się do pliku w wersji w script:

{
  "name": "myapp",
  "version": "0.1.2",
  "scripts": {
    "run": "node index.js 2>&1 | tee -a myapp_v$(node -p \"require('./package.json').version\").log",
  ...
}

To nie jest jednak sama aplikacja nodeJS, zgodnie z żądaniem.
Steve Bennett

1
@ SteveBennett Nie, ale pomogło 90 osobom plus ja.
Karl Morrison

1
Prawdopodobnie o wiele więcej.
Steve Bennett

61

Istnieją dwa sposoby pobrania wersji:

  1. Wymaganie package.jsoni uzyskanie wersji:
const { version } = require('./package.json');
  1. Korzystanie ze zmiennych środowiskowych:
const version = process.env.npm_package_version;

Proszę nie używać JSON.parse, fs.readFile, fs.readFileSynci nie używać innego npm modulesnie jest to konieczne dla tej kwestii.


2
Dziękujemy za ten fragment kodu, który może zapewnić pewną ograniczoną, natychmiastową pomoc. Właściwe wyjaśnienie byłoby znacznie poprawić swoją długoterminową wartość pokazując dlaczego jest to dobre rozwiązanie problemu, a byłoby bardziej użyteczne dla czytelników przyszłości z innymi, podobnymi pytaniami. Proszę edytować swoją odpowiedź dodać kilka wyjaśnień, w tym założeń już wykonanych.
milo526,

8
Następnie npm_*wartości środowiskowe są dostępne tylko wtedy, gdy skrypt został rozpoczęty przez KMP, np npm start. Jeśli to robisz node app.jslub coś podobnego, nie będą one obecne.
Nate

@Nate Więc lepiej jest używać wersji z package.json?
Filip Š

37

Oto jak odczytać wersję z pliku package.json:

fs = require('fs')
json = JSON.parse(fs.readFileSync('package.json', 'utf8'))
version = json.version

Widziałem to kilka i podoba mi się to - czy ty / ktokolwiek zna uwagi, które require() introduces? (for instance, does wymagają () `nie obsługi odczytu utf8? jak może sugerować Twój fragment)
electblake

4
require()buforuje plik, co w tym przypadku nie powinno mieć znaczenia.
jlee,

@jlee jest powód, dla którego ludzie często to robią JSON.parse(fs.readFileSync('package.json', 'utf8'))zamiast delete require.cache[require.resolve('package.json')]; require('package.json')kiedy chcą ponownie załadować?
Mihail Malostanidis

const {wersja} = wymagana ('./ package.json');
аlex dykyі

23

Istnieje inny sposób pobierania niektórych informacji z package.jsonpliku, a mianowicie użycie modułu pkginfo .

Korzystanie z tego modułu jest bardzo proste. Możesz pobrać wszystkie zmienne pakietu, używając:

require('pkginfo')(module);

Lub tylko niektóre szczegóły ( versionw tym przypadku)

require('pkginfo')(module, 'version');

Zmienne pakietu zostaną ustawione na module.exports(więc numer wersji będzie dostępny za pośrednictwem module.exports.version).

Możesz użyć następującego fragmentu kodu:

require('pkginfo')(module, 'version');
console.log "Express server listening on port %d in %s mode %s", app.address().port, app.settings.env, module.exports.version

Moduł ma bardzo fajną funkcję - można go użyć w dowolnym pliku w projekcie (np. W podfolderach) i automatycznie pobierze informacje z twojego package.json. Więc nie musisz się martwić, gdzie jesteś package.json.

Mam nadzieję, że to pomoże.


1
co moduletu jest
chovy

@chovy, modulenie jest tą konkretną przykładową zmienną; jest to zmienna reprezentująca bieżący moduł w node.js. Możesz przeczytać więcej o modułach node.js tutaj: nodejs.org/api/modules.html#modules_the_module_object
Tom

2
Próbuję uzyskać wersję innych modułów wymaganą przez mój moduł ... i trudno mi ustalić, czy pkginfo to umożliwia.
Michael

23

Dla tych, którzy szukają bezpiecznego rozwiązania po stronie klienta , które działa również po stronie serwera, istnieje genversion . Jest to narzędzie wiersza polecenia, które odczytuje wersję z najbliższego package.json i generuje importowalny plik modułu CommonJS, który eksportuje wersję. Oświadczenie: Jestem opiekunem.

$ genversion lib/version.js

Uznaję bezpieczeństwo po stronie klienta nie był pierwotny zamiar OP, ale jak wspomniano w odpowiedzi przez Mark Wallace i sie , to jest bardzo istotne, a także powód Znalazłem Q & A.


4
To jest odpowiedź, która potrzebuje więcej głosów, aby wyjść poza głęboko problematyczną odpowiedź na górze.
Jeff Allen

1
Niektóre osoby mogą być zaniepokojone faktem, że jest to narzędzie wiersza poleceń. Nie martw się! Plik Readme narzędzia opisuje, w jaki sposób (łatwo) zintegrować wywołanie kompilacji z pakietem.json, abyś mógł zapomnieć o istnieniu narzędzia i zawsze miał najnowszy numer wersji.
Malamut

11

Właśnie dodając odpowiedź, ponieważ przyszedłem do tego pytania, aby zobaczyć najlepszy sposób na dołączenie wersji z package.json do mojej aplikacji internetowej.

Wiem, że to pytanie jest skierowane do Node.js, ale jeśli używasz Webpacka do spakowania aplikacji jako przypomnienie, zalecanym sposobem jest użycie DefinePlugin do zadeklarowania wersji globalnej w konfiguracji i odwołanie się do tego. Więc możesz zrobić w swoimwebpack.config.json

const pkg = require('../../package.json');

...

plugins : [
    new webpack.DefinePlugin({
      AppVersion: JSON.stringify(pkg.version),
...

A potem AppVersionjest teraz globalny, który jest dostępny do użycia. Upewnij się także, .eslintrcże zignorujesz to poprzez rekwizyt globals


8

opcja 1

Najlepszą praktyką jest wersja z package.json przy użyciu zmiennych środowiskowych npm.

process.env.npm_package_version

więcej informacji na: https://docs.npmjs.com/using-npm/config.html

Działa to tylko po uruchomieniu usługi za pomocą polecenia NPM.

Szybka informacja: możesz odczytać dowolne wartości w pacakge.json przy użyciu process.env.npm_package_ [nazwa klucza]

Opcja 2

Ustawianie wersji w zmiennej środowiskowej za pomocą https://www.npmjs.com/package/dotenv jako .envpliku i uwzględnianie jej wprocess.env.version


7

Za pomocą ES6 można zaimportować pakiet.json w celu pobrania numeru wersji i wypisania wersji na konsolę.

import {name as app_name, version as app_version}  from './path/to/package.json';

console.log(`App ---- ${app_name}\nVersion ---- ${app_version}`);

3
Działa to tak długo, jak w „tsconfig.json” ustawisz „resolJsonModule” na „true”.
Russell Phillips

6

Aby ustalić wersję pakietu w kodzie węzła, możesz użyć następujących opcji:

  1. const version = require('./package.json').version; dla wersji <ES6

  2. import {version} from './package.json'; dla wersji ES6

  3. const version = process.env.npm_package_version; jeśli aplikacja została uruchomiona przy użyciu npm start, wszystkie zmienne środowiskowe npm_ * stają się dostępne.

  4. Możesz także użyć następujących pakietów npm - root-demand, pkginfo, wersja projektu.


4

Możesz użyć pakietu wersji projektu .

$ npm install --save project-version

Następnie

const version = require('project-version');

console.log(version);
//=>  '1.0.0'

Używa, process.env.npm_package_versionale zastępuje wersję napisaną package.jsonw przypadku, gdy z jakiegoś powodu brakuje zmiennej env var.


Na przykład, jeśli plik js nie został uruchomiony z npm?
Mihail Malostanidis

1

Robię to z findup-sync:

var findup = require('findup-sync');
var packagejson = require(findup('package.json'));
console.log(packagejson.version); // => '0.0.1' 

findup zaczyna się od cwd, więc w większości przypadków po prostu uzyskałby najwyższy poziom package.json, podobnie jak process.env.npm_package_versionpoza tym, że nie wymagałby, aby był uruchamiany przez npm. Tak więc próba uzyskania wersji biblioteki faktycznie dostałaby wersję osoby dzwoniącej. Proste wymaganie („./ package.json”) uniknęłoby tego.
Mihail Malostanidis

1

Wiem, że to nie jest cel PO, ale musiałem to zrobić, więc mam nadzieję, że pomoże to następnej osobie.

Jeśli używasz komponowania dokującego do procesu CI / CD, możesz to zrobić w ten sposób!

version:
  image: node:7-alpine
  volumes:
    - .:/usr/src/service/
  working_dir: /usr/src/service/
  command: ash -c "node -p \"require('./package.json').version.replace('\n', '')\""

dla obrazu możesz użyć dowolnego obrazu węzła. Używam alpine, ponieważ jest najmniejsza.


1

Dlaczego nie użyć wymagającego rozwiązania ...

const packageJson = path.dirname(require.resolve('package-name')) + '/package.json';
const { version } = require(packageJson);
console.log('version', version)

Dzięki takiemu podejściu działa dla wszystkich ścieżek podrzędnych :)


0

Zaimportuj package.jsonplik do pliku server.jslub, app.jsa następnie uzyskaj dostęp do właściwości package.json do pliku serwera.

var package = require('./package.json');

zmienna pakietu zawiera wszystkie dane w pliku package.json.


0

Zrobiłem użyteczny kod, aby uzyskać pakiet.json modułu nadrzędnego

function loadParentPackageJson() {
    if (!module.parent || !module.parent.filename) return null
    let dir = path.dirname(module.parent.filename)
    let maxDepth = 5
    let packageJson = null
    while (maxDepth > 0) {
        const packageJsonPath = `${dir}/package.json`
        const exists = existsSync(packageJsonPath)
        if (exists) {
            packageJson = require(packageJsonPath)
            break
        }
        dir = path.resolve(dir, '../')
        maxDepth--
    }
    return packageJson
}

0

Jeśli używasz pakietu zbiorczego, rollup-plugin-replacewtyczki można użyć do dodania wersji bez ujawniania pliku package.json klientowi.

// rollup.config.js

import pkg from './package.json';
import { terser } from "rollup-plugin-terser";
import resolve from 'rollup-plugin-node-resolve';
import commonJS from 'rollup-plugin-commonjs'
import replace from 'rollup-plugin-replace';

export default {
  plugins: [
    replace({
      exclude: 'node_modules/**',
      'MY_PACKAGE_JSON_VERSION': pkg.version, // will replace 'MY_PACKAGE_JSON_VERSION' with package.json version throughout source code
    }),
  ]
};

Następnie w kodzie źródłowym, gdziekolwiek chcesz mieć wersję package.json, użyjesz ciągu „MY_PACKAGE_JSON_VERSION”.

// src/index.js
export const packageVersion = 'MY_PACKAGE_JSON_VERSION' // replaced with actual version number in rollup.config.js
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.