Next.js: Unterstützung für Transpile-Module in node_modules hinzufügen

Erstellt am 9. Jan. 2017  ·  103Kommentare  ·  Quelle: vercel/next.js

Jetzt versenden einige von uns NPM-Pakete (insbesondere Komponenten), die in ES2015 geschrieben wurden, ohne sie zu transpilieren.

Das ist eine ziemlich gute Sache, besonders wenn sie in einem Projekt wie Next.js oder CRA (das Transpiling macht) verwendet werden. Sie bieten Vorteile wie:

  • Kein Transpilieren vor dem Versand an NPM erforderlich
  • Profitieren Sie vom Tree-Shaking von Webpack 2

Aber wir können das jetzt nicht tun , wir ausschließen alles in node_modules von babel transpiling.

Hier also der Lösungsvorschlag.

Wir haben einen Eintrag in next.config.js , um Module einzuschließen, die durch babel gehen müssen. Sehen:

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

Hilfreichster Kommentar

Je mehr ich next.js ernsthaft nutze und eine reichhaltige Bibliothek von Modulen drumherum erstelle, desto wichtiger wird diese Funktion. Es wird zu einem echten PITA, das den Babel-Kompilierungsschritt in meinen internen Modulen repliziert.

🚀🤖

Alle 103 Kommentare

  • Warum ist dies mit der Erweiterung webpack() ?
  • transpileModules klingt besser
  • Werden wir Regexps akzeptieren?

Warum ist dies mit der webpack()-Erweiterung nicht möglich?

Ich hoffe du meinst die benutzerdefinierte Webpack-Konfiguration. Das ist machbar. Dieser sitzt aber in einem vorhandenen Loader. Das zu bekommen ist etwas schwieriger.

transpileModules klingt besser

Fantastisch. Ich werde aktualisieren.

Werden wir Regexps akzeptieren?
Ja. sicher.

Hey,

Während ich meine eigene Website starte, probiere ich neue Technologien wie Lerna/Next/Styled... aus und gebe gerne frühzeitig Feedback dazu.

Ich habe ein doppeltes Problem geöffnet

Mir ist auch aufgefallen, dass Babel, das ebenfalls auf Lerna basiert, jedes Modul transpiliert , bevor es veröffentlicht wird, aber es @arunoda vorschlägt und die Client-App die Transpilierung durchführen zu lassen.

Ich möchte eine einzelne Babel-Konfiguration für meinen Client haben und diese Konfiguration mit allen meinen entkoppelten Modulen teilen. Das ist wahrscheinlich nicht so einfach, wenn ich die Möglichkeit haben möchte, meine Module als Standalone außerhalb von Next Runner auszuführen

Mein aktuelles Testprojekt ist hier: https://github.com/slorber/playground/ Ich werde versuchen, es zu aktualisieren, sobald es einen Fork/PR gibt. @arunoda arbeitest du daran?

@slorber derzeit konzentrieren wir uns auf die Veröffentlichung von 2.0 und wir

Ich habe noch nicht damit begonnen, aber wir können dies kurz nach 2.0 tun.

Okay, ich mache eine Gabel. Ich laufe bereits gegen 2.0.0 Beta, weil ich keine kritische Website erstelle und ich glaube nicht, dass Webpack 1.13 das Feld jsnext:main/module auflöst .

Ich bin kein Bundler-Experte, aber ich denke, ich würde eher das Feld "module" von package.json verwenden, nein? "main" scheint für bereits transpilierten Code zu sein, soweit ich weiß. Aber da die Webpack-Konfiguration es ermöglicht, die Transpilation einzuschließen/auszuschließen, bin ich mir nicht sicher, ob dies relevant ist. Irgendeine Empfehlung, welches der 3 Felder ich lieber verwenden würde?

@slorber Ich denke, Webpack unterstützt nur main genau wie NPM. Das kannst du benutzen.
Wir können den Dateipfad in der Funktion exclude in unserem next.conf.js überprüfen

Hmm nach dem, was ich in der Praxis gegen Next 2.x gesehen habe, habe ich gesehen, dass das Modul funktioniert (aber später zur Laufzeit fehlschlägt, weil es nicht transpiliert wurde), während jsnext:main nicht funktionierte (soweit ich mich erinnere). Aber es soll unterstützt werden .

Wie auch immer, jsnext:main oder module scheint nicht die Lösung für dieses Problem zu sein, daher reicht es für firmeninterne Module wahrscheinlich aus, die Transpilation zu aktivieren

