Next.js: Agregue soporte para transpilar módulos dentro de node_modules

Creado en 9 ene. 2017  ·  103Comentarios  ·  Fuente: vercel/next.js

Ahora, algunos de nosotros enviamos paquetes NPM (especialmente componentes) escritos en ES2015 sin transpilarlos.

Eso es algo bastante bueno, especialmente si se van a usar en un proyecto como Next.js o CRA (que sí se transpila). Ofrecen beneficios como:

  • No es necesario transpilar antes de enviarlo a NPM
  • Obtenga el beneficio de la sacudida de árboles de Webpack 2

Pero no podemos hacer esto ahora, excluimos todo dentro de node_modules del transpiling de babel.

Entonces, aquí está la solución propuesta.

Tenemos una entrada en next.config.js para incluir módulos que deben pasar por babel. Ver:

module.exports = {
   transpileModules: [
     "my-component",
     "redux/src"
   ]
}
story feature request

Comentario más útil

Cuanto más uso next.js en serio y construyo una rica biblioteca de módulos a su alrededor, más importante se vuelve esta característica. Se está convirtiendo en un PITA real que replica el paso de compilación de babel en mis módulos internos.

🚀🤖

Todos 103 comentarios

  • ¿Por qué esto no es posible con la extensión webpack() ?
  • transpileModules suena mejor
  • ¿Aceptaremos expresiones regulares?

¿Por qué esto no es posible con la extensión webpack ()?

Espero que te refieras a la configuración personalizada del paquete web. Eso es factible. Pero esto se encuentra en un cargador existente. Conseguir eso es algo más difícil.

transpileModules suena mejor

Impresionante. Lo actualizaré.

¿Aceptaremos expresiones regulares?
Sí. seguro.

Oye,

Ahora que estoy comenzando mi propio sitio web, estoy probando nuevas tecnologías como Lerna / Next / Styled ... y estaría encantado de proporcionar comentarios al respecto.

Abrí un problema duplicado en el que intenté importar / transpilar un módulo basado en CRA en mi módulo NextJs pero no sabía cómo hacer que ocurriera la transpilación (tenga en cuenta que me gustaría mantener mi módulo ejecutable como independiente)

También he notado que Babel, también basado en Lerna, está transpilando cada módulo antes de exponerlos, pero me parece mejor hacer lo que sugiere @arunoda y dejar que la aplicación cliente haga la transpilación.

Me gustaría tener una única configuración de babel para mi cliente y compartir esa configuración con todos mis módulos desacoplados. Probablemente no sea tan fácil si quiero mantener la capacidad de ejecutar mis módulos de forma independiente, fuera de Next runner

Mi proyecto de prueba actual está aquí: https://github.com/slorber/playground/ Intentaré actualizarlo tan pronto como haya una bifurcación / PR. @arunoda ¿estás trabajando en eso?

@slorber actualmente nos estamos enfocando en la versión 2.0 y estamos afinando cosas y encontrando errores lo más posible.

No he empezado a trabajar en esto, pero podemos hacerlo justo después de 2.0.

Ok, entonces haré un tenedor. Ya estoy corriendo contra 2.0.0 beta porque no estoy construyendo un sitio web crítico y no creo que el paquete web 1.13 resuelva jsnext: main / module field.

No soy un experto en paquetes, pero creo que prefiero usar el campo "módulo" de package.json, ¿no? "main" parece para el código ya transpilado que yo sepa. Pero como la configuración del paquete web permite incluir / excluir la transpilación, no estoy seguro de que sea relevante. ¿Alguna recomendación sobre cuál de los 3 campos prefiero usar?

@slorber Creo que el paquete web solo admite main al igual que NPM. Puedes usar eso.
Podemos verificar la ruta del archivo en la función exclude en nuestra next.conf.js

Hmm, de acuerdo con lo que he visto en la práctica contra Next 2.x, he visto que el módulo funciona (pero falla más tarde en tiempo de ejecución porque no se transpiló) mientras que jsnext: main no funcionó (por lo que recuerdo). Pero se supone que debe ser compatible .

De todos modos, jsnext: main o module no parece ser la solución a este problema, por lo que para los módulos internos de la empresa, solo habilitar la transpilación es probablemente suficiente

La comunidad no se ha puesto de acuerdo en un enfoque, ¿verdad? Por ejemplo, pude usar react-youtube el otro fuera de la caja sin problemas. ¿Supongo que una gran cantidad de módulos se transpilan antes de publicarlos?

Ref: https://github.com/rauchg/blog/blob/master/components/post/youtube.js

Sí, tiene sentido transpilar siempre antes de publicar porque no sabe quién / cómo se consumirá el módulo y no desea obligar al cliente a configurar los ajustes de babel adecuados para su lib. Eso es lo que sugiere Rollup : publicar el módulo transpilado de diferentes maneras para que el empaquetador pueda decidir cuál usar.

