วิธีการ npm เผยแพร่โฟลเดอร์เฉพาะ แต่เป็นแพ็กเกจรูท


91

distผมมีโครงการที่มีงานอึกสำหรับการสร้างและบรรจุภัณฑ์แหล่งที่มาและการเปิดตัวในไดเรกทอรีที่เรียกว่า เป้าหมายของฉันคือเผยแพร่เป็นแพ็คเกจ npm แต่มีเพียงโฟลเดอร์ dist ของฉันเท่านั้น เอกสาร NPMบอกว่าผมสามารถใช้filesแท็กเพื่อระบุไฟล์ที่จะส่งออก มันได้ผล. แต่เอกสารยังบอกด้วยว่า:

หากคุณตั้งชื่อโฟลเดอร์ในอาร์เรย์โฟลเดอร์นั้นจะรวมไฟล์ไว้ในโฟลเดอร์นั้นด้วย

ผลลัพธ์คือแพ็กเกจ npm ซึ่ง node_modules มีลักษณะดังนี้:

สร้างแพ็คเกจ npm

แต่ฉันต้องการดูไฟล์ทั้งหมดของฉันที่รูทของแพ็คเกจ (ไม่มีdistโฟลเดอร์นั้น) index.jsไฟล์ของฉันอยู่ในdistโฟลเดอร์ แต่ควรอยู่ที่รูท ฉันพยายามตั้งค่าแท็กfilesเป็น/dist/**/*แต่ไม่ได้ผล

ฉันจะบรรลุได้อย่างไร?

คำตอบ:


45

ฉันมีความปรารถนาเดียวกัน แต่ฉันคิดว่าไม่มีทางที่จะทำสิ่งนี้ให้สำเร็จได้ด้วยการใช้เครื่องมือ npmเท่านั้น สามารถใช้สคริปต์ / เครื่องมืออื่นเพื่อจัดเรียงแพ็คเกจของคุณ

โซลูชันทางเลือก

ขณะนี้ฉันกำลังคัดลอกpackage.jsonลงในdistโฟลเดอร์แล้วเรียกใช้npm packภายในdistโฟลเดอร์ ฉันคิดว่านี่เป็นการจัดเตรียมแพ็คเกจที่ต้องการเป็นหลัก

นี่คือบางส่วนอ่านที่เกี่ยวข้องกับการออกแบบ NPM นี้: ทำไมไม่มี Directories.lib ในโหนด

นอกจากนี้ยังน่าสนใจที่จะทราบว่า jspm ไม่เคารพdirectories.libตัวเลือกในpackage.jsonและจัดเรียงไฟล์ใหม่เมื่อแก้ไขแพ็คเกจ npm ทั้งหมดนี้เกิดขึ้นสำหรับฉันเพราะฉันต้องการสร้างไลบรารีทั่วไปที่สามารถใช้งานได้โดย jspm หรือ npm / webpack


1
(ทำไมไม่มี Directories.lib ... ) เป็นลิงก์ที่ตายแล้ว
Shanimal

1
ทำไมไม่มี Directories.lib ใน Node บอกว่าถ้าคุณไม่ทำในแบบของเราคุณควรรู้สึกเจ็บปวด ทั้งหมดนี้สร้างความจำเป็นในการใช้เครื่องมือในการแก้ไขปัญหานี้
Brian Takita

6
ฉันเชื่อว่าคำตอบนี้ล้าสมัย ตามคำตอบด้านล่างหมายเหตุโดยใช้npm packpackage.json filesและmainfields และ.npmignoreให้ทุกสิ่งที่จำเป็นแก่นักพัฒนาในการสร้างแพ็คเกจจากไดเร็กทอรีที่ติดตั้งเฉพาะ
Jefftopia

1
สร้างสคริปต์บางส่วนเพื่อปรับปรุง / บังคับใช้รูปแบบ "เผยแพร่ย่อย"
micimize

2
ใครสามารถโพสต์วิธีแก้ปัญหาได้โดยใช้ npmignore ไฟล์และคุณสมบัติหลักใน package.json ฉันต้องการย้ายไฟล์ทั้งหมดไปที่รูทและไม่มีโฟลเดอร์ dist
Angad