Die Community hat sich nicht auf einen Ansatz geeinigt, oder? Zum Beispiel konnte ich react-youtube das andere ohne Probleme verwenden. Ich gehe davon aus, dass eine große Anzahl von Modulen vor der Veröffentlichung transpiliert werden?

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

Ja, es ist sinnvoll, immer vor der Veröffentlichung zu transpilieren, da Sie nicht wissen, wer/wie das Modul konsumiert wird und Sie den Client nicht zwingen möchten, geeignete Babel-Einstellungen für Ihre Lib einzurichten. Das ist es, was Rollup vorschlägt : das Modul auf verschiedene Weise

Bei unternehmensinternen Paketen können die Transpilationseinstellungen jedoch über mehrere Projekte hinweg gleich sein (wie ein Babel-Preset) und es ist für mich sinnvoll, den Client-Bundler alle Unternehmensabhängigkeiten transpilieren zu lassen

Stimme sehr zu aufteilen und die Dinge so weit wie möglich isolieren.

Und @rauchg / @arunoda, die RegExp's unterstützen, wäre wirklich nett, also könnten Sie einen Eintrag haben, der alle firmeninternen Module

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

Schöner Vorschlag @philcockfield

Hey, vielleicht könnte es sich lohnen, ein paar Presets anzubieten. Es scheint mir, dass die meisten Tools (Lerna / npm-Link ...) auf Symlinks basieren, warum also nicht etwas so Einfaches wie:

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

Je mehr ich next.js ernsthaft nutze und eine reichhaltige Bibliothek von Modulen drumherum erstelle, desto wichtiger wird diese Funktion. Es wird zu einem echten PITA, das den Babel-Kompilierungsschritt in meinen internen Modulen repliziert.

🚀🤖

Daran arbeite ich heute :)

@philcockfield probiere das mal aus: https://github.com/zeit/next.js/pull/749

danke @arunoda

Wie in Ihrem PR kommentiert, ist die Funktion etwas eingeschränkt, wenn dies keine Symlinks unterstützt, da sie nicht mit npm-Link oder Lerna funktioniert, sondern nur für npm-Module, die nicht transpiliert sind (richtig? Ich sehe keine anderen?) Anwendungsfall, es sei denn, Sie übertragen Module innerhalb von /node_modules )

Warum keine Symlinks unterstützen? ist es schwieriger zu unterstützen?

Außerdem wollte ich Ihren Zweig in meiner App testen, bin mir aber nicht sicher, wie das am besten geht. Gibt es ein bekanntes Verfahren, mit dem wir einen Zweig einfach testen können und es für den Tester nicht zu schmerzhaft ist? Ich habe einiges ausprobiert wie:

  • npm install https://github.com/arunoda/next.js.git#add -706 : schlägt fehl, weil der nächste /bin-Ordner im Github-Repository leer ist
  • Git-Klon des Forks in /node_modules: nicht viel Erfolg (aber es könnte an meinen spezifischen Lerna-Einstellungen liegen)

Wie testet man derzeit eine Gabel am besten?

