“npm install”이 package-lock.json을 다시 쓰는 이유는 무엇입니까?


612

방금 최근에 npm @ 5로 업그레이드했습니다 . 이제 package.json의 모든 것을 가진 package-lock.json 파일이 있습니다. 실행 하면 종속성 파일을 잠금 파일에서 가져 와서 node_modules 디렉토리에 설치해야 할 내용을 결정할 수 있습니다 . 이상한 점은 실제로 package-lock.json 파일을 수정하고 다시 작성한다는 것 입니다.npm install

예를 들어, 잠금 파일의 유형 스크립트는 버전 2.1.6으로 지정되었습니다 . 그런 다음 npm install명령 후 버전이 2.4.1 로 변경되었습니다 . 잠금 파일의 전체 목적을 무효화하는 것 같습니다.

내가 무엇을 놓치고 있습니까? 잠금 파일을 실제로 존중하기 위해 npm을 어떻게 얻습니까?


4
이것은 귀하의 질문에 대답하지 않으므로 희망적으로 의견은 괜찮지 만 원사를 살펴보십시오. 전환하는데 1 시간도 걸리지 않았습니다.
KayakinKoder

4
같은 문제이지만 원사 github.com/yarnpkg/yarn/issues/570 (매우 유익한 ) 사용
Yves M.

2
같은 문제가 있습니다. package-lock.json내가 실행할 때 내 재생성됩니다 npm install. 이것은 npm 버그 냄새가납니다. 당신은 당신의 자신의 레지스트리를 사용합니까?
HaNdTriX


@YvesM. --no-save잠금 파일을 변경하지 못하지만 OP가 언급 한 구피 1 단계 종속성 업그레이드에는 영향을 미치지 않습니다.
Ross Allen

답변:


423

업데이트 3 : 다른 답변도 지적했듯이 npm ci명령은 CI 컨텍스트에서 빠르고 재현 가능한 빌드를 달성하는 추가 방법으로 npm 5.7.0에 도입되었습니다. 자세한 내용은 설명서npm 블로그 를 참조하십시오 .


업데이트 2 : 설명서를 업데이트하고 명확히하는 문제GitHub 문제 # 18103 입니다.


업데이트 1 : 아래 설명 된 동작은 npm 5.4.2에서 수정되었습니다. 현재 의도 된 동작은 GitHub 문제 # 17979에 요약되어 있습니다 .


원래 답변 : 문제 # 16866 에서 설명한대로 npm 5.1.0package-lock.json 에서 동작 이 변경되었습니다 . 관찰되는 동작은 버전 5.1.0부터 npm에 의해 의도 된 것입니다.

이는 의 최신 버전이 발견 될 때마다 package.json재정의 package-lock.json할 수 있음을 의미합니다 package.json. 종속성을 효과적으로 고정하려면 이제 접두사없이 버전을 지정해야합니다. 예를 들어 또는 1.2.0대신에 버전을 작성해야합니다 . 다음의 조합 과 재생 가능한 빌드를 얻을 것입니다. 분명히 : 더 이상 루트 레벨 종속성을 잠그지 않습니다!~1.2.0^1.2.0package.jsonpackage-lock.jsonpackage-lock.json

이 디자인 결정이 좋은지 아닌지는 논란의 여지가 있지만 이슈 # 17979의 GitHub에 대한 이러한 혼란으로 인해 지속적인 논의가 진행되고 있습니다 . (제 눈에는 의심스러운 결정입니다. 최소한 그 이름 lock은 더 이상 사실이 아닙니다.)

추가 참고 사항 : npmjs.org 대신 GitHub에서 직접 패키지를 가져올 때와 같이 변경 불가능한 패키지를 지원하지 않는 레지스트리에 대한 제한 사항도 있습니다. 자세한 설명은이 패키지 잠금 설명서를 참조하십시오 .


43
그렇다면 핵은 무엇인가 npm update? : o 나는 똑같이 npm install업데이트 된 뎁을 느꼈지만 그것을 믿기를 원하지 않는다. 그러나 슬프게 사실 인 것 같다. 어쨌든 여전히 npm shrinkwrap뎁을 잠그는 옵션이 있지만 확실하게 package-lock이라는 이름은 틀렸다 그것이 멈추거나 의존성을 잠그지 않기 때문에 ..
Jurosh