17

ฉันมีปัญหาคล้ายกับโปสเตอร์ต้นฉบับ (@robsonrosa) ในกรณีของฉันฉันใช้ typecript ซึ่งรวบรวมไปยังdistไดเร็กทอรี ในขณะที่ฉันสามารถสร้าง typescript คอมไพล์ไปยังไดเร็กทอรีรูทได้ฉันคิดว่าทางออกที่ดีที่สุดคือสร้างpackage.jsonไฟล์แยกต่างหากในไดเร็กทอรี dist
สิ่งนี้คล้ายกับคำแนะนำของ @scvnc ในการคัดลอกpackage.jsonแต่ด้วยการบิด:

ในฐานะส่วนหนึ่งของกระบวนการpackage.jsonแพ็กเกจคุณควรสร้างแพ็กเกจที่อิง แต่แตกต่างจากpackage.jsonไฟล์หลักในไดเร็กทอรีราก

เหตุผล:

  • package.jsonไฟล์รูทคือไฟล์การพัฒนา อาจมีสคริปต์หรือการอ้างอิงการพัฒนาที่ไม่มีประโยชน์สำหรับผู้ใช้แพ็กเกจ แต่อาจก่อให้เกิดปัญหาด้านความปลอดภัยสำหรับคุณ package.jsonขั้นตอนการบรรจุภัณฑ์ของคุณอาจมีรหัสที่แถบข้อมูลว่าจากการผลิต
  • คุณอาจต้องการปรับใช้แพ็กเกจของคุณกับสภาพแวดล้อมที่แตกต่างกันซึ่งอาจต้องใช้ไฟล์แพ็กเกจที่แตกต่างกัน (เช่นคุณอาจต้องการมีเวอร์ชันหรือการอ้างอิงที่ต่างกัน)

- แก้ไข -

ฉันถูกขอให้แก้ปัญหาในความคิดเห็น นี่คือรหัสบางส่วนที่ฉันใช้ สิ่งนี้ควรถือเป็นตัวอย่างที่ไม่ได้หมายถึงทั่วไปและเป็นข้อมูลเฉพาะสำหรับโครงการของฉัน

การตั้งค่าของฉัน:

package.json         - main package.json with dev dependencies and useful scripts.
.npmignore           - files to ignore; copied to 'dist' directory as part of the setup.
/src                 - directory where my typescript code resides.
/src/SetupPackage.ts - bit of code used to setup the package.
/dist                - destination directory for the compiled javascript files.

ฉันต้องการทำแพ็กเกจเฉพาะdistไดเร็กทอรีและไดเร็กทอรีควรเป็นไดเร็กทอรีรูทในแพ็กเกจ

ไฟล์SetupPackage.tsในsrcไดเร็กทอรีของฉันจะถูกคอมไพล์SetupPackage.jsในdistไดเร็กทอรีโดย typescript:

import fs from "fs";

// DO NOT DELETE THIS FILE
// This file is used by build system to build a clean npm package with the compiled js files in the root of the package.
// It will not be included in the npm package.

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 + "/package.json", Buffer.from(JSON.stringify(sourceObj, null, 2), "utf-8") );
    fs.writeFileSync(__dirname + "/version.txt", Buffer.from(sourceObj.version, "utf-8") );

    fs.copyFileSync(__dirname + "/../.npmignore", __dirname + "/.npmignore");
}

main();

ไฟล์นี้:

  • คัดลอกรูทpackage.jsonแต่ลบสคริปต์และการอ้างอิง dev ซึ่งไม่จำเป็นในแพ็กเกจ นอกจากนี้ยังแก้ไขจุดเข้าหลักไปยังแพ็กเกจ
  • เขียนรุ่นของแพคเกจจากไปยังไฟล์ที่เรียกว่าpackage.jsonversion.txt
  • คัดลอก.npmignoreแพ็กเกจจากรูท

เนื้อหา. npmignore คือ:

*.map
*.spec.*
SetupPackage.*
version.txt