Wenn Sie dies mit next.config.js : module.exports = { webpack: (config , dann hat config.module.rules ein paar Dinge. Sie müssen eine dieser Regeln ändern oder hinzufügen? :

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

Ich freue mich auf die vorgeschlagene einfachere Syntax.

Entschuldigung für meine Unwissenheit, ich kann nicht sehen, was die Lösung dieses Problems ist? Wir würden gerne es6 in unsere Codebasis importieren, wir brauchen das Tree-Shaking .

Gibt es dazu eine PR?

@andrewmclagan Dieses Problem ist noch offen und hat eine verwandte PR , die wahrscheinlich nicht alle zufriedenstellen wird (wie LernaJS-Benutzer)

Wie ist der Stand davon? Gibt es andere Möglichkeiten, das Webpack von next so zu gestalten, dass aus node_modules importierte Dateien transpiliert werden?

@slorber ich

ich stehe vor einem ähnlichen Problem. Es wird versucht, das Paket get-urls . Funktioniert mit dev aber wenn ich es kompiliere. Ich habe einen Fehler von uglify erhalten

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

Gibt es hierfür bitte einen Workaround?

Arunoda wird hier irgendwann daran arbeiten. Hat er schon in #749 gemacht

Ich würde diese Funktion gerne implementiert sehen. Wie @philcockfield erwähnte, ist es ein übliches Szenario, eine Bibliothek von Modulen aufzubauen, die von der Next.js-Transpilation abhängig sind, und es wäre großartig, Komponenten zwischen Projekten teilen zu können.

Dies wird nicht nur beim Baumrütteln benötigt. Auch für Babel-Plugins wie styled-jsx . Wenn Sie also ein Modul (wie eine Bibliothek) haben, das ein Babel-Plugin verwendet, besteht die beste Lösung darin, den ES6-Quellcode einzubinden und Ihrer App zu erlauben, ihn aus node_modules zu transpilieren. Natürlich enthält next standardmäßig bereits styled-jsx .

Folgendes habe ich getan

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

Ich habe im Grunde jedes exclude durch eine benutzerdefinierte Funktion ersetzt.
Ich weiß nicht, was ich falsch mache, aber ich kann es einfach nicht zum Laufen bringen.
Ich muss den Inhalt von node_modules/mycomponents auch von Next.js transpilieren

Es funktioniert nicht einmal, wenn ich alle Ausschlüsse mit einem leeren Array vollständig überschreibe

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

Bitte hilf mir :)
Vielen Dank

Hey Leute ( @thealjey ) Ich jsnext:main betriebene Module.

Ich benutze nicht next.js aber ich hoffe, es hilft.

@damianobarbati nein, leider nicht
Webpack direkt zu konfigurieren, um alles zu transpilieren, ist nicht schwierig, aber ich habe Mühe, dies im Kontext von Next.js zum Laufen zu bringen

Hallo zusammen, hat jemand eine Lösung gefunden?

Ich habe ein lokales ES6-Linked-Node-Modul, das ich in mein Projekt importieren muss, aber ich kann das Webpack-Voodoo nicht richtig hinbekommen!

Ich bin sicher, es gibt einen besseren Weg, aber wir führen alles durch babel beim Build:

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

Ist das gestorben? Ich suche nach einer Möglichkeit, ein benutzerdefiniertes Modul zu transpilieren, und es scheint, als wäre dies immer noch nicht möglich.

@mattfelten es steht auf der Roadmap für v5

Hat jemand ein Beispiel für einen Workaround dafür?

@timneutkens Gibt es dafür eine Zeitleiste? Schätzen Sie, dass dies oft eine unmögliche Frage ist, aber wir versuchen, unseren Stack bei der Arbeit zu bestimmen, und dies ist ein ziemlich großer Blocker für uns! :)

Vorschläge zur Problemumgehung sind ebenfalls gültig.

@thealjey ist sich include angegeben ist, das überschrieben werden müsste.

Update: Diese Strategie wurde geprüft, aber angesichts all der verschiedenen Loader für verschiedene Modulverzeichnisse in der internen Konfiguration von next.js ist sie einfach nicht vernünftig. Das muss erstklassig sein.

@chrisui meine (vorläufige) Lösung bestand darin, babel-plugin-module-resolver zu verwenden , konfiguriert wie folgt - "plugins": [["module-resolver", {"root": ["./"]}]]
es ist keineswegs eine perfekte lösung, aber da alles andere fehlgeschlagen ist, funktioniert es vorerst
dadurch muss ich nicht bei jedem Import einen Haufen ../ schreiben
Dies könnte für einige tatsächlich eine bessere Lösung sein, obwohl es bei der Wiederverwendbarkeit sicherlich nicht hilft

@thealjey könntest du ein Beispiel geben?
Ich habe ein Projekt-Setup, bei dem ich dies vergeblich versuche ...
https://github.com/jamesgorrie/nappy

Ich würde gerne versuchen, eine PR zu bekommen, da dies unser Leben so viel einfacher machen würde, aber es gibt ein paar Fragen wie: Sollte next.js das Transpilieren bestimmter Module unterstützen oder sollte dies dem Transpiler überlassen werden, aber die next.js folgt strenger der Modulauflösung. Ich bin mir nicht sicher, wen Sie fragen oder wo Sie hier als Neuling bei next.js anfangen sollen.

es ist auf der Roadmap für v5

@timneutkens hat es das in v5 geschafft?

frage mich zu wissen.

Schauen Sie sich nur an, wo es zusammengeführt wurde. Dies wurde vor 8 Tagen zusammengeführt. 5.0.0 wurde vor 2 Tagen veröffentlicht. von der kanarischen Filiale, wo diese in...

Hat jemand ein Beispiel, wie das umgesetzt werden kann? Soll das wie oben beschrieben so funktionieren?

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

oder sieht es anders aus?

Ich bin verwirrt. @timneutkens Der oben genannte Link führt zu einer noch offenen PR. Wurde dies noch NICHT in v5 zusammengeführt?

EDIT: Egal, dies ist nur eine PR, um das Beispiel hervorzuheben.

Es ist ein Beispiel, Sie können das Beispiel verwenden, ohne dass es zusammengeführt wird. transpileModules ist etwas, das wir später in Angriff nehmen werden.

