วิธีการเผยแพร่โมดูลที่เขียนใน ES6 ถึง NPM?


144

ฉันกำลังจะเผยแพร่โมดูลให้กับ NPM เมื่อฉันคิดเกี่ยวกับการเขียนใหม่ใน ES6 เพื่อพิสูจน์ในอนาคตและเรียนรู้ ES6 ฉันใช้ Babel เพื่อ transpile เป็น ES5 และทำการทดสอบ แต่ฉันไม่แน่ใจว่าจะดำเนินการอย่างไร:

  1. ฉันจะส่งสัญญาณและเผยแพร่โฟลเดอร์ผลลัพธ์ / ออกไปยัง NPM หรือไม่
  2. ฉันจะรวมโฟลเดอร์ผลลัพธ์ใน repo Github ของฉันหรือไม่
  3. หรือฉันจะรักษา 2 repos ซึ่งมี ES6 code + gulp script สำหรับ Github และอีกหนึ่งที่มี transpiled results + tests สำหรับ NPM

กล่าวโดยย่อ: ฉันต้องใช้ขั้นตอนอะไรบ้างในการเผยแพร่โมดูลที่เขียนใน ES6 ถึง NPM ในขณะที่ยังคงอนุญาตให้ผู้ใช้เรียกดู / แยกรหัสต้นฉบับ


ฉันดิ้นรนกับการตัดสินใจครั้งนี้ ฉันเห็นคำตอบที่คุณทำเครื่องหมายว่าถูกต้องโดยโฮเซ่ซึ่งเป็นฉันทามติด้วยเช่นกัน
Talves

นี่คือคำตอบของฉันในปี 2018โดยคำนึงถึงความคืบหน้าด้วยการสนับสนุนโมดูลตั้งแต่ 2558
Dan Dascalescu

1
ฉันจะรักถ้าฉันสามารถทำตรงข้าม ใช้โมดูล ES เพื่อนำเข้าโมดูล NPM แต่ผลลัพธ์เหล่านี้เป็นผลลัพธ์เดียวที่ฉันได้รับ
SeanMC

คำตอบ:


81

รูปแบบที่ฉันได้เห็นจนถึงตอนนี้คือการเก็บไฟล์ es6 ไว้ในsrcไดเรกทอรีและสร้างเนื้อหาของคุณในการเผยแพร่ล่วงหน้าของ npm ไปยังlibไดเรกทอรี

คุณจะต้องเป็นไฟล์ .npmignore คล้ายกับ .gitignore แต่ไม่สนใจแทนsrclib


4
คุณมีที่เก็บตัวอย่างหรือไม่?
Ahmed Abbas

2
หมายเหตุ @JamesAkwuh ที่คุณอาจจะต้องการที่จะเปลี่ยน "เริ่มต้น" และ "สร้าง" คำสั่งใน package.json ที่จะใช้เส้นทางสัมพันธ์ของ ./node_modules/babel-cli/bin/babel.js -s inline -d lib -w srcBabel-CLI: สิ่งนี้ควรตรวจสอบให้แน่ใจว่าการติดตั้งไม่ได้ล้มเหลวเมื่อปรับใช้กับสภาพแวดล้อมใหม่
phazonNinja

2
@phazonNinja npm จัดการกับมัน
James Akwuh

4
“ ถ้าไม่มีไฟล์. pmignore แต่มีไฟล์. gitignore ดังนั้น npm จะไม่สนใจสิ่งที่จับคู่กับไฟล์. gitignore” เอกสาร npm อย่างเป็นทางการ
Frank Nocke

10
แทนที่จะ.npmignoreคุณสามารถใช้filesข้อมูลใน package.json มันช่วยให้คุณระบุไฟล์ที่คุณต้องการเผยแพร่ได้อย่างแม่นยำแทนที่จะหาไฟล์สุ่มที่คุณไม่ต้องการเผยแพร่
Dan Dascalescu

76

ฉันชอบคำตอบของโฮเซ่ ฉันสังเกตเห็นหลายโมดูลตามรูปแบบนั้นแล้ว นี่คือวิธีที่คุณสามารถใช้กับ Babel6 ได้อย่างง่ายดาย ฉันติดตั้งแบบbabel-cliโลคัลเพื่อให้บิลด์ไม่หยุดถ้าฉันเปลี่ยนรุ่นบาเบลทั่วโลก

