node instalar como javascript node.js npm ecmascript-6 babeljs

javascript - instalar - ¿Cómo publicar un módulo escrito en ES6 a NPM?



node js (10)

Algunas notas adicionales para cualquier persona, utilizando módulos propios directamente desde github, sin pasar por los módulos publicados :

El gancho "prepublish" ( ampliamente utilizado ) no está haciendo nada por usted.

Lo mejor que se puede hacer (si planea confiar en repositorios de github, no en cosas publicadas):

  • unlist src de .npmignore (en otras palabras: permitirlo). Si no tiene un .npmignore , recuerde: se .npmignore una copia de .gitignore su lugar en la ubicación instalada, como le mostrará ls node_modules/yourProject .
  • asegúrese de que babel-cli sea ​​una dependencia en su módulo, no solo un DevDepenceny, ya que realmente está construyendo en la máquina consumidora, también conocida como la computadora de desarrolladores de aplicaciones, que está utilizando su módulo
  • hacer lo de compilación, en el gancho de instalación, es decir:

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

(sin valor agregado al intentar algo "preinstalar", es decir, puede faltar babel-cli)

Estaba a punto de publicar un módulo en NPM, cuando pensé en reescribirlo en ES6, para prepararlo en el futuro y aprender ES6. He usado Babel para transpilar a ES5 y ejecutar pruebas. Pero no estoy seguro de cómo proceder:

  1. ¿Transpilo y publico la carpeta resultante / fuera en NPM?
  2. ¿Incluyo la carpeta de resultados en mi repositorio de Github?
  3. ¿O mantengo 2 repositorios, uno con el código ES6 + script gulp para Github y otro con los resultados transpilados + pruebas para NPM?

En resumen: ¿qué pasos debo seguir para publicar un módulo escrito en ES6 en NPM, y al mismo tiempo permitir que la gente explore / bifurque el código original?


@Jose tiene razón. No hay nada de malo en publicar ES6 / ES2015 en NPM, pero eso puede causar problemas, especialmente si la persona que usa su paquete está usando Webpack, por ejemplo, porque normalmente las personas ignoran la carpeta node_modules mientras procesan previamente con babel por razones de rendimiento.

Entonces, solo use gulp , grunt o simplemente Node.js para construir una carpeta lib que sea ES5.

Aquí está mi script build-lib.js , que guardo en ./tools/ (no gulp ni grunt aquí):

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

Aquí hay un último consejo: debe agregar un .npmignore a su proyecto . Si npm publish no encuentra este archivo, usará .gitignore en .gitignore lugar, lo que le causará problemas porque normalmente su archivo ./lib excluirá ./lib e incluirá ./src , que es exactamente lo contrario de lo que desea cuando están publicando en NPM. El archivo .npmignore tiene básicamente la misma sintaxis de .gitignore (AFAIK).


Dependiendo de la anatomía de su módulo, esta solución puede no funcionar, pero si su módulo está contenido dentro de un solo archivo y no tiene dependencias (no hace uso de la importación ), con el siguiente patrón puede liberar su código tal como está , y podrá importarse con import (Módulos ES6 del navegador) y requerir (Módulos Node CommonJS)

Como beneficio adicional, será adecuado importarlo utilizando un elemento 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 */ }

Para usar su módulo, ahora puede usar la sintaxis regular ...

Cuando se importa en NODE ...

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

Cuando se importa en NAVEGADOR ...

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

O incluso cuando se incluye utilizando un elemento de secuencia de comandos HTML ...

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


El patrón que he visto hasta ahora es mantener los archivos es6 en un directorio src y construir sus cosas en la publicación previa de npm en el directorio lib .

Necesitará un archivo .npmignore, similar a .gitignore pero ignorando src lugar de lib .


La clave principal en package.json decide el punto de entrada al paquete una vez que se publica. Por lo tanto, puede colocar la salida de su Babel donde quiera y solo tiene que mencionar la ruta correcta en la tecla main .

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

Aquí hay un artículo bien escrito sobre cómo publicar un paquete npm

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