เช่นการทดสอบหน่วย (ไฟล์ข้อมูลจำเพาะ) และไฟล์แม็พ typescript จะถูกละเว้นเช่นเดียวกับSetupPackage.jsไฟล์และversion.txtไฟล์ที่สร้างขึ้น สิ่งนี้ทำให้แพ็คเกจสะอาด

ในที่สุดpackage.jsonไฟล์หลักจะมีสคริปต์ต่อไปนี้สำหรับใช้โดยระบบบิลด์ (สมมติว่าshใช้เป็นเชลล์)

"scripts": {
    "compile": "tsc",
    "clean": "rm -rf dist",
    "prebuildpackage": "npm run clean && npm run compile && node dist/SetupPackage.js",
    "buildpackage": "cd dist && npm pack"
  },

ในการสร้างแพ็กเกจระบบบิลด์จะโคลน repo ทำnpm installแล้วรันnpm run buildpackageซึ่งจะ:

  • ลบdistไดเร็กทอรีเพื่อให้แน่ใจว่าคอมไพล์สะอาด
  • คอมไพล์โค้ด typescript ไปยัง javascript
  • เรียกใช้SetupPackage.jsไฟล์ที่เตรียมdistบรรจุภัณฑ์
  • ซีดีไปยังdistไดเร็กทอรีและสร้างแพ็คเกจที่นั่น

ฉันใช้version.txtไฟล์เป็นวิธีง่ายๆในการรับเวอร์ชันใน package.json และติดแท็ก repo ของฉัน มีวิธีอื่นอีกมากมายในการทำเช่นนี้หรือคุณอาจต้องการเพิ่มเวอร์ชันอัตโนมัติ ลบสิ่งนี้ออกจากSetupPackage.tsและ.npmignoreหากไม่มีประโยชน์กับคุณ


คำตอบนี้ดูเหมือนจะดีที่สุด แต่คุณมีวิธีแก้ปัญหาที่พร้อมหรือไม่?
yumaa

3
@yumaa ฉันแก้ไขคำตอบด้วยตัวอย่างที่เป็นรูปธรรม หวังว่าจะเป็นประโยชน์
Eli Algranti

1
ทำงานให้ฉันพร้อมกับการเปลี่ยนแปลงบางอย่าง SetupPackage.tsไฟล์ปัจจุบันคัดลอกไฟล์ไปยังsrcไดเร็กทอรีแทนที่จะเป็นไฟล์dist. ขอบคุณ👍
Harinder Singh

15

หากโครงการของคุณมีคอมไพล์คุณสามารถใช้แฮ็คขนาดเล็ก เพิ่มสคริปต์ถัดไปใน package.json

    "prepublishOnly": "npm run build && cp -r ./lib/* . && rm -rf ./lib",
    "postpublish": "git clean -fd",

ตอนนี้เมื่อคุณเรียกใช้publishคำสั่ง NPM prepublishOnlyเกี่ยวข้องกับ สร้างไฟล์และบันทึกลงในlibโฟลเดอร์ (สคริปต์การสร้างขึ้นอยู่กับโครงการของคุณ) libไฟล์สำเนาคำสั่งต่อไปยังโฟลเดอร์รากและลบ หลังจากเผยแพร่postpublishสคริปต์จะส่งคืนโปรเจ็กต์กลับสู่สถานะก่อนหน้า


1
ฉันเป็นแฟนของโซลูชันนี้!
DanMad

7

ฉันขอแนะนำให้คุณใช้.npmignoreแทนการย้ายหรือคัดลอกสิ่งต่างๆโดยเฉพาะอย่างยิ่งหากคุณใช้ CI สำหรับการปรับใช้และเพิ่มไฟล์ที่คุณไม่ต้องการเผยแพร่

https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package

ตัวอย่าง:

#tests
test
coverage

#build tools
.travis.yml
.jenkins.yml
.codeclimate.yml

#linters
.jscsrc
.jshintrc
.eslintrc*

#editor settings
.idea
.editorconfig

อัปเดต:

หากคุณต้องการแยกรหัสของคุณเป็นแพ็คเกจ npm ที่แตกต่างกันโดยใช้ repo เดียวกันฉันได้พบกับโครงการนี้เมื่อเร็ว ๆ นี้: Lernaและดูดีจริงๆ

