Next.js: Ajout du support pour transpiler les modules dans node_modules

Créé le 9 janv. 2017  ·  103Commentaires  ·  Source: vercel/next.js

Maintenant, certains d'entre nous expédient des packages NPM (spécialement des composants) écrits en ES2015 sans les transpiler.

C'est une très bonne chose, surtout s'ils sont utilisés dans un projet comme Next.js ou CRA (qui transpile). Ils offrent des avantages tels que :

  • Pas besoin de transpiler avant d'expédier à NPM
  • Bénéficiez du tree-shaking de Webpack 2

Mais nous ne pouvons pas le faire maintenant, nous excluons tout ce qui se trouve à l'intérieur de node_modules de babel transpiling.

Voici donc la solution proposée.

Nous avons une entrée dans next.config.js pour inclure des modules qui doivent passer par babel. Voir:

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

Commentaire le plus utile

Plus j'utilise next.js sérieusement et que je construis une riche bibliothèque de modules autour, plus cette fonctionnalité devient importante. C'est en train de devenir un vrai PITA reproduisant l'étape de compilation babel dans mes modules internes.

??

Tous les 103 commentaires

  • Pourquoi n'est-ce pas faisable avec l'extension webpack() ?
  • transpileModules sonne mieux
  • Accepterons-nous les expressions régulières ?

Pourquoi n'est-ce pas faisable avec l'extension webpack() ?

J'espère que vous voulez dire config webpack personnalisée. C'est faisable. Mais cela se trouve dans un chargeur existant. Obtenir cela est un peu plus difficile.

transpileModules sonne mieux

Impressionnant. Je vais mettre à jour.

Accepterons-nous les expressions régulières ?
Ouais. Bien sur.

Hey,

Alors que je démarre mon propre site Web, j'essaie de nouvelles technologies comme Lerna/Next/Styled... et je serais heureux de fournir des commentaires à ce sujet.

J'ai ouvert un problème en double où j'ai essayé d'importer/transpiler un module basé sur CRA dans mon module NextJs mais je ne savais pas comment faire en sorte que la transpilation se produise (notez que j'aimerais garder mon module exécutable de manière autonome)

J'ai également remarqué que Babel, également basé sur Lerna, transpile chaque module avant de les exposer, mais il me semble préférable de faire comme @arunoda le suggère et de laisser l'application cliente effectuer le transpilation.

J'aimerais avoir une seule configuration babel pour mon client et partager cette configuration avec tous mes modules découplés. Ce n'est probablement pas si facile si je veux garder la possibilité d'exécuter mes modules de manière autonome, en dehors de Next runner

Mon projet de test actuel est ici : https://github.com/slorber/playground/ J'essaierai de le mettre à niveau dès qu'il y aura un fork/PR. @arunoda travailles-tu dessus ?

@slorber actuellement, nous nous concentrons sur la version 2.0 et nous

Je n'ai pas commencé à travailler là-dessus, mais nous pouvons le faire juste après la 2.0.

Bon alors je vais faire une fourchette. J'utilise déjà la version bêta de la version 2.0.0 car je ne construis pas de site Web critique et je ne pense pas que webpack 1.13 résolve le champ jsnext:main/module .

Je ne suis pas un expert en bundler mais je pense que je préférerais utiliser le champ "module" de package.json non? "main" semble pour le code déjà transpilé pour autant que je sache. Mais comme la configuration webpack permet d'inclure/exclure la transpilation, je ne suis pas sûr que ce soit pertinent. Une recommandation sur lequel des 3 champs je préfère utiliser ?

@slorber Je pense que webpack ne prend en charge que main tout comme NPM. Vous pouvez l'utiliser.
Nous pouvons vérifier le chemin du fichier dans la fonction exclude dans notre next.conf.js