Als Faustregel gilt: Wenn ein Issue geöffnet ist, wird es nicht freigegeben.

@brianyingling Ich habe das Beispiel in ein Plugin für eine Zwischenlösung umgewandelt (nur v5).
Im Moment funktioniert es für uns, bis die robustere, offizielle Lösung eingeführt ist.

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

Ich würde gerne ein Beispiel dafür für ein einzelnes Modul in der Anwendungscodebasis sehen.

Zum Beispiel habe ich ein Modul, das ich sowohl server- als auch clientseitig verwende. Ich konnte keines der obigen Beispiele zum Laufen bringen, entweder indem ich das Modul in ein eigenes separates Modul einbezog und es yarn link ing, oder indem ich die Webpack-Regeln hackte.

Hier ist ein einfaches Repro: 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 sagt mir, dass dies daran liegt, dass ich async/await im freigegebenen Modul verwende. Ich denke, meine Lösung könnte darin bestehen, async/await zu entfernen und alles in .then() -Rückrufe zu ändern.

OK, ich habe eine Lösung gefunden, die für mich funktioniert.

Zuerst habe ich die Einstellung config.resolve.symlinks = false zu meiner next.config.js Konfiguration pro https://github.com/zeit/next.js/issues/3018#issuecomment -380879576 hinzugefügt

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

Dann lege ich meine gemeinsame Bibliothek – eine .js Datei, die CommonJS-Exporte und async / await -Schlüsselwörter verwendet – in ein Unterverzeichnis der Anwendung namens 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": { ... }
}

Und schließlich habe ich ein postinstall Skript hinzugefügt, um alles miteinander zu verknüpfen, wenn jemand ein yarn install in der Hauptanwendung macht:

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

Jetzt laufen meine Mocha-Tests auf der Serverseite, mein benutzerdefinierter Koa-Server startet gut und es gibt keine verrückten Cannot assign to read only property 'exports' of object '#<Object>' auf meinen NextJS-Seiten.

Ich hatte das gleiche Problem beim Upgrade auf NextJs 5.1.0. Ein oder zwei der Knotenmodule im nächsten transpilierten keine Fettpfeilfunktionen und warfen Fehler in IE11. Ich hatte zuvor einzelne Polyfills eingerichtet und am Ende entschied ich mich, diese Moduldateien mit babel-polyfill in meinem next.config.js mit diesem Ziel zu erreichen:

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

Hoffe das hilft jemandem.

ESM funktioniert wie ein Zauber.

Mit einem benutzerdefinierten Next.js-Server in index.js kann ich diesen Befehl ausführen, um den Server zu starten, und esm startet perfekt und löst ES-Module in Lerna-symlinked Projektpaketen auf.

node -r esm index.js

@curran cool, kann es babel-node ersetzen?

@curran Das würde ich in der Produktion vermeiden

@blackbing ich weiß es nicht.

@thealjey Warum ist das so?

Falls jemand nach einer schnellen und einfachen Lösung sucht, habe ich Folgendes getan. Ich habe ein Unterverzeichnis, shared/ , mit jedem Code erstellt, den wir sowohl auf dem Backend über ein eigenständiges Node-Skript als auch auf dem Client über NextJS ausführen möchten. Es hat sein eigenes package.json und deklariert seinen Namen als @myproject/shared .

Dann habe ich im Haupt-(übergeordneten) Projekt ein Postinstall-Skript wie folgt zu package.json hinzugefügt: cd shared && yarn -s unlink >/dev/null 2>&1 ; yarn -s link && yarn -s && yarn link @myproject/shared — dann führe yarn mindestens einmal aus und ändere deine Importe in import { whatever } from '@myproject/shared/somefile'

Auf diese Weise funktioniert der freigegebene Code ohne verrückte Transpilationsschritte und Sie müssen yarn / npm jedes Mal erneut ausführen, wenn Sie ein Update vornehmen, da yarn link ein Symlink.

Für diejenigen, die TypeScript verwenden, sollte @weco/next-plugin-transpile-modules nicht funktionieren. Ich habe einen Fork erstellt, um Nexts withTypescript : https://github.com/KeitIG/next-plugin-transpile-modules

Ich muss jedoch noch herausfinden, wie man die Dinge richtig macht, wenn wir auch serverseitigen Code in TypeScript benötigen.

Gibt es darüber irgendwelche Neuigkeiten?

Und noch eins von mir, im folgenden Kern. Es verarbeitet TypeScript und auch bestimmte Pakete eines @scope , und nicht alle Pakete. https://gist.github.com/trusktr/44400d0d016c506629b4f914799dc9cd