266
엉망이야! 세계에서 가장 큰 패키지 관리자는 아직 작동 방법에 대한 설명서가 없습니다. 모두가해야 할 일에 대해 추측하고 있으며 의견의 전쟁으로 변합니다. 토론은 좋지만 실제로 공개되기 전에 이루어져야합니다. 어떤 시점에서 누군가는 최종 전화를 걸어야하고 구현, 문서화 및 릴리스를 수행 할 수 있습니다. PHP는위원회에 의해 설계되었고 임시로 함께 만들어졌으며 그것이 어떻게 나타 났는지 살펴 봅니다. 이 중요하고 널리 사용되는 도구에서 동일한 일이 발생하는 것을 싫어합니다.
랜든 포치

85
그렇다면 package-lock을 사용하는 요점은 무엇입니까? 다른 작업 공간에서 동일한 환경을 만들 것이라고 생각했지만 아무 것도하지 않는 것으로 나타났습니다
laltin

17
"그런 다음 package.json과 package-lock.json의 조합은 재현 가능한 빌드를 생성합니다." "package-lock.json"의 역할은 무엇입니까? 버전 접두사가 사용되지 않으면 "package.json"만으로도 재현 가능한 빌드가 생성되지 않습니까?
Jānis Elmeris

12
@ JānisElmeris 나는 package.json이 깊은 의존성을 잠글 수 없다고 생각합니다 ...
Juan Mendes

165

나는 NPM의 새로운 버전이 될 것입니다 것으로 나타났습니다 5.7.1 새로운 명령 npm ci에서 설치되며, package-lock.json단지

새로운 npm ci 명령은 잠금 파일에서만 설치합니다. package.json과 잠금 파일이 동기화되지 않은 경우 오류가보고됩니다.

node_modules를 버리고 처음부터 다시 작성하면 작동합니다.

node_modules로 시작하지 않으면 잠금 파일에있는 내용 만 얻을 수 있다는 것을 보장하는 것 외에도 npm 설치보다 훨씬 빠릅니다 (2x-10x!).

이름에서 알 수 있듯이 지속적인 통합 환경에 큰 도움이 될 것으로 기대합니다. 또한 git 태그를 사용하여 프로덕션 배포를 수행하는 사람들은 큰 이익을 얻을 것으로 기대합니다.


133
잠금 파일이 존재하면 이것이 기본 동작이어야합니다.
무효 성

13
그래서 그들은 npm 작동 방식을 변경하여 몇 개월 후 npm으로 다시 가져 오도록합니까?
Scott Flack

1
여전히 혼란 스러워요. 문서화는 말한다 : "당신이 패키지 잠금 및 최신 설치가 있는지 확인 npm install" 명령을 실행하기 전에 npm ci해당 프로젝트에. 하지 않습니다 npm install패키지-lock.json 파일을 덮어?
adiga 2016 년

1
AFAIK : @adiga-버전 5.4부터는 필요한 경우 npm 에만 잠금 파일을 변경하여 packages.json의 사양을 충족시킵니다 . 따라서 패키지가 say thatpackage: 1와 lock 가 말했 더라면 ..: 1.0.4dev는 say를 편집 할 수 있으며 새로 지정된 범위와 호환되지 thatpackage: 2않기 때문에 lock 파일을 강제로 변경 1.0.4합니다. 변경하지 않으면 packages.json잠금 파일을 삭제할 때까지 정확한 버전으로 잠겨 있습니다. [잠금 상태를 유지하지 않고 packages.json을 변경하지 않은 경우 버그 보고서를 제출하십시오.]
ToolmakerSteve

1
@George 내가 읽은 정보 (최신 버전의 npm) 및 제한적인 테스트에서 : yes to both
Venryx

95

새로 소개 된 사용

npm ci

npm ci는 대규모 팀에게 가장 큰 이점을 약속합니다. 개발자에게 패키지 잠금에서 "로그 오프"할 수있는 기능을 제공하면 대규모 팀간에보다 효율적인 협업이 가능하며 잠금 파일에 정확하게 설치하는 기능은 한 달에 수백 시간의 개발자 시간이 아니라도 수십 시간을 절약 할 수있어 팀이 자유롭게됩니다. 놀라운 것들을 만들고 배송하는 데 더 많은 시간을 할애합니다.