Hmm d'après ce que j'ai vu en pratique contre Next 2.x, j'ai vu que le module fonctionne (mais échoue plus tard au moment de l'exécution car non transpilé) alors que jsnext:main ne fonctionnait pas (pour autant que je m'en souvienne). Mais il est censé être pris en charge .

Quoi qu'il en soit, jsnext:main ou module ne semble pas être la solution à ce problème, donc pour les modules internes à l'entreprise, il suffit probablement d'activer la transpilation

La communauté ne s'est pas mise d'accord sur une approche, n'est-ce pas ? Par exemple, j'ai pu utiliser react-youtube l'autre sans problème. Je suppose qu'un grand nombre de modules sont transpilés avant de publier ?

Réf : https://github.com/rauchg/blog/blob/master/components/post/youtube.js

Oui, il est logique de toujours transpiler avant de publier car vous ne savez pas qui/comment le module sera consommé et vous ne voulez pas forcer le client à configurer les paramètres Babel appropriés pour votre bibliothèque. C'est ce que propose Rollup : publier le module transpilé de différentes manières afin que le bundler puisse décider lequel utiliser.

Mais pour les packages internes de l'entreprise, les paramètres de transpilation peuvent être les mêmes sur plusieurs projets (comme un préréglage babel) et il est logique pour moi de laisser le bundler client transpiler toutes les dépendances de l'entreprise

Tout à fait d'accord @slorber - ce serait très pratique pour les modules internes si vous divisez votre projet et isolez les choses autant que possible.

Et @rauchg / @arunoda prenant en charge les RegExp serait vraiment bien, vous pourriez donc avoir une entrée qui capture tous les modules internes de l'entreprise, en utilisant par exemple l'espace de noms de l'organisation NPM :

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

Belle suggestion @philcockfield

Hé peut-être que cela pourrait valoir la peine de proposer des préréglages. Il me semble que la plupart des outils (lien Lerna/npm...) reposent sur des liens symboliques, alors pourquoi pas quelque chose d'aussi simple que :

```javascript
module.exports = {
transpileModules : ["liens symboliques"]
}
````

Plus j'utilise next.js sérieusement et que je construis une riche bibliothèque de modules autour, plus cette fonctionnalité devient importante. C'est en train de devenir un vrai PITA reproduisant l'étape de compilation babel dans mes modules internes.

??

Je travaille dessus aujourd'hui :)

@philcockfield essayez ceci: https://github.com/zeit/next.js/pull/749

merci @arunoda

Donc, comme commenté sur votre PR, si cela ne prend pas en charge les liens symboliques, la fonctionnalité sera un peu limitée car elle ne fonctionnera pas avec le lien npm ou Lerna, mais uniquement pour les modules npm qui ne sont pas transpilés (non? Je ne vois pas d'autre cas d'utilisation sauf si vous commitez des modules dans /node_modules )

Pourquoi ne pas prendre en charge les liens symboliques ? est-ce plus difficile à supporter ?

Je voulais également tester votre branche sur mon application, mais je ne sais pas quelle est la meilleure façon de le faire. Existe-t-il une procédure connue pour que l'on puisse tester facilement une branche et que ce ne soit pas trop pénible pour le testeur ? J'ai essayé des trucs comme :

  • npm install https://github.com/arunoda/next.js.git#add -706 : échoue car le dossier /bin suivant est vide sur le référentiel github
  • clone git du fork dans /node_modules : pas beaucoup de succès (mais c'est peut-être à cause de mes paramètres spécifiques à Lerna)

Quelle est la meilleure façon de tester une fourche actuellement ?

Si vous envisagez de le faire avec next.config.js : module.exports = { webpack: (config , alors config.module.rules a quelques éléments, il semble que vous deviez modifier l'une de ces règles ou en ajouter une ? :

  { 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: [] } } ]

Dans l'attente de la syntaxe plus simple suggérée.

Désolé pour mon ignorance, je ne vois pas quelle est la résolution de ce problème? Nous aimerions importer es6 dans notre base de code, nous avons besoin du tree-shaking .

Y a-t-il un PR à ce sujet ?

@andrewmclagan Ce problème est toujours ouvert et a un PR connexe qui ne satisfera probablement pas tous (comme les utilisateurs de LernaJS)

Quel est le statut de ceci? Existe-t-il d'autres moyens de faire en sorte que le webpack de next transpile les fichiers importés de node_modules ?

@slorber je vais jeter un oeil au PR. Contribuez à notre cas d'utilisation.

Je suis confronté à un problème similaire. Essayer d'utiliser le package get-urls . Fonctionne avec dev mais quand je le compile. J'ai eu une erreur de uglify

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

Existe-t-il une solution de contournement pour cela s'il vous plaît?

Arunoda y travaillera quelque temps ici. Il l'a déjà fait dans #749

J'aimerais voir cette fonctionnalité implémentée. Comme @philcockfield l'a mentionné, il est courant de créer une bibliothèque de modules qui dépendent de la transpilation Next.js, et ce serait formidable de pouvoir partager des composants entre les projets.

Ce n'est pas seulement nécessaire pour secouer les arbres. Aussi pour les plugins babel comme styled-jsx . Donc, si vous avez un module (comme une bibliothèque) qui utilise un plugin babel, la meilleure solution est d'inclure le code source ES6 et de permettre à votre application de le transpiler à partir de node_modules. Bien sûr, next inclut déjà styled-jsx par défaut.

Voici ce que j'ai fait

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

J'ai essentiellement remplacé chaque exclude par une fonction personnalisée.
Je ne sais pas ce que je fais de mal, mais je ne peux tout simplement pas le faire fonctionner.
J'ai besoin que le contenu de node_modules/mycomponents soit également transpilé par Next.js

Cela ne fonctionne même pas si je remplace complètement toutes les exclusions avec un tableau vide

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

Aidez-moi, s'il vous plaît :)
Merci

Hé les gars ( @thealjey ) Je transpile des modules alimentés par jsnext:main depuis des mois maintenant.

Je n'utilise pas next.js mais j'espère que cela vous aidera.

@damianobarbati non, malheureusement ce n'est pas le cas
Configurer webpack directement pour transpiler tout ce qui n'est pas difficile, mais j'ai du mal à faire fonctionner cela dans le contexte de Next.js

salut a tous, quelqu'un a trouvé une solution ?

j'ai un module de nœud lié ES6 local que je dois importer dans mon projet mais je n'arrive pas à obtenir le vaudou webpack correctement !

Je suis sûr qu'il y a un meilleur moyen, mais nous faisons tout passer par babel on build :

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

Est-ce que c'est mort ? Je cherche un moyen de transpiler un module personnalisé et il semble que ce ne soit toujours pas possible.

@mattfelten c'est sur la feuille de route pour la v5 👍

Quelqu'un a-t-il un exemple de solution de contournement pour cela?

@timneutkens Existe-t-il un calendrier pour cela ? Appréciez que c'est souvent une question impossible, mais nous essayons de déterminer notre stack au travail pour le moment et c'est un assez gros bloqueur pour nous ! :)

Les suggestions de contournement sont également valables.

@thealjey se rend compte qu'il s'agit d'un ancien commentaire, mais votre solution n'a probablement pas fonctionné car il y a également un include spécifié qui devrait être remplacé.

Mise à jour : a examiné cette stratégie, mais ce n'est tout simplement pas raisonnable étant donné tous les différents chargeurs pour les différents répertoires de modules dans la configuration interne de next.js. Cela devra être de première classe.

@chrisui ma solution (temporaire) consistait à utiliser babel-plugin-module-resolver , configuré comme ceci - "plugins": [["module-resolver", {"root": ["./"]}]]
ce n'est en aucun cas une solution parfaite, mais, comme tout le reste a échoué, cela fonctionne pour l'instant
grâce à cela, je n'ai pas besoin d'écrire un tas de ../ à chaque importation
cela pourrait en fait être une meilleure solution pour certains, même si cela n'aide certainement pas à la réutilisation

@thealjey peux -tu donner un exemple ?
J'ai une configuration de projet où j'essaie cela en vain...
https://github.com/jamesgorrie/nappy

J'essaierais volontiers d'obtenir un PR car cela nous faciliterait la vie, mais il y a quelques questions comme : next.js devrait-il prendre en charge le transpilage de certains modules ou devrait-il dépendre du transpileur, mais le next.js suit plus strictement la résolution du module. Je ne sais pas à qui demander ou par où commencer ici en tant que nouveau à next.js .

c'est sur la feuille de route pour la v5 👍

@timneutkens est-ce que cela a été

me demande de savoir.

Il suffit de regarder où il a fusionné. cela a été fusionné il y a 8 jours. 5.0.0 est sorti il ​​y a 2 jours. de la branche canarienne où cela est fusionné dans...

Quelqu'un a-t-il un exemple sur la façon dont cela peut être mis en œuvre? Est-ce censé fonctionner comme ça, comme mentionné ci-dessus?

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

ou ça a l'air différent ?

Je suis confus. @timneutkens Le lien mentionné ci-dessus

EDIT : Peu importe, ceci est juste un PR pour mettre en évidence l'exemple.

C'est un exemple, vous pouvez utiliser l'exemple sans qu'il soit fusionné. transpileModules est quelque chose que nous aborderons plus tard.

En règle générale : lorsqu'un numéro est ouvert, il n'est pas publié.

@brianyingling J'ai transformé l'exemple en plugin pour une solution provisoire (v5 uniquement).
Cela fonctionne pour nous en ce moment, jusqu'à ce que la solution officielle plus robuste soit mise en place.

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

J'aimerais voir un exemple de cela pour un seul module dans la base de code de l'application.

Par exemple, j'ai un module que j'utilise à la fois côté serveur et côté client. Je n'ai pas réussi à faire fonctionner l'un des exemples ci-dessus, soit en factorisant le module dans son propre module séparé et en le yarn link en l'intégrant, soit en piratant les règles du pack Web.

Voici une simple reproduction : 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 dit que c'est parce que j'utilise async/await dans le module partagé. Je suppose que ma solution pourrait être de supprimer async/wait et de tout changer en rappels de style .then() .

OK, j'ai trouvé une solution qui fonctionne pour moi.

Tout d'abord, j'ai ajouté le paramètre config.resolve.symlinks = false à ma configuration next.config.js par https://github.com/zeit/next.js/issues/3018#issuecomment -380879576

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

Ensuite, j'ai mis ma bibliothèque partagée - un fichier .js qui utilise des exportations CommonJS et des mots-clés async / await - dans un sous-répertoire de l'application appelé 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": { ... }
}

Et enfin, j'ai ajouté un script postinstall pour tout lier ensemble lorsque quelqu'un fait un yarn install dans l'application principale :

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

Maintenant, mes tests Mocha passent côté serveur, mon serveur Koa personnalisé démarre correctement et il n'y a plus de Cannot assign to read only property 'exports' of object '#<Object>' fou dans mes pages NextJS.

J'ai eu ce même problème lors de la mise à niveau vers NextJs 5.1.0. Un ou deux des modules de nœuds suivants ne transpilaient pas les fonctions de flèches grasses et ne lançaient pas d'erreurs dans IE11. J'avais déjà configuré des polyfills individuels et j'ai finalement choisi de cibler ces fichiers de modules avec babel-polyfill dans mon next.config.js avec ceci :

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

J'espère que cela aide quelqu'un.

ESM fonctionne comme un charme.

Avec un serveur Next.js personnalisé dans index.js , je peux exécuter cette commande pour démarrer le serveur et esm démarre parfaitement, en résolvant les modules ES dans les packages de projet liés à Lerna.

node -r esm index.js

@curran cool, peut-il remplacer babel-node ?

@curran j'éviterais de faire ça en production

@blackbing je ne sais pas.

@thealjey Pourquoi ça ?

Si quelqu'un cherche une solution simple et rapide, voici ce que j'ai fait. J'ai créé un sous-répertoire, shared/ , avec tout code que nous souhaitons exécuter à la fois sur le backend via un script Node autonome et sur le client via NextJS. Il a son propre package.json et déclare son nom comme @myproject/shared .

Ensuite, dans le projet principal (parent), j'ai ajouté un script de post-installation à package.json comme ceci : cd shared && yarn -s unlink >/dev/null 2>&1 ; yarn -s link && yarn -s && yarn link @myproject/shared — puis exécutez yarn au moins une fois et changez vos importations en import { whatever } from '@myproject/shared/somefile'

De cette façon, le code partagé fonctionne sans aucune étape de transpilation folle, et vous n'avez pas à réexécuter yarn / npm chaque fois que vous effectuez une mise à jour puisque yarn link fait un lien symbolique.

Pour ceux qui utilisent TypeScript, @weco/next-plugin-transpile-modules ne devrait pas fonctionner. J'ai créé un fork pour gérer les withTypescript Next : https://github.com/KeitIG/next-plugin-transpile-modules

J'ai encore besoin de comprendre comment faire les choses correctement lorsque nous devons également avoir du code côté serveur dans TypeScript.

des nouvelles à ce sujet?

Et encore un autre par moi, dans l'essentiel suivant. Il gère TypeScript, ainsi que des packages spécifiques d'un @scope , plutôt que tous les packages. https://gist.github.com/trusktr/44400d0d016c506629b4f914799dc9cd

Je viens de créer un exemple de travail simple qui utilise esm et lerna

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

/cc @jdalton

Personnellement, cela fonctionne avec les next.config.js :

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

    return config
  }
}

Il contient tout en node_modules , dont j'avais besoin pour obtenir la compatibilité avec IE 11...

J'apprécierais également une solution pour cela, car j'ai du mal à ajouter des packages npm non transpilés à mon projet. J'ai dû les télécharger au vendeur/ pour l'instant :(
Vraiment énervant

@bel0v Je pense que vous devriez déjà pouvoir accomplir cela avec next-plugin-transpile-modules . Ce problème devrait probablement être clos. cc/ @timneutkens

J'aimerais quand même étudier des solutions alternatives.

Récemment, Jamie a écrit un fil de discussion très détaillé sur le problème de la compilation de node_modules : https://twitter.com/jamiebuilds/status/1080840492525350912

J'ai lu le fil de Jamie, bien que j'aimerais également partager le point de vue d'Henry Zhu et Babel sur cette situation et cette solution.
https://babeljs.io/blog/2018/06/26/on-consumer-and-publishing-es2015+-packages

(Je ne suis pas en désaccord avec Tim, j'ai juste pensé que je partagerais de nombreux avantages et inconvénients. Cela pourrait aider Tim à rechercher des solutions alternatives)

Oui, nous avons discuté de ce problème avec de nombreuses personnes au cours des six derniers mois, y compris Henry 😄

Nonobstant les préoccupations concernant le transpilation de node_modules, vouloir transpiler vos propres packages dans un monorepo est une exigence très courante, à laquelle ces préoccupations ne s'appliquent pas

@dcalhoun Je l'ai essayé mais malheureusement, j'obtiens toujours une erreur de jeton inattendue. Il y a un problème Next 7 ouvert sur ce plugin qui pourrait être lié

@bel0v

Vous devriez lire la FAQ ;) il existe une solution à ce problème : https://github.com/martpie/next-plugin-transpile-modules#i -have-trouble-making-it-work-with-nextjs-7

J'ai utilisé ce plugin sur plusieurs projets, et il fait bien le travail. Le problème Next 7 est bizarre, je ne sais pas si cela vient de Next ou de Babel, j'ai quand même ouvert un problème ici: https://github.com/zeit/next.js/issues/5393

@martpie ouais je crois que j'ai essayé ça .. de toute façon je vais faire un autre essai

@martpie, nous avons commencé à utiliser next7 avec un babel.config.js cohérent et des espaces de travail de fil, je pourrais voir si je peux configurer un exemple simple.

J'ai forké l'exemple de base ici
https://github.com/bel0v/learnnextjs-demo
dans celui-ci, j'ai installé une dépendance non transpilée (wired-elements), j'ai obtenu une erreur de construction Unhandled Rejection (SyntaxError): Unexpected token { et j'ai essayé de la corriger de la manière suggérée.
Je pense que j'ai peut-être besoin de quelques plugins babel supplémentaires pour que cela fonctionne.. 🤔

@ bel0v dans la FAQ à nouveau, il y a une explication sur les raisons pour lesquelles les configurations de Lerna ne fonctionnent pas (TL, DR; vous utilisez probablement est faux)

@martpie ah, j'ai compris ! Je ne savais pas que le package tiers avait été configuré avec Lerna. Merci

Il semble que https://twitter.com/jamiebuilds ait été suspendu, je ne peux donc plus lire le fil là-bas. #3018 Vous avez fermé en référence à ce problème, alors je me demande quelles sont les approches alternatives envisagées ?
Représentent-ils l'état de l'art / les meilleures pratiques de next.js pour ces cas d'utilisation atm ?
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

Donc, si vous travaillez, comme moi, sur un projet qui doit prendre en charge IE11, vous devez vraiment transpiler tout le code dans node_modules/ . Dans Next.js 7.x, j'utilisais la configuration suivante, qui fonctionnait très bien.

Malheureusement, il a cessé de fonctionner dans Next.js 8.x avec des erreurs indiquant que les modules n'ont pas réussi à importer d'autres modules car ils n'avaient pas d'exportation par défaut. J'ai ensuite proposé la configuration ci-dessous pour Next.js 8.x, qui ne transpile le code qu'en node_modules/ avec @babel/preset-env , et aucun autre plugin.

Ceci est combiné en définissant ma propriété browserlist dans le package.json :

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

Suivant 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
  },
}

Malheureusement, je n'ai pas encore compris comment utiliser @babel/plugin-transform-runtime avec cette configuration, donc il va probablement cracher pas mal d'aides dans le code 😞 j'espère que gzip s'en occupe 😆 😅


Je pense que ce serait génial si Next.js pouvait nous donner une option pour transpiler correctement node_modules/ pour travailler avec tout ce que vous avez browserlist . Il semble que tous les grands sites qui ont des utilisateurs d'entreprise en dépendent pour prendre en charge correctement les anciens navigateurs.

En tant que mainteneur de next-transpile-modules (basé sur le travail impressionnant de @jamesgorrie), je suis heureux d'aider toute personne confrontée à ce problème ici.

Je travaille sur des projets professionnels depuis plus d'un an avec ce plugin, et jusqu'à présent, il a bien fonctionné.

Le support natif de Next.js serait bien sûr génial et je serais heureux d'aider à intégrer cette fonctionnalité dans le package next . Je sais que Tim avait des idées qu'il voulait essayer, mais quand même.

À votre santé!

@martpie J'ai rapidement regardé votre projet, mais je n'ai pas trouvé de moyen rapide de transpiler _tous_ les modules, est-ce possible ? ☺️

De plus, je vois que vous choisissez options.defaultLoaders.babel et que vous l'utilisez comme chargeur babel. En faisant cela avec Next.js 8.x, j'ai eu le problème que certains modules ne parvenaient pas à être correctement reconnus en tant que module CJS après cela, puis que d'autres bibliothèques ne parvenaient pas à les importer, par exemple :

./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'.

C'est pourquoi je suis passé à la fourniture d'une configuration babel personnalisée pour node_modules/ , qui ne transpile le code qu'à l'aide de preset-env , et ignore les transformations spécifiques à Next.js. Que pensez-vous de cette approche?

Bravo

@LinusU Essayez peut-être transpileModules: ['(.*?)'] et dites-moi si cela fonctionne ?

Mais il se peut que cela ne fonctionne pas dans une future version majeure, alors soyez prudent.

Plus généralement, je ne recommande pas (lire "fortement déconseillé") de transpiler tout le dossier node_modules , cela prendra une éternité à compiler et les packages devraient fournir du code compatible ES3 (donc compatible IE11).

Ne transpilez que le module dont vous avez besoin ! (comme lodash-es , modules locaux etc...)

les packages doivent fournir un code compatible ES3 (donc compatible IE11).

Ce n'est pas la réalité que j'ai vue cependant, et je ne suis en fait pas d'accord. Les auteurs du module ne sauront jamais exactement quels navigateurs je cible, et s'ils envoient du code plus ancien, ils pénaliseront potentiellement les utilisateurs qui ciblent les navigateurs modernes.

il faudra une éternité pour compiler

C'est un peu lent au démarrage pour moi, mais après cela, il semble être mis en cache et lorsque je modifie une page spécifique, je vois des rechargements quasi instantanés.

Ne transpilez que le module dont vous avez besoin !

Cela nécessiterait que je sache exactement quels packages sont compatibles avec IE11 et lesquels ne le sont pas, ainsi que de maintenir ces informations à jour à chaque fois que des dépendances (même transitoires) changent. Je ne vois pas en quoi c'est réaliste

L'important est que les points d'entrée ESM fournis dans package.json module soient généralement ES5 avec des importations/exportations ES6 pour le secouage d'arbres. C'est donc le travail d'un bundler (Webpack) et non d'un transpiler (Babel), sauf indication contraire. De nombreux packages bien entretenus ont déjà des points d'entrée ESM, par exemple redux/es pour Redux qui a été mentionné par OP.

Si vous envisagez de le faire avec next.config.js : module.exports = { webpack: (config , alors config.module.rules a quelques éléments, il semble que vous deviez modifier l'une de ces règles ou en ajouter une ? :

  { 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: [] } } ]

Dans l'attente de la syntaxe plus simple suggérée.

Fonctionne bien pour moi

{
    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']
    }
},

J'ai rencontré ce problème en utilisant un dépôt mono Lerna et je me demandais quelle en était la cause. Étant donné que l'erreur provient de webpack, elle ne donne pas de bons détails, à part le fait qu'il manque un chargeur, ce qui n'est pas utile. Heureusement, j'ai trouvé ce problème github!

Je vais laisser ma solution ici pour tous ceux qui recherchent ce problème et utilisent également Lerna :

Créez un script de prépublication pour le package partagé qui transpile la source dans un répertoire dist et dites à Lerna de pointer vers le répertoire dist lors de la liaison :

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

Maintenant, lorsque vous lerna bootstrap il exécutera le script de prépublication et transpilera la source afin que Next puisse la consommer.

Si vous utilisez lerna vous pouvez créer des liens symboliques pour être transpilés à l'aide de next-transpile-modules . Comment utiliser ce package avec lerna est écrit au bas de la documentation.

Pour tous ceux qui recherchent le partage de code entre les applications NextJs, j'aimerais simplement signaler que la solution de @LinusU a fonctionné pour moi lorsque j'essayais de partager des composants et des utilitaires React entre plusieurs applications NextJs dans mon référentiel 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
        })
        }
    }
}

J'utilise la dernière version de NextJs au moment de cet article.

@ Lwdthe1 J'ai essayé votre code et j'ai d'abord eu cette erreur:

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

J'ai fait quelques ajustements et j'ai fini avec ça:

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

Mais le s'est heurté à une autre erreur:

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

qui semble avoir été affronté auparavant en #2850 et #883.

Il semble donc que la seule solution soit : https://github.com/martpie/next-transpile-modules#but -i-really-need-to-make-it-work-with-lerna

D'après ce que j'ai entendu, RFC sera bientôt présenté sur la façon dont Next.js prévoit de résoudre ce problème, mais si quelqu'un doit le résoudre maintenant, j'ai publié sur npm ma solution à partir de https://github.com/ zeit/next.js/pull/10098 que vous pouvez utiliser en mettant ce qui suit dans package.json :

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

et suivant à next.config.js :

  babelIncludeRegexes: [/turf/],

(dans mon cas, j'avais besoin que tous les fichiers turf soient précompilés avec babel)

Ce problème a-t-il progressé ?

J'utilise next.js 9.2.0, mais l'option babelIncludeRegexes ne fonctionne pas

Ce problème a-t-il progressé ?

next-transpile-modules vise à résoudre ce problème exactement, l'avez-vous essayé ?

Salut @martpie ,

J'ai déjà résolu mon problème d'édition de fichier .babelrc. je fais référence à ce problème

THX

@martpie J'utilise next-transpile-modules mais je suis toujours confronté à l'erreur ci-dessous pendant que j'essaie de créer l'application. J'utilise monorepo avec une base de code partagée. Essayer d'accéder à des composants partagés comme '@myapp/shared/components/componentname.js'. J'utilise nextjs 9.x et custom next.config.js .

Erreur
`
Échec de l'analyse du module : jeton inattendu (12:4)
Vous aurez peut-être besoin d'un chargeur approprié pour gérer ce type de fichier, actuellement aucun chargeur n'est configuré pour traiter ce fichier. Voir https://webpack.js.org/concepts#loaders
| const Spinner = accessoires => {
| const renderDefaultSpinner = (spinnerClass, { ... autres }) => (
>


| );
|

Une erreur de construction s'est produite
Erreur : > Échec de la construction en raison d'erreurs de pack Web
`

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

S'il vous plaît aider ce que je fais mal ici.

@ raghav1086 Pouvez-vous ouvrir un problème sur le repo ? ;) cela évitera le bruit pour les gens ici.

+1

J'ai un répertoire src/ pour mon projet et lib/ pour un framework de démarrage qui exporte des utilitaires/wrappers courants que je réutilise dans quelques applications nextjs différentes (mon point de départ)

lib n'est pas remarqué lorsque je démarre le serveur de développement. tous les composants de lib/ ne passent pas par le chargeur et donnent une erreur

J'ai utilisé une variante de la solution de @Lwdthe1 (https://github.com/zeit/next.js/issues/706#issuecomment-569041997) pour résoudre le problème src et lib dans mon commentaire ci-dessus. Fondamentalement la même chose, sauf que cela utilise config.resolve.modules au lieu de parcourir le tableau 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],
    });

Quelle est la solution de travail pour lerna, nextjs et babel ces jours-ci ?

J'essaie d'éviter de pré-transpiler mes bibliothèques avant l'importation, et je me suis heurté à un mur de briques avec chaque solution ici. Voici ce que je n'arrive pas à faire fonctionner :

  • next-transpile-modules .
  • réinitialiser les paramètres prédéfinis-env.
  • mettre à jour les règles next-babel-loader include et exclude pour réussir/échouer respectivement.

@mikestopcontinues next-transpile-modules travaillé pour moi avec TypeScript.

@calebmpeterson et @martpie (je te vois ! 👀). Je suis revenu à la prise et le problème semble être qu'il n'y a aucun moyen de référencer des sous-modules. Par exemple, le modèle '@mono/components' ne prendra pas en charge l'importation de '@mono/components/Div' ou autre. Et spécifier '@mono/components/Div' comme modèle ne fonctionne pas non plus... pas que je veuille le faire pour chaque composant partagé. J'ai également essayé d'effectuer une ingénierie inverse de la génération de regex pour créer des modèles de correspondance, et pendant que la regex de sortie fonctionne, quelque chose d'autre se passe sous le capot qui ne l'est pas.

Idéalement, je voudrais juste spécifier '@mono' pour s'occuper de tout, et laisser mon package.json être la seule source de vérité pour ce dont dépend chacune de mes applications. De même, je voudrais éviter de maintenir des fichiers d'index qui importent/exportent tout dans chacune de mes bibliothèques juste pour pouvoir accéder aux sous-modules.

Pour revenir en arrière, je pense que le problème actuel pourrait être entièrement résolu s'il y avait un moyen de passer rootMode: 'upward' à next-babel-loader , afin que babel puisse gérer la logique de transpilation. Cela ouvre peut-être d'autres problèmes liés à Next, mais la racine du problème semble être la manière atypique dont Next est enchevêtré dans webpack et babel. Il existe sûrement un moyen de séparer babel-loader de la logique supplémentaire de Next ?

Juste une mise à jour sur le front next-transpile-modules . J'avais mal diagnostiqué l'erreur. Aucune importation ne fonctionne avec cette méthode (index ou sous-module) si vous avez besoin d'une configuration .babelrc . Les paramètres personnalisés ne sont tout simplement pas appliqués au code requis. C'est encore un problème de rootMode: 'upward' .

@mikestopcontinues Vous devez utiliser babel.config.js (config globale) avec next-transpile-modules , et non .babelrc (config locale), c'est expliqué dans la FAQ ;)

@martpie Vous n'avez aucune idée à quel point je suis gêné. J'ai dû lire cette ligne une douzaine de fois au cours des dernières semaines et je n'ai jamais pris la peine de cliquer sur le numéro. Cela a totalement fonctionné. Merci!

next-transpile-modules a cassé React pour moi. Il indique maintenant que j'utilise des crochets non valides, alors que j'ai transpilé TROIS modules d'exemple

Quelqu'un pourrait-il réitérer quelle est la meilleure configuration pour que la transpilation fonctionne. Je ne comprends pas ce que je dois écrire dans babel.config.js

@masbaehr dans la plupart des cas, il suffit d'ajouter next-transpile-modules à votre configuration next.config

Le seul problème est que next-transpile-modules ne prend pas en charge Yarn 2 pnp.

Cette page vous a été utile?
0 / 5 - 0 notes