.npmignore

/src/

.gitignore

/lib/
/node_modules/

ติดตั้ง Babel

npm install --save-dev babel-core babel-cli babel-preset-es2015

package.json

{
  "main": "lib/index.js",
  "scripts": {
    "prepublish": "babel src --out-dir lib"
  },
  "babel": {
    "presets": ["es2015"]
  }
}

29
คำสั่งใด ๆ ในscriptsจะได้node_modules/.binเพิ่มไปยังของพวกเขา$PATHและตั้งแต่babel-cliติดตั้งไบนารีไปที่node_modules/.bin/babelไม่จำเป็นต้องอ้างอิงคำสั่งโดยเส้นทาง
Sukima

3
โปรดสังเกตว่าprepublishมีปัญหาเพราะมันสามารถทำงานได้ในเวลาติดตั้ง ( github.com/npm/npm/issues/3059 ) ชอบversionhook hook ของสคริปต์ที่มีลักษณะเฉพาะมากกว่านี้( docs.npmjs.com/cli/version )
mattecapu

@mattecapu ดูเหมือนว่าปัญหาprepublishยังคงมีอยู่ ในขณะนี้ฉันคิดว่ารวบรวมsrcไดเรกทอรีด้วยตนเองและnpm publishเป็นวิธีที่จะไป
sonlexqt