บางทีคุณควรจะดู


9
เรายังคงต้องปล่อยไฟล์ที่สร้างไว้ในไดเรกทอรีรากของแพ็คเกจ อาจเป็นที่อนุญาตสำหรับ CI สังเกตโพสต์จากบล็อกของ Isaac ที่ฉันเชื่อมโยงและบอกฉันว่าโซลูชันของคุณจะอนุญาตให้ใช้require('mypackage/foo')แทนได้อย่างไรrequire('mypackage/dist/foo')
scvnc

ฉันไม่ได้พยายามแก้ปัญหาตรงนี้ หากคุณต้องการแยกรหัสของคุณฉันเพิ่งพบโครงการนี้: lernajs.ioและดูดีมาก
Thram

พบเครื่องมืออื่นที่คุ้มค่า :) github.com/philcockfield/msync
Thram

ใช่ UI วัสดุใช้มันและฉันใช้สิ่งนี้ใน บริษัท สุดท้ายของฉันฉันพบว่ามันโอเค
นิ

6

วิธีนี้ใช้ได้ดีสำหรับฉัน

ซีดี TMPDIR; npm pack/path/to/package.json

Tarball จะสร้างภายในไดเร็กทอรี TMPDIR


^ คำตอบนี้ไม่ได้รับการประเมิน npm packบวกกับfilesฟิลด์package.json (หรือ.npmignore) ทำงานได้อย่างยอดเยี่ยม
Jefftopia

1

หากคุณ (และฉันแนะนำ) โดยใช้semantic-releaseให้เพิ่มpkgRootตัวเลือกใน.releaserc.jsonไฟล์:

{
  "pkgRoot": "dist",
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/npm",
    [
      "@semantic-release/exec",
      {
        "prepareCmd": "npx rjp package.json version nextRelease.version"
      }
    ],
    [
      "@semantic-release/git",
      {
        "assets": ["package.json"]
      }
    ],

  ],
}

ที่จะดูแลปัญหา ตรวจสอบให้แน่ใจว่าdistโฟลเดอร์ของคุณมีpackage.jsonไฟล์ คุณสามารถทำได้อย่างง่ายดายโดยการเพิ่มสคริปต์cpของคุณ postbuildติดตั้งrjp ด้วย


0

คุณต้องเผยแพร่distโฟลเดอร์

วิธีที่เป็นธรรมชาติในการบรรลุเป้าหมายนั้นตามแนวทางของ npm คือการเผยแพร่โฟลเดอร์ที่จะเป็นรูท มีหลายวิธีในการดำเนินการดังกล่าวขึ้นอยู่กับสภาพแวดล้อมสุดท้ายที่คุณต้องการใช้งาน:

  1. npm เผยแพร่ <folder>จากแพ็กเกจ repo ของคุณไปยังรีจิสตรี npm จากนั้นติดตั้งแพ็กเกจของคุณในโปรเจ็กต์อื่นเมื่อคุณติดตั้งแพ็กเกจอื่น npm publish distในกรณีของคุณมันจะเป็น
  2. npm ติดตั้ง <folder>ในโปรเจ็กต์อื่น ๆ หากคุณต้องการใช้แพ็คเกจของคุณในเครื่องเท่านั้น ในกรณีของคุณคุณไปที่โครงการอื่นและเรียกใช้npm install relative/path/to/dist
  3. npm เชื่อมโยงโฟลเดอร์ของคุณnode_modulesภายในกับโปรเจ็กต์อื่นในกรณีที่คุณต้องการให้การเปลี่ยนแปลงในแพ็กเกจเดิมของคุณปรากฏในโปรเจ็กต์อื่นทันที ในกรณีของคุณคุณเป็นครั้งแรกcd distและเรียกใช้npm linkแล้วไปที่โครงการอื่น ๆ npm link robsonrosa-ui-alertและการทำงาน

