Cách npm xuất bản thư mục cụ thể nhưng dưới dạng gốc gói


86

Tôi có một dự án bao gồm một nhiệm vụ gulp để xây dựng và đóng gói các nguồn và phát hành trong một thư mục có tên dist. Mục tiêu của tôi là xuất bản nó dưới dạng gói npm, nhưng chỉ có thư mục dist của tôi. Các tài liệu NPM nói rằng tôi có thể sử dụng filesthẻ để xác định tập tin để xuất khẩu. Nó hoạt động. Tuy nhiên, tài liệu cũng nói rằng:

Nếu bạn đặt tên một thư mục trong mảng, thì nó cũng sẽ bao gồm các tệp bên trong thư mục đó

Kết quả là một gói npm, node_modules trông giống như sau:

gói npm được tạo

Nhưng tôi muốn xem tất cả các tệp của mình ở distthư mục gốc của gói (không có thư mục đó ). index.jsTệp của tôi nằm trong distthư mục, nhưng phải ở gốc. Tôi đã cố gắng đặt thẻ files/dist/**/*nhưng nó không hoạt động.

Làm thế nào tôi có thể đạt được nó?

Câu trả lời:


44

Tôi có cùng mong muốn nhưng tôi nghĩ không có cách nào đạt được điều này nếu chỉ sử dụng công cụ npm . Một tập lệnh / công cụ khác có thể được sử dụng để sắp xếp gói của bạn.

Giải pháp thay thế

Hiện tại tôi đang sao chép của tôi package.jsonvào distthư mục và sau đó chạy npm packbên trong distthư mục. Tôi nghĩ rằng điều này về cơ bản cung cấp sự sắp xếp mong muốn của gói của chúng tôi.

Đây là một số bài đọc có liên quan về thiết kế npm này: Tại sao không có Directories.lib trong Node .

Cũng rất thú vị khi lưu ý rằng jspm KHÔNG tôn trọng directories.libtùy chọn trong package.jsonvà sắp xếp lại các tệp khi giải quyết gói npm. Tất cả điều này xảy ra đối với tôi bởi vì tôi muốn xây dựng một thư viện chung có thể được sử dụng bởi jspm hoặc npm / webpack.


1
(Tại sao không Directories.lib ...) là một liên kết chết
Shanimal

1
Tại sao không có Directories.lib trong Node đang nói, nếu bạn không làm theo cách của chúng tôi, bạn sẽ cảm thấy đau đớn. Tất cả điều này là tạo ra nhu cầu về các công cụ để giải quyết vấn đề này.
Brian Takita

6
Tôi tin rằng câu trả lời này đã lỗi thời. Như các câu trả lời bên dưới lưu ý, việc sử dụng npm pack, package.json filesmaincác trường, và .npmignorecung cấp cho nhà phát triển mọi thứ cần thiết để tạo một gói từ một thư mục cụ thể, có thể cài đặt.
Jefftopia 19/09/19

1
Thực hiện một số kịch bản để sắp xếp / thực thi "xuất bản subdir" mẫu
micimize

2
Ai đó có thể đăng giải pháp làm thế nào nó có thể đạt được bằng cách sử dụng npmignore, tệp và thuộc tính chính trong package.json. Tôi muốn di chuyển tất cả các tệp vào thư mục gốc và không có thư mục dist
Angad

16

Tôi gặp sự cố tương tự với người đăng ban đầu (@robsonrosa). Trong trường hợp của tôi, tôi sử dụng typecript để biên dịch thành một distthư mục. Trong khi tôi có thể biên dịch typecript vào thư mục gốc, tôi nghĩ giải pháp tốt nhất là tạo một package.jsontệp riêng trong thư mục dist.
Điều này tương tự như @scvnc đề xuất sao chép package.jsonnhưng có sự thay đổi:

Là một phần của quá trình đóng gói, bạn nên tạo một package.jsongói dựa trên nhưng khác với package.jsontệp chính trong thư mục gốc

Cơ sở lý luận:

  • Gốc package.json là tệp phát triển. Nó có thể chứa các tập lệnh hoặc phần phụ thuộc phát triển không có ích cho người dùng gói, nhưng có thể gây ra các lo ngại về bảo mật cho bạn. Quy trình đóng gói của bạn có thể bao gồm mã tách thông tin đó khỏi quá trình sản xuất package.json.
  • Bạn có thể muốn triển khai gói của mình đến các môi trường khác nhau có thể yêu cầu các tệp gói khác nhau (ví dụ: bạn có thể muốn có các phiên bản hoặc phụ thuộc khác nhau).