npm ci보다 빠르고 안정적인 빌드를위한 소개


3
이것은 나에게 맞는 것 같습니까? 다른 사람이 확인할 수 있습니까?
phouse512

6
@ phouse512 맞습니다. 우리는 거의 만을 사용 npm ci, 만 사용 npm install업데이트하거나 새로운 패키지를 설치합니다.
Jacob Sievers

1
최근 의견 등. 이것은 내가 함께 할 대답입니다. 너무 나쁘게 그들은 끔찍한 snafu를 고치지 않지만 새로운 복음이 "npm ci"라면 괜찮습니다. 적응할 수 있습니다.
Svend

너무 나쁘면 항상 기존 node_modules디렉토리를 삭제하고 로컬이지만 빈 디렉토리이지만 중요한 심볼릭 링크 인 경우에도 로컬로 다시 작성합니다. :(
Joe Atzberger 2016 년

2
@ToolmakerSteve 숨을 참지 마십시오! 디렉토리의 내용을 삭제하는 것이 디렉토리를 삭제하는 것보다 훨씬 느리다고 생각합니다. 내용을 열거 한 다음 하나의 delete 명령 대신 O / S에 일련의 delete 명령을 실행해야합니다. 이전에 npm에서 수준 조정 된 성능 문제와 사용을 통한 개선 npm ci으로 인해 매우 드문 유스 케이스의 성능을 저하시킬 수있는 것을 소개하는 것이 매우 꺼릴 것으로 기대합니다. pnpm.js.org 를 확인 하면 디스크 사용을 줄이기 위해 하드 링크를 사용합니다.
Caltor

64

짧은 답변:

  • npm install package-lock.json이 package.json의 요구 사항을 충족하는 경우에만 존중합니다.
  • 이러한 요구 사항을 충족하지 않으면 패키지가 업데이트되고 패키지 잠금이 덮어 씁니다.
  • 빌드가 실패하면 패키지 잠금을 다시 작성하는 것보다을 사용하십시오 npm ci.

다음은 상황을 설명 할 수있는 시나리오입니다 (NPM 6.3.0으로 검증 됨).

package.json에서 다음과 같이 종속성을 선언합니다.

"depA": "^1.0.0"

그런 다음 다음 npm install과 같이 package-lock.json을 생성합니다.

"depA": "1.0.0"

며칠 후 "depA"의 최신 마이너 버전 (예 : "1.1.0")이 릴리스되면 다음 사항이 적용됩니다.

npm ci       # respects only package-lock.json and installs 1.0.0

npm install  # also, respects the package-lock version and keeps 1.0.0 installed 
             # (i.e. when package-lock.json exists, it overrules package.json)

다음으로 package.json을 수동으로 업데이트하여 다음을 수행하십시오.

"depA": "^1.1.0"

그런 다음 다시 실행하십시오.

npm ci      # will try to honor package-lock which says 1.0.0
            # but that does not satisfy package.json requirement of "^1.1.0" 
            # so it would throw an error 

npm install # installs "1.1.0" (as required by the updated package.json)
            # also rewrites package-lock.json version to "1.1.0"
            # (i.e. when package.json is modified, it overrules the package-lock.json)

4
이것은 실제로 "잠금"파일의 의도 된 동작입니다. 이전 버전의 NPM에서는 그렇지 않았습니다.
Blockost 2019 년

1
그렇다면 npm은 package.json의 마지막 업데이트를 어떻게 추적합니까? package.json 및 package-lock.json을 다른 컴퓨터로 이동하면 어떻게됩니까? 새 컴퓨터의 npm은 package-lock.json을 업데이트해야하는지 여부를 결정하기 위해 package.lock이 원본인지 또는 업데이트되었는지 어떻게 알 수 있습니까?
Lahiru Chandima

3
@LahiruChandima 업데이트를 실제로 추적하지는 않습니다. npm install이 경우 package.json을 설치하고 그에 따라 package-lock.json을 다시 빌드 package-lock.json하지 않는 한 잠긴 버전을 사용합니다 package.json. package.json기존 패키지 잠금이 여전히 업데이트 된 package.json내용을 만족시키는 방식으로 변경 한 경우 계속 사용할 것입니다.package-lock
Ahmad Abdelghany 2016 년

1
package.json의 요구 사항을 충족하는 모듈이 node_modules에 이미 있으면 npm installpackage-lock.json에 관계없이 아무 것도 수행하지 않습니다. package.json에 지정된 semver와 일치하는 업데이트가있는 경우에도 패키지를 명시 적으로 업데이트해야합니다. 적어도 그것은 수년간 나의 경험이었습니다.
carlin.scott

1
@ToolmakerSteve 나는 또한 @ carlin.scott이보고 한 행동에 회의적이지만 방금 테스트했으며 실제로 그는 정확합니다. 내의 버전이 node_modules의 범위를 만족하고 파일 package.json이 없으면 package-lock.jsonnpm은 실행시 모듈을 업데이트하지 않습니다 npm install. 의존성을 업데이트하기 위해 npm update(또는 npm-check최신으로) 사용할 수 있기 때문에 괜찮은 것 같습니다. 이 동작은 항목을 하나만 추가 package.json하고 관련없는 패키지가 해당 항목을 만족하는 최신으로 업데이트하지 않으려 는 경우 더 빠릅니다. 범위.
Venryx

19

npm ci대신 명령을 사용하십시오 npm install.

"ci"는 "연속 통합"을 나타냅니다.

lenient package.json 파일 종속성 대신 package-lock.json 파일을 기반으로 프로젝트 종속성을 설치합니다.

팀 동료와 동일한 빌드를 생성하며 훨씬 빠릅니다.

이 블로그 게시물에서 자세한 내용을 확인할 수 있습니다 : https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable


2
ci명령을 알리는 문서 및 블로그 게시물에 언급 한 바와 같이, "지속적인 통합"을 의미한다 : blog.npmjs.org/post/171556855892/...
조 Atzberger

고마워 조. 정답을 올바른 이름으로 업데이트하고 블로그 게시물에 연결했습니다. 😊 (이것을 읽는 사람들을 위해, 나는 이전에 그것이 "깨끗한 설치"를 의미한다고 말했다)
Daniel Tonon

"또한 훨씬 빠릅니다."- node_modules폴더 를 삭제 하고 처음부터 다시 만듭니다. 정말 더 빠릅니까? 폴더도 npm install삭제 합니까 node_modules?
izogfif

속도는 npm에서 다운로드 할 패키지를 계산할 필요가 없기 때문에 발생한다고 생각합니다. npm install실행시 모든 패키지 종속성을 해결해야 한다고 생각하십시오 . npm ci"정확한 모듈을 얻으십시오"의 쇼핑 목록 일뿐입니다.
Daniel Tonon

8

앞으로는 --from-lock-file(또는 유사한) 플래그를 사용 하여 수정하지 않고서 설치할 있습니다 package-lock.json.

이는 재현 가능한 빌드가 중요한 CI 등의 환경에 유용합니다.

기능 추적에 대해서는 https://github.com/npm/npm/issues/18286 을 참조 하십시오 .


나는 그것을 의심한다. 운영 체제마다 종속성이 다른 경우 어떻게 작동하지 않는 것을 강제로 설치할 수 있습니까?
Yevgeniy Afanasyev

4
@YevgeniyAfanasyev이 플래그 대신 npm ci질문을 처리하는 방식으로 구현되었습니다 .
spex

8

이 문제는 npm v5.4.2에서 해결 된 것으로 보입니다.

https://github.com/npm/npm/issues/17979

(스레드의 마지막 주석으로 스크롤)

최신 정보

5.6.0에서 실제로 수정되었습니다. 5.4.2에 크로스 플랫폼 버그가있어 문제가 계속 발생했습니다.

https://github.com/npm/npm/issues/18712

업데이트 2

내 대답보기 : https://stackoverflow.com/a/53680257/1611058

npm ci 기존 프로젝트를 지금 설치할 때 사용해야하는 명령입니다.


5
5.4.2를 사용하고 있는데 여전히 패키지-lock.json이 수정됩니다 npm i. 예를 들어, 지원하지 않는 컴퓨터 에서 모듈 fsevents을 제거하면 제거 npm i된 컴퓨터에서 fsevents다시 추가됩니다 npm i.
hrdwdmrbl

그런 다음 npm GitHub 리포지토리에서이를 설명하는 새로운 문제를 제기해야합니다. 그것이 작동한다고 말하는 방식으로 작동하지 않으면 긴급히 수정 해야하는 우선 순위가 높은 버그로 간주됩니다.
Daniel Tonon

@hrdwdmrbl 저도 같은보고 있어요 fsevents내에서 드롭 package-lock.jsonnpm@5.5맥 OS X의 기여와 협력하면서. 이슈를 열지 않았다면 내가 할 것입니다.
AL the X

@hrdwdmrbl 내 의견을 남긴 후 (및 관련 문제의 긴 스레드) 내 의견을 업데이트하기 위해 SO로 돌아 오는 것을 잊었습니다. 돌아 와줘서 고마워 다 괜찮아
AL

4

아마도 다음과 같은 것이 있습니다.

"typescript":"~2.1.6"

귀하의 package.jsonnpm이 최신 부 버전으로 업데이트되는 경우2.4.1

편집 : OP의 질문

그러나 "npm install"이 잠금 파일을 변경하는 이유는 설명하지 않습니다. 잠금 파일이 재현 가능한 빌드를 작성하기위한 것이 아닙니까? 그렇다면 semver 값에 관계없이 여전히 동일한 2.1.6 버전을 사용해야합니다.

대답:

이것은 전체 종속성 트리를 잠그기위한 것입니다. typescript v2.4.1필요 하다고 가정 해 봅시다 widget ~v1.0.0. 당신이 npm을 설치할 때 그것을 잡는다 widget v1.0.0. 나중에 동료 개발자 (또는 CI 빌드)에서 npm을 설치하고 로 업데이트 typescript v2.4.1되었지만 widget로 업데이트되었습니다 widget v1.0.1. 이제 노드 모듈이 동기화되지 않았습니다. 이것이 package-lock.json방지하는 것입니다.

또는 더 일반적으로 :

예를 들어,

패키지 A :

{ "name": "A", "version": "0.1.0", "dependencies": { "B": "<0.1.0"}}

패키지 B :

{ "name": "B", "version": "0.0.1", "dependencies": { "C": "<0.1.0"}}

패키지 C :

{ "name": "C", "version": "0.0.1"}

이들이 레지스트리에서 사용 가능한 A, B 및 C의 유일한 버전 인 경우 일반 npm 설치 A가 설치됩니다.

A@0.1.0-B@0.0.1-C@0.0.1

그러나 B@0.0.2가 게시되면 새로운 npm 설치 A가 설치됩니다.

새 버전이 B의 종속성을 수정하지 않았다고 가정하면 A@0.1.0-B@0.0.2-C@0.0.1입니다. 물론, 새로운 버전의 B는 새로운 버전의 C와 수많은 새로운 의존성을 포함 할 수 있습니다. 이러한 변경이 바람직하지 않은 경우 A 작성자는 B@0.0.1에 대한 종속성을 지정할 수 있습니다. 그러나 A의 저자와 B의 저자가 같은 사람이 아닌 경우 A의 저자는 B가 전혀 바뀌지 않았을 때 새로 게시 된 C 버전을 가져오고 싶지 않다고 말할 방법이 없습니다.


OP 질문 2 : 알겠습니다. 당신이 말하는 것은 잠금 파일이 보조 종속성의 버전을 지정하지만 최상위 종속성을 결정하기 위해 package.json의 퍼지 일치에 여전히 의존한다는 것입니다. 정확합니까?

답변 : 아니요. package-lock은에서 설명한 루트 패키지를 포함하여 전체 패키지 트리를 잠급니다 package.json. 만약typescript에 잠겨2.4.1 당신에 package-lock.json이 변경 될 때까지, 그 방법을 유지해야한다. 그리고 내일 typescript출시 버전 이라고 말해 보자 2.4.2. 지점을 체크 아웃하고 실행 npm install하면 npm은 잠금 파일을 존중하고 설치 2.4.1합니다.

package-lock.json:

npm이 node_modules 트리 또는 package.json을 수정하는 모든 작업에 대해 package-lock.json이 자동으로 생성됩니다. 후속 설치가 중간 종속성 업데이트에 관계없이 동일한 트리를 생성 할 수 있도록 생성 된 정확한 트리를 설명합니다.

이 파일은 소스 리포지토리에 커밋되어 다양한 목적으로 사용됩니다.

팀원, 배포 및 지속적인 통합이 정확히 동일한 종속성을 설치하도록 종속성 트리의 단일 표현을 설명하십시오.

디렉토리 자체를 커밋하지 않고도 사용자가 node_modules의 이전 상태로 "시간 여행"할 수있는 기능을 제공합니다.

읽을 수있는 소스 제어 차이를 통해 트리 변경의 가시성을 향상시킵니다.

또한 npm이 이전에 설치된 패키지에 대해 반복되는 메타 데이터 분석을 건너 뛰도록하여 설치 프로세스를 최적화하십시오.

https://docs.npmjs.com/files/package-lock.json


29
그러나 "npm install"이 잠금 파일을 변경하는 이유는 설명하지 않습니다. 잠금 파일이 재현 가능한 빌드를 작성하기위한 것이 아닙니까? 그렇다면 semver 값에 관계없이 여전히 동일한 2.1.6 버전을 사용해야합니다.
Viper Bailey

3
그리고 그것이 제가 말하는 것입니다. 패키지 잠금 파일에 typescript@2.1.6이 표시되지만 npm install을 실행하면 항목이 typescript@2.4.1로 바뀝니다.
Viper Bailey

5
이 같은 문제가 발생했습니다. CI / CD에서 package-lock.json가져 오기가 풀다운 된 다음 실행 npm install되지만 package-lock.json파일이 수정되므로 다음 변경 사항을 가져 오기 전에 재설정을 수행해야합니다.
BayssMekanique

15
나는 그것을 얻지 못한다. 후속 설치로 여전히 업그레이드를 수행 할 수있는 경우이 파일은 어떻게 "잠금"파일입니까?!
Ross Allen

5
나는 그들이이 파일을 "info"와 "lock"으로 생각한다는 생각으로 시작한 다음 "info"파일 만 결정하기로했습니다. 더 나은 이름은 "package-info.json"입니다. "package-lock.json"에서 설치하고 "package.json"을 무시하는 "npm install -lock"을 갖고 싶습니다.
Jeremy Chone

2

아마도 당신은 이와 같은 것을 사용해야합니다

npm ci

사용하는 대신 npm install 패키지 버전을 변경하지 않으려는 경우 하십시오.

공식 문서에 따르면, 모두 npm installnpm ci프로젝트에 필요한 종속성을 설치합니다.

가장 큰 차이점은 npm install패키지를 packge.json참조로 설치한다는 것 입니다. 어디의 경우 npm ci, 그것은 복용 패키지 설치 않습니다 package-lock.json있는지 정확한 패키지가 설치 될 때마다 만드는 참조로를.


1

https://github.com/npm/npm/issues/18712에 github 페이지에 공개 문제가 있습니다.

이 문제는 개발자가 다른 운영 체제를 사용하는 경우 가장 심각합니다.


패키지 잠금의 재 작성은 의도 된 것이며 문제는 이것의 결과가 아닙니다
.

0

편집 : "lock"이라는 이름은 까다로운 것으로 NPM은 Yarn을 따라 잡으려고합니다. 잠긴 파일이 아닙니다. package.json"고정"되면 node_modules 폴더 트리가 생성되고 해당 트리가로 작성된 사용자 수정 파일입니다 package-lock.json. 따라서 당신은 다른 방법으로 의존성 버전 package.json을 항상 가져 와서 package-lock.json호출해야합니다.package-tree.json

(이것은 많은 downvotes 후에 내 대답이 더 명확 해지기를 바랍니다)


간단한 대답 : package.json평소와 같이 종속성을 유지하면서 package-lock.json"정확하고 더 중요하게 재현 가능한 node_modules 트리"( npm 문서 자체 에서 가져옴) )입니다.

까다로운 이름은 NPM이 Yarn을 따라 잡으려고 노력하는 것입니다.


1
npm install을 실행하면 패키지 잠금이 업데이트됩니다.
Jean-Baptiste
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.