1
คุณสามารถใช้prepublishOnlyเบ็ดของสคริปต์ (ดูdocs.npmjs.com/misc/scripts#prepublish-and-prepare ) โปรดทราบว่าในเวอร์ชัน 5 ของ npm สิ่งนี้ควรทำงานได้ตามที่คาดไว้ แต่สำหรับตอนนี้ (สมมติว่าคุณใช้ npm v4 +) สิ่งนี้จะทำงานได้
Alex Mann

1
@FrankNocke prepublishทำงานก่อนpublish(obv.) ซึ่งส่งข้อมูลไปยัง npm (หรือที่ใดก็ตามที่คุณกำหนดค่า) ดังนั้นสำหรับการสร้างสิ่งที่จะเกิดขึ้นในแพ็คเกจ NPM แม้ว่าจะยังไม่ได้เช็คอินก็ตาม
Simon Buchan

42

TL; DR - อย่าจนกระทั่ง ~ ตุลาคม 2019 ทีมโมดูล Node.js ได้ถาม :

โปรดอย่าเผยแพร่แพคเกจโมดูล ES ใด ๆ ที่มีไว้เพื่อการใช้งานโดย Node.js จนถึง [ตุลาคม 2019]

2019 พ.ค. อัพเดท

ตั้งแต่ปี 2015 เมื่อมีการถามคำถามนี้การสนับสนุน JavaScript สำหรับโมดูลได้ครบกำหนดแล้วและหวังว่าจะมีเสถียรภาพอย่างเป็นทางการในเดือนตุลาคม 2019 คำตอบอื่น ๆ ทั้งหมดนั้นล้าสมัยหรือซับซ้อนเกินไป นี่คือสถานการณ์ปัจจุบันและแนวทางปฏิบัติที่ดีที่สุด

รองรับ ES6

99% ของ ES6 (aka 2015) ได้รับการสนับสนุนจาก Node ตั้งแต่รุ่น 6 Node เวอร์ชันปัจจุบันคือ 12 เบราว์เซอร์ที่เขียวตลอดปีรองรับคุณสมบัติ ES6 ส่วนใหญ่ ECMAScript ตอนนี้เป็นรุ่น 2019และรูปแบบการกำหนดเวอร์ชันสนับสนุนตอนนี้ใช้เวลาหลายปี

ES Modules (aka โมดูล ECMAScript) ในเบราว์เซอร์

เบราว์เซอร์เอเวอร์กรีนทั้งหมดได้รับการสนับสนุน importโมดูล ES6 ตั้งแต่ปี 2017 การสนับสนุนการนำเข้าแบบไดนามิกได้รับการสนับสนุนโดย Chrome (+ forks เช่น Opera และ Samsung Internet) และ Safari รองรับ Firefox มีกำหนดไว้สำหรับรุ่นถัดไป 67

คุณไม่จำเป็นต้องใช้ Webpack / rollup / Parcel ฯลฯ เพื่อโหลดโมดูลอีกต่อไป อาจยังมีประโยชน์สำหรับวัตถุประสงค์อื่น แต่ไม่จำเป็นต้องโหลดรหัสของคุณ คุณสามารถนำเข้า URL ที่ชี้ไปยังรหัสโมดูล ES โดยตรง

โมดูล ES ในโหนด

โมดูล ES ( .mjsไฟล์ที่มีimport/ export) ได้รับการสนับสนุนตั้งแต่ Node v8.5.0 โดยเรียกnodeด้วย--experimental-modulesแฟล็ก โหนด v12 วางจำหน่ายในเดือนเมษายน 2019 เขียนการสนับสนุนโมดูลทดลองใหม่ การเปลี่ยนแปลงที่มองเห็นได้มากที่สุดคือค่าเริ่มต้นที่ต้องระบุนามสกุลไฟล์เมื่อนำเข้า:

// lib.mjs 

export const hello = 'Hello world!';

// index.mjs:

import { hello } from './lib.mjs';
console.log(hello);

บันทึก.mjsนามสกุลที่จำเป็นตลอด ทำงานเป็น:

node --experimental-modules index.mjs

โหนด 12 เปิดตัวเป็นเมื่อทีมโมดูลถามนักพัฒนาที่จะไม่เผยแพร่แพคเกจโมดูล ES ไว้สำหรับการใช้งานโดย Node.jsจนวิธีการแก้ปัญหาที่พบในการใช้แพคเกจทั้งทางและrequire('pkg') import 'pkg'คุณยังคงสามารถเผยแพร่โมดูล ES ดั้งเดิมได้สำหรับเบราว์เซอร์

การสนับสนุนระบบนิเวศของโมดูล ES ดั้งเดิม

ตั้งแต่เดือนพฤษภาคม 2019 การสนับสนุนระบบนิเวศสำหรับโมดูล ES ยังไม่สมบูรณ์ ยกตัวอย่างเช่นกรอบการทดสอบเช่นเจ็ทและAva--experimental-modulesไม่สนับสนุน คุณต้องใช้ transpiler และจะต้องตัดสินใจระหว่างการใช้import { symbol }ไวยากรณ์import ( ) ที่มีชื่อ(ซึ่งยังไม่สามารถใช้งานได้กับแพคเกจ npm ส่วนใหญ่) และไวยากรณ์การนำเข้าเริ่มต้น ( import Package from 'package') ซึ่งใช้งานได้แต่ไม่ใช่เมื่อ Babel แยกวิเคราะห์มันสำหรับแพ็คเกจที่เขียนใน TypeScript (graphql-tools, node-infux, faast เป็นต้น) มีวิธีแก้ไขที่ใช้ได้ทั้งกับ--experimental-modulesและถ้า Babel transpiles รหัสของคุณเพื่อให้คุณสามารถทดสอบกับ Jest / Ava / Mocha เป็นต้น:

import * as ApolloServerM from 'apollo-server'; const ApolloServer = ApolloServerM.default || ApolloServerM;

เนื้อหาน่าเกลียด แต่วิธีนี้คุณสามารถเขียนโค้ดโมดูล ES ของคุณเองด้วยimport/ exportและรันด้วยnode --experimental-modulesโดยไม่มี transpilers หากคุณมีการพึ่งพาที่ยังไม่พร้อม ESM ให้นำเข้าดังกล่าวข้างต้นและคุณจะสามารถใช้กรอบการทดสอบและเครื่องมืออื่น ๆ ผ่าน Babel


คำตอบของคำถามก่อนหน้านี้ - อย่าเพิ่งทำเช่นนี้จนกว่าโหนดจะแก้ปัญหาปัญหาการนำเข้า / นำเข้าหวังว่าประมาณเดือนตุลาคม 2019

การเผยแพร่โมดูล ES6 ถึง npm พร้อมความเข้ากันได้ย้อนหลัง

หากต้องการเผยแพร่โมดูล ES ไปที่ npmjs.org เพื่อให้สามารถนำเข้าโดยตรงโดยไม่ต้อง Babel หรือ transpilers อื่น ๆ เพียงแค่ชี้mainฟิลด์ในไฟล์ของคุณpackage.jsonไปยัง.mjsไฟล์ แต่ไม่ต้องใส่นามสกุล:

{
  "name": "mjs-example",
  "main": "index"
}

นั่นคือการเปลี่ยนแปลงเท่านั้น โดยการข้ามส่วนขยายโหนดจะค้นหาไฟล์ mjs ก่อนหากรันด้วย --experimental-modules มิฉะนั้นจะย้อนกลับไปที่ไฟล์. js ดังนั้นกระบวนการถ่ายโอนข้อมูลที่มีอยู่ของคุณเพื่อสนับสนุนโหนดรุ่นเก่าจะทำงานเหมือนก่อน - เพียงตรวจสอบให้แน่ใจว่าได้ชี้ Babel ไปที่.mjsไฟล์

นี่คือแหล่งที่มาสำหรับโมดูล ES ดั้งเดิมที่มีความเข้ากันได้ย้อนหลังสำหรับโหนด <8.5.0ที่ฉันเผยแพร่ไปยัง NPM คุณสามารถใช้งานได้ทันทีโดยไม่ต้องใช้ Babel หรืออย่างอื่น

ติดตั้งโมดูล:

npm install local-iso-dt
# or, yarn add local-iso-dt

สร้างไฟล์ทดสอบtest.mjs :

import { localISOdt } from 'local-iso-dt/index.mjs';
console.log(localISOdt(), 'Starting job...');

Run node (v8.5.0 +) ด้วยแฟล็ก --experimental-modules:

node --experimental-modules test.mjs

สิ่งที่พิมพ์ด้วยพิมพ์ดีด

หากคุณพัฒนาใน TypeScript คุณสามารถสร้างรหัส ES6 และใช้โมดูล ES6:

tsc index.js --target es6 --modules es2015

จากนั้นคุณต้องเปลี่ยนชื่อ*.jsเอาต์พุต.mjsเป็นปัญหาที่ทราบแล้วซึ่งหวังว่าจะได้รับการแก้ไขในไม่ช้าเพื่อให้tscสามารถส่งออก.mjsไฟล์ได้โดยตรง


3
การพูดว่า "เบราว์เซอร์ที่เขียวตลอดปีรองรับคุณลักษณะส่วนใหญ่ของ ES6 ไม่ได้มีความหมายอะไรมากเมื่อคุณดูข้อมูลและตระหนักว่าการสนับสนุน es6 ในเบราว์เซอร์มีผู้ใช้ถึงประมาณ 80% เท่านั้น
Pedro Pedrosa

3
ปัจจุบันระบบนิเวศยังไม่สมบูรณ์เพียงพอสำหรับเรื่องนี้ ทีม Node.js พร้อมด้วยการเปิดตัว v12 ถามเป็นพิเศษ: "โปรดอย่าเผยแพร่แพคเกจโมดูล ES ใด ๆ ที่มีไว้สำหรับใช้งานโดย Node.js จนกว่าจะได้รับการแก้ไข" 2ality.com/2019/04/nodejs-esm-impl.html#es-modules-on-npm Mocha ไม่รองรับไฟล์. mjs ห้องสมุดหลายแห่ง (เช่น create-react-app, react-apollo, graphql-js) มีปัญหากับการขึ้นต่อกันที่มีmjsไฟล์ Node.js วางแผนที่จะเปิดตัวการสนับสนุนอย่างเป็นทางการในเดือนตุลาคม 2019 ซึ่งเป็นช่วงแรก ๆ ที่ฉันจะทบทวนเรื่องนี้อย่างจริงจัง
thisismydesign

3
@thisismydesign: ขอบคุณสำหรับคำเตือนให้อัปเดตคำตอบเก่านี้! เพิ่งทำไป
Dan Dascalescu

17

@ โจเซ่พูดถูก ไม่มีอะไรผิดปกติกับการเผยแพร่ ES6 / ES2015 ไปยัง NPM แต่อาจทำให้เกิดปัญหาโดยเฉพาะอย่างยิ่งหากผู้ใช้แพคเกจของคุณกำลังใช้ Webpack ตัวอย่างเช่นเพราะโดยปกติแล้วคนทั่วไปจะไม่สนใจnode_modulesโฟลเดอร์ในขณะประมวลผลล่วงหน้าด้วยbabelเหตุผลด้านประสิทธิภาพ

ดังนั้นเพียงแค่ใช้gulp, gruntหรือเพียงแค่ Node.js จะสร้างlibโฟลเดอร์ที่อยู่ ES5

นี่คือbuild-lib.jsสคริปต์ของฉันซึ่งฉันเก็บไว้./tools/(ไม่gulpหรือgruntที่นี่):

var rimraf = require('rimraf-promise');
var colors = require('colors');
var exec = require('child-process-promise').exec;

console.log('building lib'.green);

rimraf('./lib')
    .then(function (error) {
        let babelCli = 'babel --optional es7.objectRestSpread ./src --out-dir ./lib';
        return exec(babelCli).fail(function (error) {
            console.log(colors.red(error))
        });
    }).then(() => console.log('lib built'.green));

ต่อไปนี้เป็นคำแนะนำสุดท้าย: คุณจำเป็นต้องเพิ่ม .npmignore ในโครงการของคุณ หากnpm publishไม่พบไฟล์นี้จะใช้.gitignoreแทนซึ่งจะทำให้คุณมีปัญหาเพราะปกติ.gitignoreไฟล์ของคุณจะแยก./libและรวม./srcซึ่งตรงข้ามกับสิ่งที่คุณต้องการเมื่อคุณเผยแพร่ไปยัง NPM .npmignoreไฟล์มีพื้นไวยากรณ์เดียวกันของ.gitignore(AFAIK)


1
แทนที่จะ.npmignoreคุณสามารถใช้filesข้อมูลใน package.json มันช่วยให้คุณระบุไฟล์ที่คุณต้องการเผยแพร่ได้อย่างแม่นยำแทนที่จะหาไฟล์สุ่มที่คุณไม่ต้องการเผยแพร่
Dan Dascalescu

ต้นไม้นี้สั่นไหวไหม?
Joe

ผมไม่แนะนำให้ใช้.npmignoreลองpackage.json's filesแทนดู: github.com/c-hive/guides/blob/master/js/...
thisismydesign

@thisismydesign: นั่นคือสิ่งที่ฉันแนะนำในความคิดเห็นของฉันด้านบน .. ?
Dan Dascalescu

ไม่ดีของฉันไม่ได้สังเกต :)
thisismydesign