Pero para los paquetes internos de la empresa, la configuración de transpilación puede ser la misma en varios proyectos (como un ajuste preestablecido de babel) y para mí tiene sentido dejar que el paquete de clientes transpile todas las dependencias de la empresa

Muy de acuerdo @slorber : esto sería muy útil para los módulos internos si está dividiendo su proyecto y aislando las cosas tanto como sea posible.

Y @rauchg / @arunoda admitir RegExp's sería realmente bueno, por lo que podría tener una entrada que capture todos los módulos internos de la empresa, usando, por ejemplo, el espacio de nombres de la organización NPM:

// next.config.js
module.exports = {
  transpileModules: [
    /^\@my-npm-org\/.*/
  ]
}

Hermosa sugerencia @philcockfield

Oye, tal vez valga la pena ofrecer algunos ajustes preestablecidos. Me parece que la mayoría de las herramientas (enlace Lerna / npm ...) se basan en enlaces simbólicos, así que ¿por qué no algo tan simple como:

`` `javascript
module.exports = {
transpileModules: ["enlaces simbólicos"]
}
`` ``

Cuanto más uso next.js en serio y construyo una rica biblioteca de módulos a su alrededor, más importante se vuelve esta característica. Se está convirtiendo en un PITA real que replica el paso de compilación de babel en mis módulos internos.

🚀🤖

Estoy trabajando en esto hoy :)

@philcockfield prueba esto: https://github.com/zeit/next.js/pull/749

gracias @arunoda

Entonces, como se comentó en su PR, si esto no admite enlaces simbólicos, la función será un poco limitada porque no funcionará con el enlace npm o Lerna, pero solo para los módulos npm que no se han transpilado (¿verdad? No veo ningún otro caso de uso a menos que confirme módulos dentro de /node_modules )

¿Por qué no admitir enlaces simbólicos? ¿es más difícil de mantener?

También quería probar su rama en mi aplicación, pero no estoy seguro de cuál es la mejor manera de hacerlo. ¿Existe algún procedimiento conocido para que podamos probar fácilmente una rama y no sea demasiado doloroso para el evaluador? He probado algunas cosas como:

  • npm install https://github.com/arunoda/next.js.git#add -706: falla porque la siguiente carpeta / bin está vacía en el repositorio de github
  • git clon de la bifurcación dentro de / node_modules: no mucho éxito (pero podría deberse a mi configuración específica de Lerna)

¿Cuál es la mejor manera de probar una bifurcación actualmente?

Si está buscando hacer esto con next.config.js : module.exports = { webpack: (config , entonces config.module.rules tiene algunas cosas, parece que necesita cambiar una de estas reglas o agregar una. :

  { loader: 'babel-loader',
    include: '/Users/me/gh/guide/node_modules/next/dist/pages',
    options: 
     { babelrc: false,
       cacheDirectory: true,
       sourceMaps: 'both',
       plugins: [Object] } },
  { test: /\.js(\?[^?]*)?$/,
    loader: 'babel-loader',
    include: 
     [ '/Users/me/gh/guide',
       '/Users/me/gh/guide/node_modules/next/dist/pages' ],
    exclude: [Function: exclude],
    query: 
     { babelrc: true,
       cacheDirectory: true,
       sourceMaps: 'both',
       presets: [] } } ]

Esperando la sintaxis más simple sugerida.

Perdón por mi ignorancia. No puedo ver cuál es la resolución de este problema. Nos encantaría importar es6 a nuestro código base, necesitamos la agitación del árbol.

¿Hay un PR en esto?

@andrewmclagan Este problema aún está abierto y tiene un PR relacionado que probablemente no satisfará a todos (como los usuarios de LernaJS)

¿Cuál es el estado de esto? ¿Hay otras formas de hacer que el paquete web de next transpile archivos importados de node_modules?

@slorber, echaré un vistazo a las relaciones públicas. Contribuya con nuestro caso de uso.

Estoy enfrentando una especie de problema similar. Intentando usar el paquete get-urls . Funciona con dev pero cuando lo compilo. Recibí un error de uglify

...
{ Error: commons.js from UglifyJs
...

¿Hay alguna solución para esto, por favor?

Arunoda trabajará en ello en algún momento aquí. Lo ha hecho antes en el # 749

Me encantaría ver implementada esta función. Como mencionó @philcockfield , es un escenario común construir una biblioteca de módulos que dependen de la transpilación de Next.js, y sería genial poder compartir componentes entre proyectos.

Esto no solo es necesario para sacudir árboles. También para complementos de babel como styled-jsx . Entonces, si tiene un módulo (como una biblioteca) que usa un complemento de babel, la mejor solución es incluir el código fuente de ES6 y permitir que su aplicación lo transpile desde node_modules. Por supuesto, el siguiente ya incluye styled-jsx por defecto.

Esto es lo que hice

// next.config.js
exports.webpack = config => (config.module.rules = config.module.rules.map(({exclude, ...rest}) => ({
  exclude: Object.prototype.toString.call(exclude) === '[object Function]' ? (str => !/mycomponents/.test(str) && exclude(str)) : exclude,
  ...rest
})), config);

Básicamente reemplacé cada exclude con una función personalizada.
No sé qué estoy haciendo mal, pero no puedo hacer que funcione.
Necesito que el contenido de node_modules/mycomponents también sea transpilado por Next.js

Ni siquiera funciona si anulo por completo todas las exclusiones con una matriz vacía

exports.webpack = config => (config.module.rules = config.module.rules.map(({exclude, ...rest}) => ({
  exclude: [],
  ...rest
})), config);

Por favor, ayúdame :)
Gracias

Hola chicos ( @thealjey ) Llevo meses transpilando módulos con tecnología de jsnext:main .

No estoy usando next.js pero espero que ayude.

@damianobarbati no, lamentablemente no
Configurar el paquete web directamente para transpilar lo que sea no es difícil, pero estoy luchando para que esto funcione en el contexto de Next.js

Hola a todos, ¿alguien ha encontrado una solución?

Tengo un módulo de nodo vinculado ES6 local que necesito importar en mi proyecto, ¡pero no puedo hacer bien el vudú del paquete web!

Estoy seguro de que hay una mejor manera, pero ejecutamos todo a través de babel en la compilación:

next build && babel .next/*.js --out-dir . --presets=es2015,react

¿Esto murió? Estoy buscando una forma de transpilar un módulo personalizado y parece que todavía no es posible.

@mattfelten está en la hoja de ruta para v5 👍

¿Alguien tiene un ejemplo de una solución alternativa para esto?

@timneutkens ¿Hay alguna línea de tiempo para esto? Aprecie que a menudo es una pregunta imposible, pero estamos tratando de determinar nuestra pila en el trabajo a partir de ahora y este es un gran bloqueador para nosotros. :)

Las sugerencias de soluciones también son válidas.

@thealjey se da cuenta de que este es un comentario antiguo, pero su solución probablemente no funcionó porque también hay un include especificado que debería anularse.

Actualización: analicé esta estrategia, pero no es sensata dados los diferentes cargadores para diferentes directorios de módulos dentro de la configuración interna de next.js. Esto deberá ser de primera clase.

@chrisui mi solución (temporal) fue usar babel-plugin-module-resolver , configurado así - "plugins": [["module-resolver", {"root": ["./"]}]]
De ninguna manera es una solución perfecta, pero, dado que todo lo demás falló, funciona por ahora.
gracias a eso no necesito escribir un montón de ../ con cada importación
esta podría ser una mejor solución para algunos, aunque ciertamente no ayuda con la reutilización

@thealjey, ¿ podrías dar un ejemplo?
Tengo una configuración de proyecto en la que intento esto en vano ...
https://github.com/jamesgorrie/nappy

Con mucho gusto trataría de conseguir un PR ya que esto haría nuestra vida mucho más fácil, pero hay algunas preguntas como: ¿Debería next.js soportar la transpilación de ciertos módulos o debería depender del transpilador, pero el next.js sigue la resolución del módulo más estrictamente. No estoy seguro de a quién preguntar o por dónde empezar aquí como nuevo en next.js .

está en la hoja de ruta para v5 👍

@timneutkens, ¿esto se convirtió en v5?

preguntándose por saber.

Solo mira dónde se fusionó. esto se fusionó hace 8 días. 5.0.0 fue lanzado hace 2 días. del Ramal de Canarias donde se fusiona con ...

¿Alguien tiene un ejemplo de cómo se puede implementar esto? ¿Se supone que funciona así, como se mencionó anteriormente?

module.exports = {
    transpileModules: ['my-npm-module']
}

o se ve diferente?

Estoy confundido. @timneutkens El enlace mencionado anteriormente es a un PR que todavía está abierto. ¿Esto NO se ha fusionado todavía en la v5?

EDITAR: No importa, esto es solo un PR para resaltar el ejemplo.

Es un ejemplo, puede usar el ejemplo sin que se fusione. transpileModules es algo que abordaremos más adelante.

Como regla general: cuando un problema está abierto, no se publica.

@brianyingling He convertido el ejemplo en un complemento para una solución provisional (solo v5).
Está funcionando para nosotros en este momento, hasta que se implemente la solución oficial más sólida.

https://www.npmjs.com/package/@weco/next -plugin-transpile-modules

Me encantaría ver un ejemplo de esto para un solo módulo en el código base de la aplicación.

Por ejemplo, tengo un módulo que utilizo tanto en el lado del servidor como en el del cliente. No he podido hacer que funcione ninguno de los ejemplos anteriores, ya sea factorizando el módulo en su propio módulo separado y yarn link inglo, o pirateando las reglas del paquete web.

Aquí hay una reproducción simple: https://github.com/statico/nextjs-with-async-lib

// pages/index.js
import { foo } from '../lib/test'
export default () => <div>hello {String(typeof foo)}</div>

// lib/test.js
async function foo () {}
module.exports = { foo }

@timneutkens me dice que esto se debe a que estoy usando async/await en el módulo compartido. Supongo que mi solución podría ser eliminar async / await y cambiar todo a devoluciones de llamada al estilo .then() .

Bien, encontré una solución que funciona para mí.

Primero, agregué la configuración config.resolve.symlinks = false a mi configuración next.config.js por https://github.com/zeit/next.js/issues/3018#issuecomment -380879576

// next.config.js
webpack: (config, { dev }) => {
  config.resolve.symlinks = false
  return config
}

Luego puse mi biblioteca compartida, un archivo .js que usa exportaciones CommonJS y palabras clave async / await , en un subdirectorio de la aplicación llamado shared :

// shared/index.js
async function foo () {}
module.exports = { foo }
// shared/package.json
{
  "name": "@myapp/shared",
  "version": "1.0.0",
  "main": "index.js",
  "license": "UNLICENSED",
  "private": true,
  "dependencies": { ... }
}

Y finalmente agregué un script postinstall para vincularlo todo cuando alguien haga un yarn install en la aplicación principal:

// package.json
{
  ...
  "scripts": {
    "postinstall": "cd shared ; yarn -s unlink ; yarn link && yarn && cd .. && yarn link @myapp/shared",
   ...

Ahora mis pruebas de Mocha pasan en el lado del servidor, mi servidor Koa personalizado se inicia bien y no hay más Cannot assign to read only property 'exports' of object '#<Object>' locos en mis páginas de NextJS.

Tuve este mismo problema al actualizar a NextJs 5.1.0. Uno o dos de los módulos de nodo en el siguiente no transpilaban funciones de flecha gruesa y arrojaban errores en IE11. Anteriormente había pasado por la configuración de polyfills individuales y, al final, opté por apuntar a esos archivos de módulos con babel-polyfill en mi next.config.js con esto:

module.exports = {
  webpack: (config, { dev }) => {
    const polyfill = new Promise((resolve, reject) => {
      const originalEntry = config.entry

      originalEntry().then(entries => {
        if (entries['main.js']) {
          entries['main.js'].unshift('./client/polyfills.js')
          entries['main.js'].unshift('babel-polyfill')
        }
        config.entry = entries

        resolve()
      })
    })

    config.module.rules.push(
     {
        test: path.resolve('./node_modules/next/node_modules/'),
        loader: 'babel-loader',
        options: {
          babelrc: false,
          cacheDirectory: false,
          presets: ['es2015']  
        }
      }
    )

    return polyfill.then(() => { return config })
  }
}

Espero que esto ayude a alguien.

ESM funciona a las

Con un servidor Next.js personalizado en index.js , puedo ejecutar este comando para iniciar el servidor y esm se activa perfectamente, resolviendo módulos ES en paquetes de proyectos enlazados simbólicamente con Lerna.

node -r esm index.js

@curran cool, ¿puede reemplazar babel-node?

@curran Evitaría hacer eso en producción

@blackbing No lo sé.

@thealjey ¿

En caso de que alguien esté buscando una solución rápida y fácil, esto es lo que hice. Creé un subdirectorio, shared/ , con cualquier código que queramos ejecutar tanto en el backend a través de un script de nodo independiente como en el cliente a través de NextJS. Tiene su propio package.json y declara su nombre como @myproject/shared .

Luego, en el proyecto principal (padre), agregué un script postinstall a package.json así: cd shared && yarn -s unlink >/dev/null 2>&1 ; yarn -s link && yarn -s && yarn link @myproject/shared - luego ejecute yarn al menos una vez, y cambie sus importaciones a import { whatever } from '@myproject/shared/somefile'

De esta manera, el código compartido funciona sin pasos de transpilación locos, además no tiene que volver a ejecutar yarn / npm cada vez que realiza una actualización, ya que yarn link hace una enlace simbólico.

Para aquellos que usan TypeScript, @weco/next-plugin-transpile-modules no debería funcionar. Creé una bifurcación para manejar los withTypescript Next: https://github.com/KeitIG/next-plugin-transpile-modules

Sin embargo, todavía necesito descubrir cómo hacer las cosas correctamente cuando también necesitamos tener código del lado del servidor en TypeScript.

¿Alguna noticia sobre esto?

Y otro más por mí, en la siguiente esencia. Maneja TypeScript y también paquetes específicos de @scope , en lugar de todos los paquetes. https://gist.github.com/trusktr/44400d0d016c506629b4f914799dc9cd

Acabo de armar un ejemplo de trabajo simple que usa esm y lerna

https://github.com/curran/nextjs-esm-example

/ cc @jdalton

Personalmente conseguí que esto funcionara con lo siguiente next.config.js :

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.js$/,
      include: /node_modules/,
      use: [
        options.defaultLoaders.babel
      ]
    })

    return config
  }
}

Babels todo en node_modules , que necesitaba para lograr la compatibilidad con IE 11 ...

También agradecería una solución para esto, luchando por agregar paquetes npm no transpilados a mi proyecto. Tuve que descargarlos al proveedor / por ahora :(
Realmente molesto

@ bel0v Creo que ya debería poder lograr esto con next-plugin-transpile-modules . Es probable que este problema se solucione. cc / @timneutkens

Todavía me gustaría investigar soluciones alternativas.

Recientemente, Jamie escribió un hilo muy detallado sobre el problema de compilar node_modules: https://twitter.com/jamiebuilds/status/1080840492525350912

Leí el hilo de Jamie, aunque también me gustaría compartir la opinión de Henry Zhu y Babel sobre esta situación y solución.
https://babeljs.io/blog/2018/06/26/on-consuming-and-publishing-es2015+-packages

(No estoy en desacuerdo con Tim, solo pensé en compartir, muchos pros y contras. Podría ayudar a Tim en la investigación de soluciones alternativas)

Sí, hemos estado hablando con muchas personas sobre este tema durante el último medio año, incluido Henry 😄

A pesar de las preocupaciones sobre la transpilación de node_modules, querer transpilar sus propios paquetes en un monorepo es un requisito muy común, al cual estas preocupaciones no se aplican

@dcalhoun Lo intenté, pero desafortunadamente todavía recibo un error de token inesperado. Hay un problema de Next 7 abierto en este complemento que podría estar relacionado

@ bel0v

Debería leer las preguntas frecuentes;) hay una solución a este problema: https://github.com/martpie/next-plugin-transpile-modules#i -have-problem-make-it-work-with-nextjs-7

He estado usando este complemento en varios proyectos y hace bien el trabajo. El problema de Next 7 es extraño, no estoy seguro de si proviene de Next o Babel, abrí un problema aquí de todos modos: https://github.com/zeit/next.js/issues/5393

@martpie, sí, creo que lo he intentado ... de todos modos, lo intentaré de nuevo.

@martpie hemos comenzado a usar next7 con un babel.config.js consistente y espacios de trabajo de hilo, podría ver si puedo configurar un ejemplo simple.

He bifurcado un ejemplo básico aquí.
https://github.com/bel0v/learnnextjs-demo
en él, instalé una dependencia no transpilada (elementos cableados), obtuve un error de compilación Unhandled Rejection (SyntaxError): Unexpected token { e intenté solucionarlo de la manera sugerida.
Estoy pensando que tal vez necesite algunos complementos de babel adicionales para que funcione ... 🤔

@ bel0v en las preguntas frecuentes nuevamente, hay una explicación de por qué las configuraciones de Lerna no funcionan (TL, DR; probablemente estás usando incorrectamente)

@martpie ¡ah, lo tengo! No me di cuenta de que el paquete de terceros se configuró con Lerna. Gracias

Parece que https://twitter.com/jamiebuilds se ha suspendido, por lo que ya no puedo leer el hilo allí. # 3018 Se cerró en referencia a este problema, así que me pregunto cuáles son los enfoques alternativos que se están considerando.
¿Representan estos el estado del arte / las mejores prácticas de next.js para estos casos de uso de cajeros automáticos?
https://github.com/curran/nextjs-esm-example
https://github.com/wellcometrust/next-plugin-transpile-modules
https://github.com/martpie/next-transpile-modules
https://github.com/zeit/next.js/tree/canary/examples/with-yarn-workspaces

Entonces, si usted, como yo, está trabajando en un proyecto que debe admitir IE11, realmente debe transpilar todo el código dentro de node_modules/ . En Next.js 7.x estaba usando la siguiente configuración, que funcionó muy bien.

Desafortunadamente, dejó de funcionar en Next.js 8.x con errores de que los módulos no pudieron importar otros módulos porque no tenían una exportación predeterminada. Luego se me ocurrió la siguiente configuración para Next.js 8.x, que solo transpila el código en node_modules/ con @babel/preset-env , y ningún otro complemento.

Esto se combina configurando mi propiedad browserlist en package.json :

  "browserslist": "defaults, IE >= 11, EDGE >= 14, Safari >= 11, Chrome >= 41, Firefox >= 52",

Siguiente 7.x

next.config.js

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.js$/,
      include: /node_modules/,
      use: [
        options.defaultLoaders.babel,
      ],
    })

    return config
  },
}

Next.js 8.x

next.config.js

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.js$/,
      include: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],
          plugins: ['@babel/plugin-syntax-dynamic-import'],
        },
      },
    })

    return config
  },
}

Desafortunadamente, todavía no he descubierto cómo usar @babel/plugin-transform-runtime con esta configuración, por lo que probablemente arrojará bastantes ayudantes en el código 😞 espero que gzip se encargue de ello 😆 😅


Creo que sería increíble si Next.js pudiera darnos una opción para transpilar correctamente node_modules/ para trabajar con cualquier browserlist que tenga. Parece que los sitios grandes que tienen usuarios corporativos dependen de esto para admitir correctamente los navegadores más antiguos.

Como mantenedor de next-transpile-modules (basado en el increíble trabajo de @jamesgorrie), me complace ayudar a cualquiera que se enfrente a este problema aquí.

He estado trabajando en proyectos profesionales durante más de un año con este complemento, y hasta ahora funcionó muy bien.

El soporte nativo de Next.js, por supuesto, sería increíble y me complacería ayudar a integrar esta función en el paquete next . Sé que Tim tenía algunas ideas que quería probar, pero de todos modos.

¡Salud!

@martpie Revisé rápidamente su proyecto, pero no encontré una manera rápida de transpilar _todos_ los módulos, ¿es posible? ☺️

Además, veo que está eligiendo options.defaultLoaders.babel y usándolo como cargador de babel. Al hacer eso con Next.js 8.x, tuve el problema de que algunos módulos no se reconocerían correctamente como un módulo CJS después de eso, y luego otras bibliotecas no pudieron importarlos, por ejemplo:

./pages/_glamor.js
Attempted import error: 'css' is not exported from 'glamor'.

./components/project-selector.js
Attempted import error: 'react-select/lib/Async' does not contain a default export (imported as 'AsyncSelect').

./node_modules/react-select/dist/react-select.esm.js
Attempted import error: 'react-input-autosize' does not contain a default export (imported as 'AutosizeInput').

./pages/signup/full.js
Attempted import error: 'react-select/lib/Creatable' does not contain a default export (imported as 'CreatableSelect').

./components/markdown-editor.js
Attempted import error: 'react-simplemde-editor' does not contain a default export (imported as 'SimpleMDEEditor').

./components/pagination.js
Attempted import error: 'react-js-pagination' does not contain a default export (imported as 'UpstreamPagination').

./node_modules/react-google-recaptcha/lib/es/recaptcha-wrapper.js
Attempted import error: 'react-async-script' does not contain a default export (imported as 'makeAsyncScriptLoader').

./pages/_glamor.js
Attempted import error: 'rehydrate' is not exported from 'glamor'.

Es por eso que cambié a proporcionar una configuración de babel personalizada para node_modules/ , que solo transpila el código usando preset-env , y omite las transformaciones específicas de Next.js. Que piensas de esta aproximación?

Saludos 🍻

@LinusU ¿ Quizás probar transpileModules: ['(.*?)'] y decirme si funciona?

Pero es posible que no funcione en una versión importante futura, así que tenga cuidado.

De manera más general, no recomiendo (lea "altamente desalentado") transpilar la carpeta node_modules , la compilación tomará una eternidad y los paquetes deben proporcionar código compatible con ES3 (por lo tanto, compatible con IE11).

¡Transpile solo el módulo que necesites! (como lodash-es , módulos locales, etc.)

Los paquetes deben proporcionar un código compatible con ES3 (por lo tanto, compatible con IE11).

Sin embargo, esta no es la realidad que he visto y, en realidad, no estoy de acuerdo. Los autores del módulo nunca sabrán exactamente a qué navegadores me dirijo, y si envían código más antiguo, potencialmente penalizarán a los usuarios que se dirigen a navegadores modernos.

tomará una eternidad compilar

Es un poco lento al inicio para mí, pero después de eso, parece que se almacena en caché y cuando realizo cambios en una página específica, veo recargas casi instantáneas.

¡Transpile solo el módulo que necesites!

Esto me obligaría a saber exactamente qué paquetes son compatibles con IE11 y cuáles no, así como mantener esta información actualizada en cualquier momento en que cambie cualquier dependencia (incluso dependencias transitorias). No veo cómo esto es realista 🤔

Lo importante es que los puntos de entrada de ESM que se proporcionan en package.json module son comúnmente ES5 con importaciones / exportaciones de ES6 para sacudir árboles. Así que este es el trabajo de un empaquetador (Webpack) y no de un transpilador (Babel), a menos que se indique lo contrario. Muchos paquetes bien mantenidos ya tienen puntos de entrada de ESM, por ejemplo, redux/es para Redux que fue mencionado por OP.

Si está buscando hacer esto con next.config.js : module.exports = { webpack: (config , entonces config.module.rules tiene algunas cosas, parece que necesita cambiar una de estas reglas o agregar una. :

  { loader: 'babel-loader',
    include: '/Users/me/gh/guide/node_modules/next/dist/pages',
    options: 
     { babelrc: false,
       cacheDirectory: true,
       sourceMaps: 'both',
       plugins: [Object] } },
  { test: /\.js(\?[^?]*)?$/,
    loader: 'babel-loader',
    include: 
     [ '/Users/me/gh/guide',
       '/Users/me/gh/guide/node_modules/next/dist/pages' ],
    exclude: [Function: exclude],
    query: 
     { babelrc: true,
       cacheDirectory: true,
       sourceMaps: 'both',
       presets: [] } } ]

Esperando la sintaxis más simple sugerida.

Funciona bien para mi

{
    test: /\.js(\?[^?]*)?$/,
    loader: 'babel-loader',
    include: [
        path.resolve(__dirname, './node_modules/next/dist/pages'),
    ],
    query: {
        cacheDirectory: true,
        sourceMaps: 'both',
        presets: ['@babel/preset-env'],
        plugins: ['@babel/plugin-proposal-object-rest-spread']
    }
},

Me encontré con este problema usando un repositorio mono de Lerna y me estaba rascando la cabeza en cuanto a cuál era la causa. Dado que el error proviene del paquete web, no proporciona buenos detalles, además de que falta un cargador, lo cual no es útil. ¡Afortunadamente encontré este problema de github!

Voy a dejar mi solución aquí para cualquier otra persona que busque este problema y también esté usando Lerna:

Cree una secuencia de comandos prepublicada para el paquete compartido que transpile la fuente en un directorio dist y dígale a Lerna que apunte al directorio dist al vincular:

// package.json
"main": "dist",
"scripts": {
  // I'm using the react-app preset because it's easy
  "prepublish": "babel --presets react-app --plugins @babel/plugin-transform-modules-commonjs src --out-dir dist"
},
// This instructs Lerna to use dist when symlinking
"publishConfig": {
  "directory": "dist"
}

Ahora, cuando lerna bootstrap ejecutará el script de prepublicación y transpilará la fuente para que Next pueda consumirla.

Si está usando lerna , puede crear enlaces simbólicos para que se transpilen usando next-transpile-modules . Cómo usar ese paquete con lerna está escrito en la parte inferior de la documentación.

Para cualquiera que busque compartir código en las aplicaciones de NextJs, solo me gusta informar que la solución de @LinusU funcionó para mí cuando intento compartir componentes y utilidades de React entre múltiples aplicaciones de NextJs en mi repositorio mono:

// next.config.js
const aliasPathsToResolve = [
    { name: 'components', path: path.resolve(__dirname, './components') },
    { name: 'Common', path: path.resolve(__dirname, '../../common/react/') },
]
module.exports = () => {
    return  {
        webpack(config, { defaultLoaders }) {
            config.module.rules.push({
            test: /\.(js|jsx)$/,
            include: [path.resolve(__dirname, '../../common/react/')],
            use: [defaultLoaders.babel],
        })

            /** Resolve aliases */
        aliasPathsToResolve.forEach((module) => {
            config.resolve.alias[module.name] = module.path
        })
        }
    }
}

Estoy usando la última versión de NextJs en el momento de esta publicación.

@ Lwdthe1 Probé su código e inicialmente obtuve este error:

TypeError: Cannot read property 'then' of undefined
    at getBaseWebpackConfig (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/build/webpack-config.js:85:25)
    at async Promise.all (index 0)
    at async HotReloader.start (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/server/hot-reloader.js:14:1675)
    at async DevServer.prepare (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/server/next-dev-server.js:7:223)
    at async /c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/cli/next-dev.js:22:359

Hice algunos ajustes y terminé con esto:

const path = require("path");

const libPath = "../components/src"
const aliasPathsToResolve = [
  { name: "Common", path: path.resolve(__dirname, libPath) }
];

module.exports = {
  webpack: (config, { defaultLoaders }) => {
    config.module.rules.push({
      test: /\.(js|jsx)$/,
      include: [path.resolve(__dirname, libPath)],
      use: [defaultLoaders.babel]
    });

    /** Resolve aliases */
    aliasPathsToResolve.forEach(module => {
      config.resolve.alias[module.name] = module.path;
    });
    return config
  }
};

Pero se encontró con otro error:

export { default as NavBar } from "./NavBar/NavBar"
^^^^^^

SyntaxError: Unexpected token 'export'
    at wrapSafe (internal/modules/cjs/loader.js:1055:16)
    at Module._compile (internal/modules/cjs/loader.js:1103:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1159:10)
....

que parece haber sido enfrentado antes en # 2850 y # 883.

Entonces parece que la única solución es: https://github.com/martpie/next-transpile-modules#but -i-really-need-to-make-it-work-with-lerna

Por lo que escuché, pronto se presentará RFC sobre cómo Next.js planea resolver este problema, pero si alguien necesita solucionarlo ahora mismo, publiqué en npm mi solución de https://github.com/ zeit / next.js / pull / 10098 que puede usar poniendo lo siguiente en package.json:

    "next": "npm:@sheerun/[email protected]",

y siguiendo a next.config.js:

  babelIncludeRegexes: [/turf/],

(en mi caso, necesitaba que todos los archivos de césped estuvieran precompilados con babel)

¿Este problema tiene algún progreso?

Utilizo next.js 9.2.0, pero la opción babelIncludeRegexes no funciona

¿Este problema tiene algún progreso?

next-transpile-modules tiene como objetivo resolver este problema exactamente, ¿lo intentaste?

Hola @martpie ,

Ya resolví mi problema de edición de archivos .babelrc. Hago referencia a este problema

Gracias

@martpie Estoy usando next-transpile-modules pero aún así, me enfrento al siguiente error mientras intento compilar la aplicación. Estoy usando monorepo con código base compartido. Intentando acceder a componentes compartidos como '@ myapp / shared / components / componentname.js'. Estoy usando nextjs 9.xy custom next.config.js .

Error
'
Error de análisis del módulo: token inesperado (12: 4)
Es posible que necesite un cargador adecuado para manejar este tipo de archivo, actualmente no hay ningún cargador configurado para procesar este archivo. Ver https://webpack.js.org/concepts#loaders
| const Spinner = props => {
| const renderDefaultSpinner = (spinnerClass, {... otros}) => (
>


| );
|

Se produjo un error de compilación
Error:> La compilación falló debido a errores del paquete web
'

next.config.js
const withTM = require('next-transpile-modules')(['<strong i="26">@myapp</strong>']); module.exports = withPlugins([withTM, withBundleAnalyzer], { ... }

Por favor ayúdenme con lo que estoy haciendo mal aquí.

@ raghav1086 ¿Puede abrir un problema en el repositorio? ;) evitará el ruido para la gente de aquí.

+1

Tengo un directorio src/ para mi proyecto y lib/ para un marco de inicio que exporta algunas utilidades / envoltorios comunes que reutilizo en algunas aplicaciones de nextjs diferentes (mi punto de partida)

lib no se nota cuando inicio el servidor de desarrollo. cualquier componente de lib / no pasa por el cargador y da un error

Usé una variación de la solución de config.resolve.modules lugar de recorrer la matriz aliasPathsToResolve .

  webpack: (config, options) => {
    config.resolve.modules = [
      './src/',
      './lib/',
      'node_modules'
    ];

    config.module.rules.push({
      test: /\.(js|jsx)$/,
      include: [path.resolve(__dirname, './lib/')],
      use: [options.defaultLoaders.babel],
    });

¿Cuál es la solución de trabajo para lerna, nextjs y babel en estos días?

Estoy tratando de evitar la transpilación previa de mis bibliotecas antes de la importación, y me he topado con una pared de ladrillos con todas las soluciones aquí. Esto es lo que no puedo hacer funcionar:

  • next-transpile-modules .
  • restablecer la configuración de entorno preestablecido.
  • actualizar las reglas next-babel-loader include y exclude para aprobar / reprobar respectivamente.

@mikestopcontinúa next-transpile-modules preparado para mí con TypeScript.

@calebmpeterson y @martpie (¡te veo! 👀). Volví con un círculo al enchufe y el problema parece ser que no hay forma de hacer referencia a los submódulos. Por ejemplo, el patrón '@ mono / components' no admitirá la importación de '@ mono / components / Div' o lo que sea. Y especificar '@ mono / components / Div' como patrón tampoco funciona ... no es que quisiera hacer eso para cada componente compartido. También probé la ingeniería inversa de la generación de expresiones regulares para crear patrones de coincidencia, y mientras la expresión regular de salida funciona, algo más está sucediendo bajo el capó que no lo es.

Idealmente, me gustaría especificar '@ mono` para encargarme de todo, y dejar que mi package.json sea la única fuente de verdad de lo que depende cada una de mis aplicaciones. Del mismo modo, me gustaría evitar mantener archivos de índice que importan / exportan todo en cada una de mis bibliotecas solo para poder acceder a los submódulos.