Ich habe gerade ein einfaches Arbeitsbeispiel zusammengestellt, das esm und lerna

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

/cc @jdalton

Ich persönlich habe das mit den folgenden next.config.js :

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

    return config
  }
}

Es babelt alles in node_modules , was ich brauchte, um IE 11-Kompatibilität zu erreichen...

Ich würde mich auch über eine Lösung dafür freuen, da ich damit zu kämpfen habe, meinem Projekt nicht transpilierte npm-Pakete hinzuzufügen. Musste sie vorerst auf Vendor/ herunterladen :(
Wirklich nervig

@bel0v Ich glaube, Sie sollten dies bereits mit next-plugin-transpile-modules . Dieses Problem sollte wahrscheinlich geschlossen werden. cc/ @timneutkens

Ich würde trotzdem gerne nach alternativen Lösungen suchen.

Kürzlich hat Jamie einen sehr ausführlichen Thread zum Thema Kompilieren von node_modules geschrieben: https://twitter.com/jamiebuilds/status/1080840492525350912

Ich habe den Thread von Jamie gelesen, möchte aber auch Henry Zhu und Babels Meinung zu dieser Situation und Lösung teilen.
https://babeljs.io/blog/2018/06/26/on-consuming-and-publishing-es2015+-packages

(Ich bin nicht anderer Meinung mit Tim, dachte nur, ich würde sagen, viele Vor- und Nachteile. Könnte Tim bei der Untersuchung alternativer Lösungen helfen)

Ja, wir haben im letzten halben Jahr mit vielen Leuten über dieses Thema gesprochen, darunter auch Henry 😄

Ungeachtet der Bedenken hinsichtlich des Transpilierens von node_modules ist der Wunsch, eigene Pakete in einem Monorepo zu transpilieren, eine sehr häufige Anforderung, auf die diese Bedenken nicht zutreffen

@dcalhoun Ich habe es versucht, aber leider erhalte ich immer noch einen unerwarteten Token-Fehler. Es gibt ein offenes Next 7-Problem bei diesem Plugin, das möglicherweise damit zusammenhängt

@bel0v

Du solltest die FAQ lesen ;) für dieses Problem gibt es eine Lösung: https://github.com/martpie/next-plugin-transpile-modules#i -have-trouble-making-it-work-with-nextjs-7

Ich habe dieses Plugin in mehreren Projekten verwendet und es erledigt die Arbeit gut. Das Next 7 Issue ist seltsam, ich bin mir nicht sicher, ob das von Next oder Babel kommt, ich habe trotzdem ein Issue hier eröffnet: https://github.com/zeit/next.js/issues/5393

@martpie ja, ich glaube, das habe ich versucht.. ich werde es auf jeden Fall noch einmal versuchen

@martpie wir haben begonnen, next7 mit einer konsistenten babel.config.js und Garn-Arbeitsbereichen zu verwenden, ich könnte sehen, ob ich ein einfaches Beispiel einrichten kann.

Ich habe hier ein einfaches Beispiel gegabelt
https://github.com/bel0v/learnnextjs-demo
darin installierte ich eine nicht transpilierte Abhängigkeit (wired-elements), bekam einen Build-Fehler Unhandled Rejection (SyntaxError): Unexpected token { und versuchte, den vorgeschlagenen Weg zu beheben.
Ich denke, vielleicht brauche ich ein paar zusätzliche Babel-Plugins, damit es funktioniert.. 🤔

@bel0v in den FAQ gibt es erneut eine Erklärung, warum Lerna-Setups nicht funktionieren (TL, DR; Sie verwenden wahrscheinlich falsch)

@martpie ah, verstanden! Wusste nicht, dass das Drittanbieterpaket mit Lerna eingerichtet wurde. Vielen Dank

Anscheinend wurde https://twitter.com/jamiebuilds gesperrt, daher kann der Thread dort nicht mehr gelesen werden. #3018 Wurde in Bezug auf dieses Problem geschlossen, also frage ich mich, welche alternativen Ansätze in Betracht gezogen werden?
Stellen diese den Stand der Technik / Best Practices von next.js für diese Anwendungsfälle atm dar?
https://github.com/curran/nextjs-esm-beispiel
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

Wenn Sie also wie ich an einem Projekt arbeiten, das IE11 unterstützen muss, müssen Sie wirklich den gesamten Code in node_modules/ transpilieren. In Next.js 7.x habe ich das folgende Setup verwendet, das großartig funktioniert hat.

Leider funktionierte es in Next.js 8.x nicht mehr mit Fehlern, dass Module andere Module nicht importieren konnten, weil sie keinen Standardexport hatten. Ich habe dann die folgende Konfiguration für Next.js 8.x entwickelt, die nur den Code in node_modules/ mit @babel/preset-env transpiliert und keine anderen Plugins.

Dies wird kombiniert, indem ich meine browserlist Eigenschaft in der package.json -Eigenschaft

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

Nächste 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
  },
}