8

ปฏิบัติตามแนวทางของJoséและ Marius (พร้อมอัปเดตเวอร์ชันล่าสุดของ Babel ในปี 2019): เก็บไฟล์ JavaScript ล่าสุดไว้ในไดเรกทอรี src และสร้างด้วยprepublishสคริปต์ของ npm และส่งออกไปยังไดเรกทอรี lib

.npmignore

/src

.gitignore

/lib
/node_modules

ติดตั้ง Babel (เวอร์ชั่น 7.5.5 ในกรณีของฉัน)

$ npm install @babel/core @babel/cli @babel/preset-env --save-dev

package.json

{
  "name": "latest-js-to-npm",
  "version": "1.0.0",
  "description": "Keep the latest JavaScript files in a src directory and build with npm's prepublish script and output to the lib directory.",
  "main": "lib/index.js",
  "scripts": {
    "prepublish": "babel src -d lib"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/preset-env": "^7.5.5"
  },
  "babel": {
    "presets": [
      "@babel/preset-env"
    ]
  }
}

และฉันมีsrc/index.jsที่ใช้ฟังก์ชั่นลูกศร:

"use strict";

let NewOneWithParameters = (a, b) => {
  console.log(a + b); // 30
};
NewOneWithParameters(10, 20);

นี่คือrepo บน GitHub