--- BIÊN TẬP ---

Tôi đã được yêu cầu một giải pháp trong các ý kiến. Vì vậy, đây là một số mã tôi đang sử dụng. Đây nên được coi là một ví dụ, nó không có nghĩa là chung chung và cụ thể cho các dự án của tôi.

Thiết lập của tôi:

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.

Tôi chỉ muốn đóng gói dist thư mục và thư mục phải là thư mục gốc trong gói.

Tệp SetupPackage.tstrong srcthư mục của tôi sẽ được biên dịch SetupPackage.jstrong distthư mục bằng typecript:

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();

Tệp này:

  • Sao chép thư mục gốc package.jsonnhưng loại bỏ các tập lệnh và phần phụ thuộc nhà phát triển không cần thiết trong gói. Nó cũng sửa điểm vào chính của gói.
  • Ghi phiên bản của gói từ package.jsonmột tệp được gọi version.txt.
  • Sao chép .npmignoregói từ gốc.

Nội dung .npmignore là:

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

Tức là các bài kiểm tra đơn vị (tệp đặc tả) và tệp bản đồ sắp chữ bị bỏ qua cũng như SetupPackage.jstệp và version.txttệp mà nó tạo ra. Điều này để lại một gói sạch.

Cuối cùng, package.jsontệp chính có các tập lệnh sau để hệ thống xây dựng sử dụng (giả shsử được sử dụng làm trình bao).

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

Để xây dựng gói, hệ thống xây dựng sao chép repo, npm install và sau đó lần lượt chạy npm run buildpackage:

  • Xóa dist thư mục đảm bảo một biên dịch sạch.
  • Biên dịch mã typecript thành javascript.
  • Thực thi SetupPackage.jstệp chuẩn bịdist đóng gói.
  • cds vào distthư mục và xây dựng gói ở đó.

Tôi sử dụng version.txttệp như một cách dễ dàng để lấy phiên bản trong package.json và gắn thẻ repo của tôi. Có vô số cách khác để làm điều này hoặc bạn có thể muốn tự động tăng phiên bản. Loại bỏ điều này khỏi SetupPackage.ts.npmignorenếu nó không hữu ích cho bạn.


Câu trả lời này có vẻ là câu trả lời hay nhất, nhưng bạn đã có sẵn giải pháp bỏ qua lý thuyết chưa?
yumaa

3
@yumaa Tôi đã chỉnh sửa câu trả lời của mình với một ví dụ cụ thể. Hy vọng nó hữu ích.
Eli Algranti,

13

Nếu dự án của bạn có git, bạn có thể sử dụng hack nhỏ. Thêm các tập lệnh tiếp theo vào package.json

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

bây giờ khi bạn chạy publishlệnh npm liên quan prepublishOnly. Nó xây dựng các tệp và lưu chúng vào libthư mục (một kịch bản xây dựng phụ thuộc vào dự án của bạn). Lệnh tiếp theo sao chép tệp vào thư mục gốc và xóa lib. Sau khi xuất bản postpublishtập lệnh trả dự án về trạng thái trước đó.


1
Tôi là một fan hâm mộ của giải pháp này!
DanMad

6

Tôi thực sự khuyên bạn nên sử dụng .npmignorethay vì di chuyển hoặc sao chép mọi thứ xung quanh, đặc biệt nếu bạn đang sử dụng CI để triển khai và chỉ cần thêm vào đó các tệp bạn không muốn xuất bản.

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

Thí dụ:

#tests
test
coverage

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

#linters
.jscsrc
.jshintrc
.eslintrc*

#editor settings
.idea
.editorconfig

Cập nhật:

Nếu bạn muốn chia mã của mình, thành các gói npm khác nhau bằng cách sử dụng cùng một repo, tôi đã bắt gặp dự án này gần đây: Lerna và trông thực sự tốt.

Có lẽ bạn nên xem


9
Chúng tôi sẽ vẫn phải phát ra các tệp đã xây dựng của chúng tôi trong thư mục gốc của gói. Có lẽ cho phép đối với CI. Quan sát bài đăng từ blog của Isaac mà tôi đã liên kết và cho tôi biết giải pháp của bạn sẽ cho phép require('mypackage/foo')thay vì như thế nàorequire('mypackage/dist/foo')
scvnc 24/02/17

Tôi đã không cố gắng giải quyết vấn đề đó ở đây. Nếu bạn muốn chia mã của bạn, tôi tình cờ gặp dự án này thời gian gần đây: lernajs.io và ngoại hình thực sự tốt
Thram