Aquí hay un repositorio de muestra que puede usar como referencia

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


Los dos criterios de un paquete NPM es que se puede usar con nada más que un require( ''package'' ) y que hace algo similar al software.

Si cumple con estos dos requisitos, puede hacer lo que desee. Incluso si el módulo está escrito en ES6, si el usuario final no necesita saber eso, lo transpilaría por ahora para obtener el máximo soporte.

Sin embargo, si como koa , su módulo requiere compatibilidad con los usuarios que usan las funciones de ES6, entonces quizás la solución de dos paquetes sería una mejor idea.

Para llevar

  1. Solo publique la cantidad de código que necesite para hacer que require( ''your-package'' ) funcione.
  2. A menos que el ES5 y 6 sean importantes para el usuario, solo publique 1 paquete. Transpílalo si es necesario.

Me gusta la respuesta de José. He notado que varios módulos siguen ese patrón ya. Así es como puede implementarlo fácilmente con Babel6. babel-cli localmente para que la compilación no se rompa si alguna vez cambio mi versión global de babel.

.npmignore

/src/

.gitignore

/lib/ /node_modules/

Instalar Babel

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

package.json

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


Si desea ver esto en acción en un módulo Node pequeño de código abierto muy simple, eche un vistazo al nth-day (que comencé, también a otros contribuyentes). Busque en el archivo package.json y en el paso de prepublicación que lo llevará a dónde y cómo hacerlo. Si clonas ese módulo, puedes ejecutarlo localmente y usarlo como plantilla para ti.


Siguiendo el enfoque de José y Marius (con la actualización de la última versión de Babel en 2019): mantenga los últimos archivos JavaScript en un directorio src y compílelos con el script prepublish de npm y envíelos al directorio lib.

.npmignore

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

.gitignore

// 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};

Instalar Babel (versión 7.5.5 en mi caso)

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

package.json

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

Y tengo src/index.js que usa la función de flecha:

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

Aquí está el repositorio en GitHub .

Ahora puedes publicar el paquete:

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

Antes de publicar el paquete en npm, verá que se ha generado lib/index.js , que se transpila a es5:

"use strict"; var NewOneWithParameters = function NewOneWithParameters(a, b) { console.log(a + b); // 30 }; NewOneWithParameters(10, 20);

[Actualización para el paquete acumulativo]

Como preguntó @kyw, ¿cómo integraría el paquete acumulador?

Primero, instale rollup y rollup-plugin-babel

npm install -D rollup rollup-plugin-babel

En segundo lugar, cree rollup.config.js en el directorio raíz del proyecto

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/**" }) ] };

Por último, actualice prepublish en package.json

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

Ahora puede ejecutar npm publish , y antes de que el paquete se publique en npm, verá que se ha generado lib / index.js, que se transpila a es5:

''use strict''; var NewOneWithParameters = function NewOneWithParameters(a, b) { console.log(a + b); // 30 }; NewOneWithParameters(10, 20);

Nota: por cierto, ya no necesita @babel/cli si está utilizando el paquete acumulativo. Puede desinstalarlo de manera segura:

npm uninstall @babel/cli


TL; DR - No, hasta ~ octubre de 2019. El equipo de módulos de Node.js ha asked :

No publique ningún paquete de módulo ES destinado a ser utilizado por Node.js hasta [octubre de 2019]

Actualización de mayo de 2019

Desde 2015, cuando se hizo esta pregunta, el soporte de JavaScript para los módulos ha madurado significativamente y, con suerte, será oficialmente estable en octubre de 2019. Todas las demás respuestas ahora son obsoletas o demasiado complicadas. Aquí está la situación actual y las mejores prácticas.

Soporte ES6

El 99% de ES6 (también conocido como 2015) ha sido compatible con Node desde la versión 6 . La versión actual de Node es 12. Todos los navegadores de hoja perenne admiten la gran mayoría de las funciones de ES6. ECMAScript ahora está en la versión 2019 , y el esquema de versiones ahora favorece el uso de años.

Módulos ES (también conocidos como módulos ECMAScript) en navegadores

Todos los navegadores de hoja perenne han sido supporting import módulos ES6 desde 2017. Las importaciones dinámicas son supported con Chrome (+ tenedores como Opera y Samsung Internet) y Safari. El soporte de Firefox está programado para la próxima versión, 67.

Ya no necesita Webpack / rollup / Parcel, etc. para cargar módulos. Pueden seguir siendo útiles para otros fines, pero no están obligados a cargar su código. Puede importar directamente las URL que apuntan al código de los módulos ES.

Módulos ES en Nodo

Los módulos ES (archivos .mjs con import / export ) han sido compatibles desde el Nodo v8.5.0 al llamar al node con el --experimental-modules . Nodo v12, lanzado en abril de 2019, reescribió el soporte de módulos experimentales. El cambio más visible es que la extensión del archivo debe especificarse de forma predeterminada al importar:

// lib.mjs export const hello = ''Hello world!''; // index.mjs: import { hello } from ''./lib.mjs''; console.log(hello);

Tenga en cuenta las extensiones obligatorias .mjs todo. Correr como:

node --experimental-modules index.mjs

La versión Node 12 también es cuando el Equipo de Módulos asked desarrolladores que no publiquen paquetes de módulos ES destinados a ser utilizados por Node.js hasta que se encuentre una solución para usar paquetes a través de require(''pkg'') e import ''pkg'' . Todavía puede publicar módulos ES nativos destinados a navegadores.

Soporte de ecosistema de módulos ES nativos

A partir de mayo de 2019, el soporte del ecosistema para los módulos ES es inmaduro. Por ejemplo, los marcos de prueba como Jest y Ava no admiten --experimental-modules . Debe usar un transpilador y luego debe decidir entre usar la sintaxis de importación nombrada ( import { symbol } ) (que todavía no funcionará con la mayoría de los paquetes npm) y la sintaxis de importación predeterminada ( import Package from ''package'' ), lo que funciona, pero no cuando Babel lo analiza para paquetes escritos en TypeScript (herramientas graphql, influjo de nodo, faast, etc.) Sin embargo, existe una solución alternativa que funciona tanto con --experimental-modules como si Babel transpila su código para que pueda puede probarlo con Jest / Ava / Mocha, etc.

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

Podría decirse que es feo, pero de esta manera puede escribir su propio código de módulos ES con import / export y ejecutarlo con node --experimental-modules , sin transpilers. Si tiene dependencias que aún no están preparadas para ESM, impórtelas como se indica arriba y podrá usar marcos de prueba y otras herramientas a través de Babel.

Respuesta previa a la pregunta: recuerde, no haga esto hasta que Node resuelva el problema de requerir / importar, con suerte alrededor de octubre de 2019.

Publicación de módulos ES6 en npm, con compatibilidad con versiones anteriores

Para publicar un módulo ES en npmjs.org para que pueda importarse directamente, sin Babel u otros transpiladores, simplemente apunte el campo main en su package.json al archivo .mjs , pero omita la extensión:

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

Ese es el único cambio. Al omitir la extensión, Node buscará primero un archivo mjs si se ejecuta con --experimental-modules. De lo contrario, volverá al archivo .js, por lo que su proceso de transpilación existente para admitir versiones de Nodo anteriores funcionará como antes, solo asegúrese de apuntar a Babel a los archivos .mjs .

Aquí está la fuente de un módulo ES nativo con compatibilidad con versiones anteriores para Nodo <8.5.0 que publiqué en NPM. Puedes usarlo ahora mismo, sin Babel ni nada más.

Instalar el módulo:

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

Cree un archivo de prueba test.mjs :

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

Ejecute el nodo (v8.5.0 +) con el indicador --experimental-modules:

node --experimental-modules test.mjs

Mecanografiado

Si desarrolla en TypeScript, puede generar código ES6 y usar módulos ES6:

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

Luego, debe cambiar el nombre de la salida *.js a .mjs , un issue conocido que con suerte se solucionará pronto para que tsc pueda .mjs archivos .mjs directamente.