ตอนนี้คุณสามารถเผยแพร่แพ็คเกจ:

$ npm publish
...
> latest-js-to-npm@1.0.0 prepublish .
> babel src -d lib

Successfully compiled 1 file with Babel.
...

ก่อนที่แพ็กเกจจะถูกเผยแพร่ไปยัง npm คุณจะเห็นว่าlib/index.jsมีการสร้างขึ้นซึ่งถูกเปลี่ยนเป็น es5:

"use strict";

var NewOneWithParameters = function NewOneWithParameters(a, b) {
  console.log(a + b); // 30
};

NewOneWithParameters(10, 20);

[อัปเดตสำหรับ Bundler Rollup]

ตามที่ถามโดย @kyw คุณจะรวม Bundler Rollup ได้อย่างไร

ก่อนติดตั้งrollupและrollup-plugin-babel

npm install -D rollup rollup-plugin-babel

ประการที่สองสร้างrollup.config.jsในไดเรกทอรีรากของโครงการ

import babel from "rollup-plugin-babel";

export default {
  input: "./src/index.js",
  output: {
    file: "./lib/index.js",
    format: "cjs",
    name: "bundle"
  },
  plugins: [
    babel({
      exclude: "node_modules/**"
    })
  ]
};

สุดท้ายปรับปรุงprepublishในpackage.json