Đã tìm thấy một công cụ khác đáng để xem :) github.com/philcockfield/msync
Thram

yeh material UI sử dụng nó và tôi đã sử dụng nó trong công ty cuối cùng của tôi, tôi thấy nó ổn
nick

5

Cái này làm việc tốt cho tôi.

cd TMPDIR; npm pack/path/to/package.json

Tarball sẽ tạo bên trong thư mục TMPDIR.


^ Câu trả lời này được đánh giá thấp. npm packcộng với trường package.json files(hoặc .npmignore) hoạt động tuyệt vời.
Jefftopia 19/09/19

1

Bạn cần xuất bản distthư mục

Cách tự nhiên để đạt được điều đó, theo cách tiếp cận npm, là xuất bản thư mục là thư mục gốc. Có một số cách để làm điều đó, tùy thuộc vào môi trường cuối cùng bạn muốn làm việc:

  1. npm xuất bản <folder> từ kho gói của bạn vào sổ đăng ký npm và sau đó cài đặt gói của bạn trong dự án khác khi bạn cài đặt các gói khác. Trong trường hợp của bạn, nó sẽ lànpm publish dist .
  2. npm install <folder> trong một số dự án khác nếu bạn chỉ muốn sử dụng gói của mình cục bộ. Trong trường hợp của bạn, bạn chuyển đến dự án khác và chạynpm install relative/path/to/dist
  3. npm liên kết cục bộ thư mục của bạn với thư mục của bạn node_modulestrong một dự án khác trong trường hợp bạn muốn những thay đổi trong gói ban đầu của mình được phản ánh ngay lập tức trong dự án khác. Trong trường hợp của bạn, trước tiên bạn cd distchạy npm linkvà sau đó chuyển sang dự án khác và chạy npm link robsonrosa-ui-alert.

Điều kiện tiên quyết : trong bất kỳ trường hợp nào ở trên, trước khi xuất bản / cài đặt / liên kết, bạn phải đưa vào distthư mục của mình ít nhất một package.jsontệp thích hợp . Trong trường hợp của bạn, bạn phải xác định tên gói trong tệp package.json "name": "robsonrosa-ui-alert". Thông thường, bạn cũng sẽ muốn có một số tệp khác như README.md hoặc LICENSE.

Ví dụ về tự động hóa

Bạn có thể tự động hóa quy trình xuất bản bằng cách sử dụng preparescript , kết hợp với buildscript. Ngoài ra, bạn có thể bảo vệ gói của mình khỏi việc vô tình xuất bản thư mục gốc của gói với "private": truetrường được đặt trong package.json, nằm trong thư mục gốc của kho gói của bạn. Đây là một ví dụ:

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

Bằng cách này, bạn sẽ không xuất bản thư mục gốc và disttự động sao chép gói và package.json vào thư mục trong quá trình xuất bản.


0

tùy chọn 1: Điều hướng đến thư mục và thực thi "npm xuất bản". chỉ huy

tùy chọn 2: Chạy npm xuất bản / đường dẫn / thư mục


-1

Đây là một cách tiếp cận nữa mà tôi nghĩ là sạch nhất. Tất cả đều dựa trên cấu hình mà không cần di chuyển tệp hoặc chỉ định đường dẫn trong tập lệnh xây dựng và đóng gói:

package.json Chỉ định tệp chính.

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

Một số tùy chọn bảng chữ bổ sung:

  • Chỉ định rootDir. Thư mục này sẽ có tất cả mã nguồn và nó phải có một indextệp trong đó (hoặc một số tệp khác mà bạn có thể sử dụng làm tệp chính trongpackage.json ).
  • Chỉ định outDir. Đây là nơi lệnh tsc của bạn sẽ xây dựng

tsconfig.json

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

}

Điều này không giống với những gì OP ban đầu có ngoại trừ việc thay đổi tên từ dist thành lib?
Bob9630

-3

Chỉ cần tạo một .npmignoretệp và thêm những thứ sau vào đó:

*.*
!dist/*

1
điều này có làm như OP yêu cầu không? Tôi đã không thể làm cho nó hoạt động. Ý tưởng là làm cho gói đã xuất bản chỉ chứa nội dung của thư mục dist mà không bao gồm chính thư mục đó. Tôi điều này để đảm bảo rằng chúng tôi không bao gồm bất kỳ thứ gì không có trong thư mục dist mà đã có thể được thực hiện với danh sách "tệp" package.json.
Bob9630
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.