สิ่งที่ต้องมีก่อน : ในกรณีใด ๆ ข้างต้นก่อนที่จะเผยแพร่ / ติดตั้ง / ลิงก์คุณต้องใส่ไฟล์distที่เหมาะสมในโฟลเดอร์ของคุณเป็นอย่างน้อย package.jsonในกรณีของคุณคุณต้องกำหนดชื่อแพ็กเกจในไฟล์ package.json ของคุณเป็น"name": "robsonrosa-ui-alert". โดยทั่วไปคุณจะต้องมีไฟล์อื่น ๆ เช่น README.md หรือ LICENSE

ข้อสังเกตวิธีที่ 2 และ 3

โดยทั่วไปจะมีปัญหากับการอ้างอิงแพ็คเกจเมื่อคุณใช้แพ็คเกจที่ติดตั้งด้วยวิธีนี้ จะหลีกเลี่ยงมันครั้งแรกแพ็คแพคเกจที่มีnpm pack distแล้วติดตั้งแพคเกจในโครงการเป้าหมายจาก tarball npm install path/to/package-tarball.tgzบรรจุคือ

ตัวอย่างการทำงานอัตโนมัติ

คุณสามารถทำให้กระบวนการเผยแพร่โดยอัตโนมัติโดยใช้prepareสคริปต์รวมกับbuildสคริปต์ นอกจากนี้คุณสามารถป้องกันแพ็กเกจของคุณจากการเผยแพร่โดยไม่ตั้งใจของโฟลเดอร์รูทแพ็กเกจพร้อม"private": trueฟิลด์ที่ใส่ไว้ใน package.json ซึ่งอยู่ในไดเร็กทอรีรากของแพ็กเกจ repo ของคุณ นี่คือตัวอย่าง:

  "private": true,
  "scripts": {
    "build": "rm -rf dist && gulp build && cat ./package.json | grep -v '\"private\":' > dist/package.json",
    "prepare": "npm run build"
  },

ด้วยวิธีนี้คุณจะไม่เผยแพร่โฟลเดอร์รูทและรับแพคเกจที่สร้างขึ้นและ package.json คัดลอกไปยังdistโฟลเดอร์โดยอัตโนมัติภายในกระบวนการเผยแพร่


-1

นี่เป็นอีกหนึ่งแนวทางที่ฉันคิดว่าสะอาดที่สุด การกำหนดค่าทั้งหมดเป็นไปตามโดยไม่จำเป็นต้องย้ายไฟล์หรือระบุพา ธ ในสคริปต์ build และ pack:

package.json ระบุไฟล์หลัก

{
    "main": "lib/index.js",
}

ตัวเลือก typecript เพิ่มเติมบางอย่าง:

  • ระบุไฟล์rootDir. ไดเร็กทอรีนี้จะมีซอร์สโค้ดทั้งหมดและควรมีindexไฟล์อยู่ในนั้น (หรือไฟล์อื่นที่คุณสามารถใช้เป็นไฟล์หลักได้package.json)
  • ระบุไฟล์outDir. นี่คือที่ที่คำสั่ง tsc ของคุณจะสร้างไป

tsconfig.json

{
    "compilerOptions": {
        "rootDir": "src",
        "outDir": "lib",
    },
    ...

}

นี่ไม่เหมือนกับสิ่งที่ OP เดิมมียกเว้นการเปลี่ยนชื่อจาก dist เป็น lib?
Bob9630

-1

ตัวเลือกที่ 1: ไปที่โฟลเดอร์และดำเนินการ "npm published" คำสั่ง

ตัวเลือกที่ 2: รัน npm published / path / directory


-4

เพียงแค่สร้าง.npmignoreไฟล์และเพิ่มสิ่งต่อไปนี้:

*.*
!dist/*

1
ทำตามที่ OP ร้องขอหรือไม่ ฉันไม่สามารถทำงานนี้ได้ แนวคิดคือการทำให้แพ็คเกจที่เผยแพร่มีเฉพาะเนื้อหาของไดเร็กทอรี dist โดยไม่รวมไดเร็กทอรีเอง ฉันทำสิ่งนี้เพื่อให้แน่ใจว่าเราไม่ได้รวมสิ่งใด ๆ ที่ไม่ได้อยู่ในไดเร็กทอรี dist ซึ่งสามารถทำได้ด้วยรายการ "files" package.json
Bob9630
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.