Para volver atrás, creo que el problema actual podría resolverse por completo si hubiera alguna forma de pasar rootMode: 'upward' a next-babel-loader , para que babel pudiera manejar la lógica de transpilación. Tal vez esto abra otros problemas relacionados con Next, pero la raíz del problema parece ser la forma atípica en que Next se enreda en webpack y babel. Seguramente, ¿hay una manera de dejar babel-loader separado de la lógica adicional de Next?

Solo una actualización en el frente next-transpile-modules . Había diagnosticado mal el error. Ninguna importación funciona con este método (índice o submódulo) si necesita una configuración .babelrc . La configuración personalizada simplemente no se aplica al código requerido. Esto es nuevamente un problema de rootMode: 'upward' .

@mikestopcontinues Necesita usar babel.config.js (configuración global) con next-transpile-modules , y no .babelrc (configuración local), se explica en las preguntas frecuentes;)

@martpie No tienes idea de lo avergonzado que estoy. Tuve que haber leído esa línea una docena de veces en las últimas semanas y nunca me molesté en hacer clic para ver el problema. Eso funcionó totalmente. ¡Gracias!

next-transpile-modules rompió React para mí. Ahora arroja que uso ganchos no válidos, mientras que transpilé TRES módulos de ejemplo

¿Alguien podría repetir cuál es la mejor configuración para que la transpilación funcione? No entiendo lo que tengo que escribir en babel.config.js

@masbaehr en la mayoría de los casos simplemente agregando next-transpile-modules a su configuración next.config

El único problema es que next-transpile-modules no admite Yarn 2 pnp.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

havefive picture havefive  ·  3Comentarios

YarivGilad picture YarivGilad  ·  3Comentarios

jesselee34 picture jesselee34  ·  3Comentarios

sospedra picture sospedra  ·  3Comentarios

wagerfield picture wagerfield  ·  3Comentarios