npm은 프런트 엔드 개발자가 널리 사용하는 패키지 관리 도구입니다. 프로젝트에서 package.json은 프로젝트가 의존하는 npm 패키지의 구성을 관리하는 데 사용됩니다. package.json은 프로젝트의 패키지 종속성을 설명하는 것 외에도 "의미적 버전 관리 규칙"을 사용하여 프로젝트의 종속 패키지 버전을 표시할 수 있으므로 빌드를 다른 개발자와 쉽게 공유할 수 있습니다. 재사용. 이 기사는 주로 최신 npm 및 node 버전과 결합된 최근 사례에서 시작하여 package.json의 몇 가지 일반적인 구성과 표준화된 package.json을 작성하는 방법을 소개합니다.
nodejs 프로젝트에서 package.json은 종속성을 관리하는 구성 파일입니다. 일반적으로 nodejs 프로젝트를 초기화할 때 다음을 전달합니다.
npm init
그러면 3이 생성됩니다. 디렉터리/파일, node_modules, package.json 및 package.lock.json. package.json의 내용은 다음과 같습니다.
{ "name": "프로젝트 이름", "버전": "1.0.0", "description": "프로젝트 설명", "메인": "app.js", "스크립트": { "test": "echo "오류: 지정된 테스트가 없습니다" && 종료 1", }, "author": "저자 이름", "라이센스": "ISC", "종속성": { "종속성1": "^1.4.0", "의존성2": "^1.5.2" } }
위에서 볼 수 있듯이 package.json에는 프로젝트 자체의 메타데이터와 프로젝트의 하위 종속성 정보(예: 종속성 등)가 포함되어 있습니다.
npm init 과정에서 package.json 파일뿐만 아니라 package-lock.json 파일도 생성되는 것을 확인했습니다. 그렇다면 package.json을 지울 때 package-lock.json 파일을 생성해야 하는 이유는 무엇입니까? 기본적으로 package-lock.json 파일은 버전을 잠그기 위한 것입니다. package.json에 지정된 하위 npm 패키지는 다음과 같습니다. 실제 설치에서는 버전이 다음보다 높습니다. 반응, package.json이 요구 사항을 충족합니다. 이는 동일한 package.json 파일에 따라 두 번 설치된 하위 종속성 버전의 일관성이 보장될 수 없음을 의미합니다.
package-lock 파일은 아래와 같으며, 하위 종속성 dependency1에 해당 버전이 자세히 지정되어 있습니다. 잠금 버전 역할을 합니다.
{ "name": "프로젝트 이름", "버전": "1.0.0", "잠금 파일 버전": 1, "요구하다": 사실, "종속성": { "종속성1": { "버전": "1.4.0", "해결됨": "https://registry.npmjs.org/dependent1/-/dependent1-1.4.0.tgz", "진실성": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, "의존성2": { "버전": "1.5.2", "해결됨": "https://registry.npmjs.org/dependent2/-/dependent2-1.5.2.tgz", "진실성": "sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ==" } } }
이번 장에서는 package.json에서 일반적으로 사용되는 구성 속성에 대해 설명합니다. 이름, 버전 등과 같은 속성은 너무 간단하므로 하나씩 소개하지 않습니다. 이 장에서는 주로 스크립트, 빈, 작업 공간 속성을 소개합니다.
npm의 script 태그를 사용하여 스크립트를 정의합니다. npm run이 지정될 때마다 쉘 스크립트가 자동으로 생성됩니다. 여기서 주목해야 할 점은 npm run으로 생성된 새 쉘이 node_modules/.bin을 저장한다는 것입니다. 로컬 디렉토리. PATH 변수에 하위 디렉토리를 추가합니다.
이는 현재 디렉터리의 node_modules/.bin 하위 디렉터리에 있는 모든 스크립트를 경로를 추가하지 않고 스크립트 이름으로 직접 호출할 수 있음을 의미합니다. 예를 들어, 현재 프로젝트의 종속성이 esbuild를 포함하는 경우 esbuild xxx를 직접 작성하면 됩니다.
{ // ... "스크립트": { "build": "esbuild index.js", } }
{ // ... "스크립트": { "빌드": "./node_modules/.bin/esbuild index.js" } }
위의 두 가지 작성 방법은 동일합니다.
bin 속성은 실행 파일을 전역 환경에 로드하는 데 사용됩니다. bin 필드가 있는 npm 패키지가 지정되면 전역 환경에 로드되고 파일은 별칭을 통해 실행될 수 있습니다.
예를 들어 @bytepack/cli의 npm 패키지:
"bin": { "bytepack": "./bin/index.js" },@bytepack/cli가 전역적으로 설치되면
bytepack -v
와 같은 bytepack을 통해 해당 명령을 직접 실행할 수 있습니다.
//1.11.0을 표시합니다.
글로벌로 설치되지 않은 경우 프로젝트의 node_module/.bin 디렉터리에 자동으로 연결됩니다. 앞서 소개한 스크립트 태그에서 설명한 것과 일관되게 별칭과 함께 직접 사용할 수 있습니다.
프로젝트가 너무 커지면 최근 모노레포(monorepo)가 점점 인기를 얻고 있습니다. 모노레포의 경우 초기에는 원사 작업공간을 사용하지 않았습니다. 이제 npm은 공식적으로 작업공간을 최상위 루트 패키지에서 관리하는 방법에 대한 문제를 해결합니다. 로컬 파일 시스템의 작업 공간 선언 디렉터리에서 패키지는 최상위 루트 패키지의 node_modules에 소프트 링크됩니다.
공식 웹사이트의 예를 직접 들어보겠습니다.
{ "이름": "내 프로젝트", "작업공간": [ "패키지/a" ] }
my-project라는 npm 패키지에는 작업 공간으로 구성된 디렉터리가 있습니다.
. +-- 패키지.json +-- index.js `-- 패키지 +-- 아 | `-- package.json
및 my-project라는 최상위 루트 패키지에는 패키지/하위 패키지가 있습니다. 이때 npm을 설치하면 루트 패키지의 node_modules에 설치된 npm 패키지 a가 로컬 package/a를 가리킵니다
. +-- node_modules | `-- 패키지/a -> ../패키지/a +-- 패키지-lock.json +-- 패키지.json `-- 패키지 +-- 아 | `-- package.json
위--
packages/a -> ../packages/a는
node_modules의 a에서 로컬 npm 패키지로의 소프트 링크를 나타냅니다
package.json 환경 관련 속성이 있는 공통 환경은 기본적으로 위의 내용은 브라우저 환경과 노드 환경 두 가지로 구분됩니다. 다음으로 package.json의 환경과 관련된 구성 속성을 살펴보겠습니다. 환경의 정의를 간단히 설명하면 다음과 같습니다.
commonjs, CMD, UMD, AMD 및 ES 모듈이 포함됩니다. 처음에는 node에서 commonjs 필드만 지원되었지만 node13.2.0부터 node에서는 ES 모듈 사양을 공식적으로 지원합니다. field는 npm 패키지가 따르는 모듈 사양을 선언하기 위해 package.json에서 사용될 수 있습니다.
//패키지.json { 이름: "일부 패키지", 유형: "모듈"||"commonjs" }type이
지정
되지 않은 경우 type의 기본값은 commonjs이지만 모든 npm 패키지에서
type 필드에 값을 지정하는 경우 ESModule 사양을 사용하는 것이
. type 필드를 지정하면 디렉터리의 모든 .js가 사용됩니다. 접미사로 끝나는 파일은 모듈화 사양을 지정할
수 있는 type 외에도 파일 뒤에 오는 모듈화 사양을 지정합니다
.mjs로 끝나는 파일은 사용되는 ESModule 사양입니다. .cjs는 commonjs 사양
3.2 기본
npm 패키지의 항목 파일을 정의합니다.
이 세 필드의 사용 시나리오와 이 세 필드가 동시에 존재할 때 우선순위를 살펴보겠습니다.
deco1,----- dist
라는 npm 패키지가 있다고 가정해 보겠습니다.
|-- index.browser.js |-- index.browser.mjs |-- index.js |-- index.mjs
의 package.json은 main, module 및 browser 세 필드를 동시에 지정합니다.
"main": "dist/index.js", // main "모듈": "dist/index.mjs", // 모듈 // 브라우저는 기본/모듈 필드에 해당하는 매핑 개체로 정의되거나 문자열 "browser"로 직접 정의될 수 있습니다. "./dist/index.js": "./dist/index.browser.js", // 브라우저+cjs "./dist/index.mjs": "./dist/index.browser.mjs" // 브라우저+mjs }, // "browser": "./dist/index.browser.js" // 브라우저는
기본적으로 빌드되어 사용됩니다. 예를 들어 프로젝트에서 이 npm 패키지를 참조하는 경우:
import deco from 'demo'
위 빌드 후 빌드 도구를 통한 코드, 모듈 로딩 순서는
browser+mjs > module > browser+cjs > main입니다.
이 로딩 순서는 webapck, esbuild 등과 같은 대부분의 빌드 도구의 기본 로딩 순서입니다. 이 로드 순서는 해당 구성을 통해 수정할 수 있지만 대부분의 시나리오에서는 여전히 기본 로드 순서를 따릅니다.
내보내기 필드가 package.json에 정의된 경우 이 필드에 정의된 콘텐츠는 npm 패키지의 실제 전체 내보내기이며 우선순위는 기본 및 파일 필드보다 높습니다.
예를 들어:
{ "이름": "패키지", "내보내기": { ".": "./main.mjs", "./foo": "./foo.js" } }
import { Something } from "pkg"; // "pkg/main.mjs"에서const { Something } = require("pkg/foo"); //
위의 예에서
require("pkg/foo.js")
내보내기는 다른 경로로 내보내기를 정의할 수 있는 것 같습니다. 내보내기가 존재하는 경우 이전에 유효한 파일 디렉터리는 내보내기에 지정되지 않았기 때문에 require('pkg/package.json')와 같은 모든 곳에서 유효하지 않으며 오류가 보고됩니다.
내보내기의 또 다른 가장 큰 기능은 조건부 참조입니다. 예를 들어, 다양한 참조 방법이나 모듈 유형을 기반으로 다양한 항목 파일을 참조하도록 npm 패키지를 지정할 수 있습니다.
//패키지.json { "이름":"패키지", "메인": "./main-require.cjs", "내보내기": { "가져오기": "./main-module.js", "require": "./main-require.cjs" }, "유형": "모듈" }
위의 예에서는
const p = require('pkg')를 통해
"./main-require.cjs"를 참조하면
됩니다.import p from 'pkg'를
전달하면
참조는 "./main-module.js" 입니다
. 마지막으로 주의할 점은 내보내기 속성이 존재하는 경우 내보내기 속성이 메인보다 우선순위가 높을 뿐만 아니라 모듈 및 브라우저 필드보다 높습니다.
package.json의 종속성 관련 구성 속성에는 종속성, devDependency, PeerDependency, PeerDependencyMeta 등이 포함됩니다.
종속성은 프로젝트 종속성이며 devDependency는 개발에 필요한 모듈이므로 개발 프로세스 중에 필요에 따라 설치하여 개발 효율성을 향상시킬 수 있습니다. 여기서 주목해야 할 것은 자신의 프로젝트에서 가능한 한 표준적으로 사용하도록 노력하는 것입니다. 예를 들어 webpack, babel 등은 개발 종속성이지 프로젝트 자체의 종속성에 넣지 마십시오.
종속성 종속성 및 devDependency 외에도 이 문서에서는 PeerDependency 및 PeerDependencyMeta에 중점을 둡니다.
피어Dependency는 package.json의 종속성으로, 핵심 라이브러리가 여러 번 다운로드되고 핵심 라이브러리 버전을 통합하는 문제를 해결할 수 있습니다.
//패키지/패키지 -----노드_모듈 |-- npm-a -> 반응, 반응 돔에 따라 다름 |-- npm-b -> 반응, 반응 돔에 따라 다름 |-- index.js
예를 들어 위의 예에서 하위 npm 패키지 a와 b가 모두 React 및 React-dom에서 나온 경우 하위 npm 패키지 a 및 b의 package.json에서 PeerDependicies를 선언하면 b, 해당 종속성은 다시 설치되지 않습니다.
주목해야 할 두 가지 사항이 있습니다.
"peerDependency": {
"반응": "^16.8.3 || ^17 || ^18" }, "peerDependencyMeta": { "반응 돔": { "선택 사항": 사실 }, "반응 네이티브": { "선택 사항": 사실 } }
"react-dom" 및 "react-native"는 여기 PeerDependencyMeta에 지정되어 있으며 선택 사항이므로 "react-dom" 및 "react-native"가 프로젝트에 설치되어 있지 않으면 오류가 보고되지 않습니다.
실제로 PeerDependencyMeta를 통해 제한을 해제했다는 점은 주목할 가치가 있지만 A 또는 B인 시나리오가 종종 있습니다. 예를 들어 위의 예에서 필요한 것은 "react-dom" 및 "react-native"입니다. 하나를 설치해야 하지만 실제로 위 명령문으로는 이 프롬프트를 얻을 수 없습니다.
tsc에서 사용되는 유형, 빌드 도구에서 사용되는 sideEffects, git에서 사용되는 husky 및 eslint에서 사용되는 eslintIgnore와 같은 3자 속성도 많이 있습니다. 확장 프로그램은 특정 개발 도구를 위한 것이므로 여기서는 예제를 제공하지 않겠습니다.