Leider habe ich noch nicht herausgefunden, wie man @babel/plugin-transform-runtime mit diesem Setup verwendet, daher wird es wahrscheinlich einige Helfer im Code ausspucken 😞 hoffentlich kümmert sich gzip darum 😆 😅


Ich denke, es wäre großartig, wenn Next.js uns eine Option geben könnte, um node_modules/ korrekt zu transpilieren, um mit allen browserlist Sie haben. Es scheint, als ob alle großen Websites mit Unternehmensbenutzern davon abhängig sind, um ältere Browser ordnungsgemäß zu unterstützen.

Als Betreuer von next-transpile-modules (basierend auf der großartigen Arbeit von @jamesgorrie) helfe ich gerne jedem, der hier mit diesem Problem konfrontiert ist.

Ich arbeite seit mehr als einem Jahr an professionellen Projekten mit diesem Plugin und bisher hat es gut gespielt.

Nativer Support von Next.js wäre natürlich super und ich helfe gerne bei der Integration dieses Features in das next Paket. Ich weiß, dass Tim einige Ideen hatte, die er ausprobieren wollte, aber trotzdem.

Danke schön!

@martpie Ich

Außerdem sehe ich, dass Sie options.defaultLoaders.babel auswählen und das als Babel-Loader verwenden. Bei Next.js 8.x hatte ich das Problem, dass einige Module danach nicht richtig als CJS-Modul erkannt wurden und andere Libs sie nicht importieren konnten, zB:

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

Aus diesem Grund habe ich eine benutzerdefinierte Babel-Konfiguration für node_modules/ bereitgestellt, die den Code nur mit preset-env transpiliert und die Next.js-spezifischen Transformationen überspringt. Was halten Sie von diesem Ansatz?

Prost 🍻

@LinusU Vielleicht versuchen Sie es mit transpileModules: ['(.*?)'] und sagen Sie mir, ob es funktioniert?

Aber es kann sein, dass es in einer zukünftigen Hauptversion nicht funktioniert, also seien Sie vorsichtig.

Im Allgemeinen empfehle ich nicht (lesen Sie "sehr entmutigt"), den gesamten node_modules Ordner zu transpilieren, das Kompilieren dauert ewig und Pakete sollten ES3-kompatiblen Code enthalten (also IE11-kompatibel).

Transpilieren Sie nur das Modul, das Sie benötigen! (wie lodash-es , lokale Module etc...)

Pakete sollten ES3-kompatiblen Code bereitstellen (also IE11-kompatibel).

Dies ist jedoch nicht die Realität, die ich gesehen habe, und ich stimme tatsächlich nicht zu. Die Modulautoren werden nie genau wissen, welche Browser ich anvisiere, und wenn sie älteren Code ausliefern, werden sie potenziell Benutzer bestrafen, die auf moderne Browser abzielen.

das kompilieren dauert ewig

Es ist beim Start etwas langsam für mich, aber danach scheint es zwischengespeichert zu werden und wenn ich Änderungen an einer bestimmten Seite vornehme, sehe ich fast sofortige Neuladevorgänge.

Transpilieren Sie nur das Modul, das Sie benötigen!

Dazu müsste ich genau wissen, welche Pakete mit IE11 kompatibel sind und welche nicht, und diese Informationen immer auf dem neuesten Stand halten, wenn sich Abhängigkeiten (auch vorübergehende Abhängigkeiten) ändern. Ich sehe nicht, wie das realistisch ist

Wichtig ist, dass ESM-Einstiegspunkte, die in package.json module bereitgestellt werden, normalerweise ES5 mit ES6-Importen/Exporten für Tree Shaking sind. Dies ist also die Aufgabe eines Bundlers (Webpack) und nicht eines Transpilers (Babel), sofern nicht anders angegeben. Viele gut gepflegte Pakete haben bereits ESM-Einstiegspunkte, zB redux/es für Redux, das von OP erwähnt wurde.

