npm 패키지를 직접 개발해서 배포하던 도중 스스로 원하는 요구사항이 생겼습니다.
package.json이 있는 프로젝트 디렉토리 루트 전체가 아닌 특정 하위 디렉토리만 배포하고 싶다!
먼저 프로젝트 디렉토리가 아래와 같이 구성되어 있었습니다.
📂project
📂src
🗒️package.json
🗒️.gitignore
🗒️.npmignore
🗒️README.md
...
그럼 패키지를 배포했을 때 📂project
가 루트가 되어 패키지가 되는 것이 아닌 하위 폴더, 이를테면..
📂project
📂dist
📂src
🗒️package.json
🗒️.gitignore
🗒️.npmignore
🗒️README.md
...
저 📂dist
폴더가 루트가 되어 📂dist
폴더 안에 있는 파일로만 구성된 패키지를 추출해 배포하고 싶었던 것이죠.
근데 저는 왜 그런 생각을 하게 된걸까요?
- 내가 배포할 패키지는 타 애플리케이션 개발 시 스크립트단에서 사용되는 라이브러리가 아니었다. 하나의 프로그램 자체였다.
- 그리고 나는 이를 typescript를 사용해서 개발했다.
위의 이유로 typescipt 코드가 패키지에 굳이 포함될 필요가 없었던 것이죠. 배포한 프로그램을 실행시킬 수 있는 javascript 코드만 있으면 됐으니까요.
다시 프로젝트 구조로 돌아와서 더 자세하게 그림을 그리면 아래와 같습니다.
배포하고자 하는 파일 및 폴더는 굵게 표시했습니다.
📂project
📂dist
📂bin
🗒️cli.js
📂lib
🗒️index.js
...
📂src
📂bin
🗒️cli.ts
📂lib
🗒️index.ts
...
🗒️package.json
🗒️.gitignore
🗒️.npmignore
🗒️README.md
...
제가 직접 작성하게 되는 것은 🗒️cli.ts
나 🗒️index.ts
등과 같은 typescript 코드입니다.
개발을 완료한 후 이 typescipt로 작성된 스크립트를 컴파일하면 javascript 파일이 생성되고 이들을 📂dist
폴더에 넣었습니다.
그리고 이 📂dist
폴더는 git repository에는 올라갈 필요가 없으므로 .gitignore
에 추가했습니다.
그럼 저는 개발한 애플리케이션이 실제로 돌아가기 위한 코드인 📂dist
폴더 안에 있는 javascript 녀석들만 배포하면 되는 것이죠!
열심히 구글링하며 방법을 강구했지만 package.json
에 특정 하위 디렉토리를 루트로 배포할 수 있는 설정은 따로 없는 것 같았습니다..ㅠ
그래서 먼저 실행에 옮긴 방법은 📂src
폴더를 .npmignore
에 넣는 것이었습니다.
그러나 이 방법은 조금 멋이 없었죠..
일단 내가 패키지를 배포했을 때 원했던 모습은 이랬습니다.
📂my-package
📂bin
🗒️cli.js
📂lib
🗒️index.js
...
...
루트 바로 하위에 📂bin
, 📂lib
폴더가 위치하는 모습이죠.
그럼 위와 같은 모습으로 패키지가 구성되도록 하기 위해서는 빌드된 javascript를 📂dist
폴더에 넣는 것이 아니라 📂project
루트 바로 하위에 넣어야 했습니다.
아래처럼 말이죠.
📂project
📂bin
🗒️cli.js
📂lib
🗒️index.js
...
📂src
📂bin
🗒️cli.ts
📂lib
🗒️index.ts
...
🗒️package.json
🗒️.gitignore
🗒️.npmignore
🗒️README.md
...
그리고 아까 .gitigonre
에 작성해주었던 📂dist
폴더를 지우고 📂bin
과 📂lib
를 추가해주었습니다.
그럼 원하는 모양으로 패키지 배포가 가능합니다. 그러나 📂project
폴더 바로 아래에 뭔가가 많아졌네요.
만약 📂bin
, 📂lib
뿐 아니라 더 많은 폴더나 파일이 패키지에 포함된다면 더더욱 많아질 것이고 관리하기 복잡하다고 느낄 수 있겠죠.
그리고 빌드된 파일은 확실하게 📂dist
와 같은 하나의 폴더에 생성되는 것이 깔끔합니다.
그렇다면 역시 처음 생각한대로 📂dist
폴더를 루트로 배포해야 합니다. 역시 그게 제일 깔끔해요.
근데 package.json
에 그렇게 할 수 있는 설정이 없다며???
뭐 그럼 다른 방법이 있지 않겠습니까?ㅎㅎ
역시 있었습니당!ㅋㅋ 아래 링크를 참고했어요.
https://newbedev.com/how-to-npm-publish-specific-folder-but-as-package-root
영문이라 읽기 싫으신 분들이 있을 수 있기에 저 방법을 따라한대로 적어보자면...
먼저 프로젝트 루트 디렉토리에 setupPackage.js
를 작성합니다.
const fs = require('fs');
function main() {
const source = fs.readFileSync(__dirname + '\\package.json').toString('utf-8');
const sourceObj = JSON.parse(source);
sourceObj.scripts = {};
sourceObj.devDependencies = {};
if (sourceObj.main.startsWith('\\dist\\')) {
sourceObj.main = sourceObj.main.slice(5);
}
fs.writeFileSync(__dirname + '\\dist\\package.json', Buffer.from(JSON.stringify(sourceObj, null, 2), 'utf-8'));
fs.writeFileSync(__dirname + '\\dist\\version.txt', Buffer.from(sourceObj.version, 'utf-8'));
fs.copyFileSync(__dirname + '\\.npmignore', __dirname + '\\dist\\.npmignore');
}
main();
필자의 경우 📂dist
폴더를 루트로 배포하고자 하기 때문에 코드에 \\dist\\
와 같이 작성하였으나 다른 폴더 이름을 사용하게 된다면 코드에서 수정해주어야 해요.
코드가 수행하는 작업은 📂dist
폴더에 package.json
과 .npmigonre
을 복사하는 것입니다. 이때 package.json
에서 배포시 불필요한 script
와 devDependencies
속성은 제거하게 되죠.
그리고 package.json
의 scripts
에 "build-publish"
명령어를 추가합니다.
"scripts": {
...
"build": "tsc -p .",
"build-publish": "npm run build && node setupPackage.js && cd dist && npm publish"
},
이후 터미널에
$ npm run build-publish
커맨드를 입력하면 배포에 필요한 package.json
과 .npmigonre
파일이 📂dist
폴더에 복사되고 📂dist
폴더에서 npm-publish
가 수행됩니다.
그럼 처음에 원했던대로 📂dist
폴더를 루트로 즉 아래와 같은 모양으로 배포가 성공적으로 된 것을 확인할 수 있습니다!
📂my-package
📂bin
🗒️cli.js
📂lib
🗒️index.js
...
...