{
  ...
  "scripts": {
    "prepublish": "rollup -c"
  },
  ...
}

ตอนนี้คุณสามารถรันnpm publishและก่อนที่แพ็กเกจจะถูกเผยแพร่ไปยัง npm คุณจะเห็นว่า lib / index.js ถูกสร้างขึ้นซึ่งถูก transpiled เป็น es5:

'use strict';

var NewOneWithParameters = function NewOneWithParameters(a, b) {
  console.log(a + b); // 30
};

NewOneWithParameters(10, 20);

หมายเหตุ: อย่างไรก็ตามคุณไม่จำเป็นต้องใช้อีกต่อไป@babel/cliหากคุณใช้ Bundler Rollup คุณสามารถถอนการติดตั้งอย่างปลอดภัย:

npm uninstall @babel/cli

คุณจะรวม Bundler Rollup อย่างไร
kyw

1
@kyw เกี่ยวกับวิธีรวมตัวรวม Rollup ดูคำตอบที่อัปเดต
Yuci

อัปเดตเมื่อธันวาคม 2562 -> github.com/rollup/rollup/blob/…
a.barbieri

6

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


4

Node.js 13.2.0+ รองรับ ESM โดยไม่ต้องตั้งค่าสถานะการทดลองและมีตัวเลือกไม่กี่ตัวในการเผยแพร่แพ็คเกจ NPM แบบไฮบริด (ESM และ CommonJS) (ขึ้นอยู่กับระดับของความเข้ากันได้แบบย้อนหลังที่จำเป็น): https://2ality.com/2019 /10/hybrid-npm-packages.html

ฉันขอแนะนำให้ใช้วิธีการเข้ากันได้แบบย้อนกลับแบบเต็มเพื่อให้การใช้งานแพคเกจของคุณง่ายขึ้น สิ่งนี้อาจมีลักษณะดังนี้:

แพ็คเกจไฮบริดมีไฟล์ดังต่อไปนี้:

mypkg/
  package.json
  esm/
    entry.js
  commonjs/
    package.json
    entry.js

mypkg/package.json

{
  "type": "module",
  "main": "./commonjs/entry.js",
  "exports": {
    "./esm": "./esm/entry.js"
  },
  "module": "./esm/entry.js",
  ···
}

mypkg/commonjs/package.json

{
  "type": "commonjs"
}

การนำเข้าจาก CommonJS:

const {x} = require('mypkg');

นำเข้าจาก ESM:

import {x} from 'mypkg/esm';

เราทำการตรวจสอบเกี่ยวกับการสนับสนุน ESM ในวันที่ 05.2019และพบว่ามีห้องสมุดจำนวนมากที่ขาดการสนับสนุน