Wenn Sie dies mit next.config.js : module.exports = { webpack: (config , dann hat config.module.rules ein paar Dinge. Sie müssen eine dieser Regeln ändern oder hinzufügen? :

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

Ich freue mich auf die vorgeschlagene einfachere Syntax.

Funktioniert bei mir gut

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

Ich stieß auf dieses Problem mit einem Lerna-Mono-Repo und kratzte mich am Kopf, was die Ursache war. Da der Fehler von Webpack kommt, gibt es keine guten Details, abgesehen davon, dass ein Loader fehlt, was nicht hilfreich ist. Zum Glück habe ich dieses Github-Problem gefunden!

Ich werde meine Lösung hier für alle anderen lassen, die nach diesem Problem suchen und auch Lerna verwenden:

Erstellen Sie ein Prepublish-Skript für das freigegebene Paket, das die Quelle in ein Verzeichnis dist transpiliert, und weisen Sie Lerna an, beim Verknüpfen auf das Verzeichnis dist zu verweisen:

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

Wenn Sie jetzt lerna bootstrap ausführen, wird das Prepublish-Skript ausgeführt und die Quelle transpiliert, damit Next sie verwenden kann.

Wenn Sie lerna , können Sie Symlinks erstellen, um mit next-transpile-modules transpiliert zu werden . Wie Sie dieses Paket mit lerna steht am Ende der Dokumentation.

Für alle, die nach dem Teilen von Code für NextJs-Apps suchen, möchte ich nur berichten, dass die Lösung von @LinusU für mich funktioniert hat, als ich versucht habe, React-Komponenten und -Utils zwischen mehreren NextJs-Apps in meinem Mono-Repo zu teilen:

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

Ich verwende die neueste Version von NextJs zum Zeitpunkt dieses Beitrags.

@Lwdthe1 Ich habe Ihren Code ausprobiert und zunächst diesen Fehler erhalten:

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

Habe etwas nachgebessert und bin dabei auf folgendes gekommen:

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

Aber es ist ein anderer Fehler aufgetreten:

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

die anscheinend schon einmal in #2850 und #883 konfrontiert wurde.

Es scheint also die einzige Lösung zu sein: https://github.com/martpie/next-transpile-modules#but -i-really-need-to-make-it-work-with-lerna

Nach allem, was ich gehört habe, wird RFC bald vorgestellt, wie Next.js dieses Problem lösen will, aber wenn jemand es jetzt beheben muss, habe ich auf npm meine Lösung von https://github.com/ veröffentlicht. zeit/next.js/pull/10098, die Sie verwenden können, indem Sie Folgendes in package.json einfügen:

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

und folgendes zu next.config.js:

  babelIncludeRegexes: [/turf/],

(in meinem Fall musste ich alle Rasendateien mit Babel vorkompilieren)

Hat dieses Problem Fortschritte?

Ich verwende next.js 9.2.0, aber die Option babelIncludeRegexes funktioniert nicht

Hat dieses Problem Fortschritte?

next-transpile-modules zielt darauf ab, dieses Problem genau zu lösen, hast du es versucht?

Hallo @martpie ,

Lösen Sie bereits mein Problem mit der Bearbeitung der .babelrc-Datei. Ich verweise auf dieses Problem

Danke

@martpie Ich verwende next-transpile-modules aber trotzdem wird der folgende Fehler angezeigt , während ich versuche, die Anwendung zu erstellen. Ich verwende Monorepo mit gemeinsamer Codebasis. Es wird versucht, von freigegebenen Komponenten wie "@myapp/shared/components/componentname.js" auf Komponenten zuzugreifen. Ich verwende nextjs 9.x und benutzerdefinierte next.config.js .

Fehler
`
Modulparsen fehlgeschlagen: Unerwartetes Token (12:4)
Möglicherweise benötigen Sie einen geeigneten Loader, um diesen Dateityp zu verarbeiten. Derzeit sind keine Loader für die Verarbeitung dieser Datei konfiguriert. Siehe https://webpack.js.org/concepts#loaders
| const Spinner = Requisiten => {
| const renderDefaultSpinner = (spinnerClass, { ...others }) => (
>


| );
|

Build-Fehler aufgetreten
Fehler: > Build aufgrund von Webpack-Fehlern fehlgeschlagen
`

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

Bitte helft mir was ich hier falsch mache.

@raghav1086 Können Sie ein Problem im Repo öffnen? ;) Es wird Lärm für die Leute hier draußen vermeiden.

+1

Ich habe ein src/ Verzeichnis für mein Projekt und lib/ für ein Starter-Framework, das einige gängige Utils/Wrapper exportiert, die ich in einigen verschiedenen nextjs-Apps wiederverwende (mein Ausgangspunkt)

lib wird nicht bemerkt, wenn ich den Dev-Server starte. Alle Komponenten von lib/ durchlaufen den Loader nicht und geben einen Fehler aus

Ich habe eine Variante der Lösung von @Lwdthe1 (https://github.com/zeit/next.js/issues/706#issuecomment-569041997) verwendet, um das src- und lib-Problem in meinem obigen Kommentar zu beheben. Im Grunde dasselbe, außer dass config.resolve.modules anstatt das Array aliasPathsToResolve durchlaufen.

  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],
    });