ฉันไม่สามารถนำเข้าโมดูล ES6 ที่ติดตั้งไว้ทั่วโลกในโฟลเดอร์ node_modules (จัดทำโดย npm root -g) พวกเราไม่ควรทำอย่างนั้นจริง ๆ หรือ? ฉันสับสนจริงๆ ฉันรู้ว่าการเชื่อมโยง npm สามารถแก้ปัญหาได้โดยการเชื่อมโยงโมดูลกับโฟลเดอร์ node_modules ในพื้นที่ของฉัน แต่ฉันต้องการทราบว่าทำไมการอิมพอร์ตโมดูลโหนดโกลบอล
Joakim L. Christiansen

ตอบตัวเองฉันเดาว่ามันจะไม่ได้รับการสนับสนุน: github.com/nodejs/node-eps/blob/master/ ......มันเป็นการตัดสินใจที่โง่จริง ๆ แม้ว่าจะง่ายต่อการสนับสนุน ...
Joakim L. Christiansen

3

เกณฑ์สองข้อของแพคเกจ NPM คือสามารถใช้งานได้โดยไม่มีอะไรมากไปกว่าrequire( 'package' )และทำสิ่งที่เป็นซอฟต์แวร์

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

อย่างไรก็ตามถ้าชอบkoaโมดูลของคุณต้องการความเข้ากันได้กับผู้ใช้ที่ใช้คุณสมบัติ ES6 ดังนั้นบางทีโซลูชันแพคเกจทั้งสองอาจเป็นแนวคิดที่ดีกว่า

Takeaway

  1. เผยแพร่รหัสได้มากเท่าที่คุณต้องการเพื่อให้require( 'your-package' )ทำงานได้
  2. ยกเว้นว่าระหว่าง ES5 และ 6 มีความสำคัญกับผู้ใช้เพียงเผยแพร่ 1 แพ็คเกจ ส่งสัญญาณถ้าคุณต้อง

1
ดูเหมือนจะไม่ตอบคำถาม ฉันคิดว่า OP กำลังพยายามหาวิธีจัดโครงสร้าง repo Github ของพวกเขาและสิ่งที่จะเผยแพร่ไปยัง NPM และสิ่งที่คุณได้กล่าวคือพวกเขาสามารถทำสิ่งที่พวกเขาต้องการ OP ต้องการคำแนะนำเฉพาะเกี่ยวกับแนวทางปฏิบัติที่ดีสำหรับสถานการณ์นี้
jfriend00

@ jfriend00 ฉันไม่เห็นด้วย ฉันแนะนำให้เขา transpile และเผยแพร่เฉพาะไฟล์ที่จำเป็นสำหรับrequire( 'package' )การทำงาน ฉันจะแก้ไขคำตอบเพื่อทำให้ชัดเจนยิ่งขึ้น ที่กล่าวว่าคำตอบของ Jose ดีกว่าของฉันเอง
JoshWillik

คำตอบของโฮเซ่เป็นสิ่งที่ดีมาก แต่ฉันขอบคุณสำหรับสิ่งนี้อย่างชัดเจนสำหรับการสรุปกฎเกณฑ์ที่ดีสำหรับการใช้เมื่อเทียบกับแพ็คเกจสองชุด
Jordan Gray

3

คีย์หลักในการpackage.jsonตัดสินใจจุดเข้าใช้งานแพคเกจเมื่อมีการเผยแพร่ ดังนั้นคุณสามารถใส่ผลลัพธ์ของ Babel ได้ทุกที่ที่คุณต้องการและเพียงกล่าวถึงเส้นทางที่ถูกต้องในmainคีย์

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

นี่คือบทความที่เขียนดีเกี่ยวกับวิธีการเผยแพร่แพคเกจ npm

https://codeburst.io/publish-your-own-npm-package-ff918698d450

นี่คือ repo ตัวอย่างที่คุณสามารถใช้สำหรับการอ้างอิง

https://github.com/flexdinesh/npm-module-boilerplate


โพสต์นั้นจะละเว้นความจริงที่ว่าคุณสามารถ (และควร) เผยแพร่ไปยังโมดูล NPM ที่เขียนขึ้นใน ES6และimportสามารถโดยตรงโดยไม่ต้องใช้ Babel หรือ transpilers อื่น ๆ
Dan Dascalescu

0

การลดลงของกายวิภาคศาสตร์ของโมดูลโซลูชันนี้อาจใช้งานไม่ได้ แต่หากโมดูลของคุณอยู่ในไฟล์เดียวและไม่มีการพึ่งพา (ไม่ใช้ประโยชน์จากการนำเข้า ) โดยใช้รูปแบบต่อไปนี้คุณสามารถปล่อยรหัสของคุณได้ และจะสามารถนำเข้าพร้อมการนำเข้า (โมดูลเบราว์เซอร์ ES6) และต้องการ (โมดูล Node CommonJS)

ในฐานะโบนัสจะสามารถนำเข้าได้โดยใช้องค์ประกอบ HTML SCRIPT

main.js :

(function(){
    'use strict';
    const myModule = {
        helloWorld : function(){ console.log('Hello World!' )} 
    };

    // if running in NODE export module using NODEJS syntax
    if(typeof module !== 'undefined') module.exports = myModule ;
    // if running in Browser, set as a global variable.
    else window.myModule = myModule ;
})()

my-module.js :

    // import main.js (it will declare your Object in the global scope)
    import './main.js';
    // get a copy of your module object reference
    let _myModule = window.myModule;
    // delete the the reference from the global object
    delete window.myModule;
    // export it!
    export {_myModule as myModule};

package.json : `

    {
        "name" : "my-module", // set module name
        "main": "main.js",  // set entry point
        /* ...other package.json stuff here */
    }

ในการใช้โมดูลของคุณคุณสามารถใช้ไวยากรณ์ปกติ ...

เมื่อนำเข้าในNODE ...

    let myModule = require('my-module');
    myModule.helloWorld();
    // outputs 'Hello World!'

เมื่อนำเข้าในBROWSER ...

    import {myModule} from './my-module.js';
    myModule.helloWorld();
    // outputs 'Hello World!'

หรือแม้กระทั่งเมื่อรวมกับการใช้ องค์ประกอบสคริปต์ HTML ...

<script src="./main.js"></script>
<script>
     myModule.helloWorld();
    // outputs 'Hello World!'
</script>

-1

หมายเหตุเพิ่มเติมเล็กน้อยสำหรับทุกคนที่ใช้โมดูลของตัวเองโดยตรงจาก Github ไม่ผ่านโมดูลที่เผยแพร่ :

ตะขอ( ใช้กันอย่างแพร่หลาย ) "prepublish" จะไม่ทำสิ่งใดเพื่อคุณ

สิ่งที่ดีที่สุดที่เราสามารถทำได้ (หากวางแผนที่จะพึ่งพา repos Github ไม่ใช่สิ่งที่เผยแพร่):

  • unlist srcจาก. npmignore (ในคำอื่น ๆ : อนุญาต) หากคุณยังไม่มี.npmignoreโปรดจำไว้ว่า: .gitignoreจะมีการใช้สำเนาแทนในตำแหน่งที่ติดตั้งเช่นเดียวกับที่ls node_modules/yourProjectแสดงให้คุณเห็น
  • ตรวจสอบให้แน่ใจว่าbabel-cliมันขึ้นอยู่กับโมดูลของคุณไม่ใช่แค่ devDepenceny เพราะคุณกำลังสร้างเครื่องจักรที่ใช้งานอยู่ที่คอมพิวเตอร์นักพัฒนาแอพซึ่งกำลังใช้โมดูลของคุณอยู่
  • ทำสิ่งที่สร้างในการติดตั้งเบ็ดคือ:

    "install": "babel src -d lib -s"

(ไม่มีค่าเพิ่มในการลอง "ติดตั้งล่วงหน้า" เช่น babel-cli อาจหายไป)


3
คอมไพล์ในการติดตั้งนั้นหยาบคายมาก โปรดอย่าทำเช่นนี้ - เวลาในการติดตั้ง npm ไม่ดีพอ! สำหรับรหัสภายในที่คุณต้องการหลีกเลี่ยงการใช้พื้นที่เก็บข้อมูลแพคเกจ npm คุณสามารถ: 1) ใช้ monorepo, 2) อัปโหลดและขึ้นอยู่กับnpm packเอาท์พุท 3) ตรวจสอบในการสร้างเอาท์พุท
Simon Buchan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.