Was ist heutzutage die funktionierende Lösung für lerna, nextjs und babel?

Ich versuche zu vermeiden, meine Bibliotheken vor dem Importieren vorab zu transpilieren, und bin hier mit jeder Lösung gegen eine Mauer gestoßen. Folgendes kann ich nicht zum Laufen bringen:

  • next-transpile-modules .
  • Zurücksetzen der Preset-Env-Einstellungen.
  • Aktualisieren der Regeln next-babel-loader include und exclude auf bestanden/nicht bestanden.

@mikestopcontinues next-transpile-modules für mich mit TypeScript sofort funktioniert.

@calebmpeterson und @martpie (Ich sehe dich! 👀). Ich ging zurück zum Stecker, und das Problem scheint zu sein, dass es keine Möglichkeit gibt, auf Submodule zu verweisen. Zum Beispiel unterstützt das Muster '@mono/components' den Import von '@mono/components/Div' oder was auch immer nicht. Und die Angabe von '@mono/components/Div' als Muster funktioniert auch nicht ... nicht, dass ich das für jede gemeinsam genutzte Komponente tun möchte. Ich habe auch versucht, die Regex-Generierung rückzuentwickeln, um Übereinstimmungsmuster zu erstellen, und während die Ausgabe von Regex funktioniert, passiert etwas anderes unter der Haube, das nicht funktioniert.

Im Idealfall würde ich einfach '@mono' angeben, um sich um alles zu kümmern, und meine package.json als einzige Quelle der Wahrheit für das, wovon jede meiner Apps abhängt, belassen. Ebenso möchte ich es vermeiden, Indexdateien zu verwalten, die alles in jede einzelne meiner Libs importieren/exportieren, nur um auf Untermodule zugreifen zu können.

Um zurück zu kehren, ich glaube, das aktuelle Problem könnte vollständig gelöst werden, wenn es eine Möglichkeit gäbe, rootMode: 'upward' durch next-babel-loader , damit Babel die Transpilierungslogik handhaben könnte. Vielleicht eröffnet dies andere Next-bezogene Probleme, aber die Wurzel des Problems scheint die untypische Art und Weise zu sein, wie Next in Webpack und Babel verwickelt ist. Sicherlich gibt es eine Möglichkeit, babel-loader von der zusätzlichen Logik von Next zu trennen?

Nur ein Update zur next-transpile-modules Front. Ich hatte den Fehler falsch diagnostiziert. Mit dieser Methode (Index oder Submodul) funktioniert kein Import, wenn Sie eine benutzerdefinierte .babelrc Konfiguration benötigen. Die benutzerdefinierten Einstellungen werden einfach nicht auf den erforderlichen Code angewendet. Dies ist wieder ein rootMode: 'upward' Problem.

@mikestopcontinues Du musst babel.config.js (globale Konfiguration) mit next-transpile-modules und nicht .babelrc (lokale Konfiguration), es wird in der FAQ erklärt ;)

@martpie Du hast keine Ahnung, wie peinlich ich bin. Ich musste diese Zeile in den letzten Wochen ein Dutzend Mal gelesen haben und habe mich nie die Mühe gemacht, mich bis zum Thema durchzuklicken. Das hat total funktioniert. Vielen Dank!

next-transpile-modules hat React für mich kaputt gemacht. Es wirft jetzt aus, dass ich ungültige Hooks verwende, während ich DREI Beispielmodule transpiliert habe

Könnte jemand wiederholen, was die beste Konfiguration ist, um die Transpilation zum Laufen zu bringen. Ich verstehe nicht, was ich in babel.config.js schreiben muss

@masbaehr fügt in den meisten Fällen einfach next-transpile-modules zu Ihrem next.config-Setup hinzu

Das einzige Problem ist, dass next-transpile-modules Yarn 2 pnp nicht unterstützt.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

sospedra picture sospedra  ·  3Kommentare

YarivGilad picture YarivGilad  ·  3Kommentare

knipferrc picture knipferrc  ·  3Kommentare

lixiaoyan picture lixiaoyan  ·  3Kommentare

timneutkens picture timneutkens  ·  3Kommentare