Next.js: Funktionsanforderung: Basepath-Unterstützung

Erstellt am 21. Aug. 2018  ·  73Kommentare  ·  Quelle: vercel/next.js

Featureanfrage

Bezieht sich Ihre Funktionsanforderung auf ein Problem? Bitte beschreiben.

Multi Zones ist eine großartige Funktion, mit der mehrere next.js-Apps in derselben Domain ausgeführt werden können. Es ist jedoch nicht möglich, einen Basispfad zu definieren, der von allen Teilen von next.js akzeptiert wird. Da wir derzeit keine Namespace-Apps verwenden können, ist es nicht möglich, für Seiten in verschiedenen Apps dieselben Namen zu verwenden.

Beschreiben Sie die gewünschte Lösung

Ich möchte in der Lage sein, ein basepath in der Datei next.config.js zu konfigurieren. Dank dieser Konfiguration kennen alle Teile von next.js (Router, Link, statische Assets usw.) den Basispfad und generieren automatisch die richtigen Pfade und stimmen diese ab.

Beschreiben Sie Alternativen, die Sie in Betracht gezogen haben

Eine Alternative besteht darin, alle gewünschten Seiten in einem Ordner zu verschachteln, der dem Basispfad entspricht. Dies löst nur ein kleines Problem mit dem Routing und ist ziemlich hässlich, da die meisten meiner Basispfade keine einstufigen Pfade sind.
Die zweite Alternative besteht darin, einen Proxy so zu konfigurieren, dass der Basispfad automatisch entfernt wird, bevor die Anforderung in einer next.js-App eingeht, und eine benutzerdefinierte Link-Komponente zu implementieren, die allen Links automatisch den Basispfad hinzufügt. Ich möchte nur keine benutzerdefinierte Gabel von next.js beibehalten. Das macht meiner Meinung nach keinen Sinn.

Zusätzlicher Kontext

Mit der assetPrefix -Lösung können wir für jede App ein anderes Präfix definieren. Aber so fair wie ich weiß, funktioniert es nur mit verschiedenen Hosts.

Beispiel für With-Zones

module.exports = {
  assetPrefix: NOW_URL ? `https://${alias}` : 'http://localhost:4000'
}

Wenn ich einen Basispfad hinzufüge, schlägt alles fehl

module.exports = {
  assetPrefix: NOW_URL ? `https://${alias}/account` : 'http://localhost:4000/account'
}

screen shot 2018-08-21 at 10 47 08

Meiner Meinung nach sollten wir es in 2 Variablen aufteilen:

module.exports = {
  assetPrefix: NOW_URL ? `https://${alias}` : 'http://localhost:4000',
  basepath: '/account'
}

Verwandte Themen

story needs investigation

Hilfreichster Kommentar

Jedes Update dazu ... letztes Jahr um diese Zeit bin ich auf dieses Problem gestoßen. Jetzt, ein Jahr später, arbeite ich an einer neuen App und muss die gleichen Problemumgehungen wie im letzten Jahr durchführen ... irgendwie alarmierend für eine "produktionsbereite" Reaktion fw. Basispfade sollten ein Vanille-Merkmal sein.

Ich bin mir nicht sicher, was Sie erwarten, wenn Sie dies veröffentlichen.

Next.js wird von meinem Team (5 Personen) in Vollzeit bearbeitet, und wir arbeiten gleichzeitig an vielen Funktionen. Im vergangenen Jahr haben wir daran gearbeitet:

Effektiv machen Next.js-Anwendungen (neu und vorhanden) erheblich kleiner, schneller und skalierbarer.

Wenn Sie Ihre "Gegenstimme" für eine Funktion äußern möchten, können Sie. Verwenden Sie die Funktion 👍 für den ersten Thread.

Ich bin definitiv der Meinung, dass basePath eine integrierte Funktion sein sollte. Es ist bereits auf der Roadmap und ich habe sogar eine erste PR geschrieben, die Sie durch Zurücklesen des Threads hätten sehen können.

Hier ist die PR: https://github.com/zeit/next.js/pull/9872

Wenden Sie sich an [email protected], wenn Sie einen finanziellen Beitrag zur Umsetzung dieser Funktion leisten möchten.

Alle 73 Kommentare

cc @jxnblk

cc @alexindigo @DullReferenceException

Würde mich über Ihr Feedback freuen 👍

Nachdem ich mit dem Code gespielt hatte, wurde mir klar, dass es viel einfacher sein würde, assetPrefix in mehrere Teile aufzuteilen:

module.exports = {
  host: NOW_URL ? `https://${alias}` : 'http://localhost:3000',
  basePath: '/account',
}

Wir können die Variable assetPrefix intern weiterhin beibehalten, aber der Benutzer sollte genauer definieren, was er benötigt.

Für den Asset-Teil ist es wirklich in Ordnung, diese beiden Variablen zusammen bereitzustellen.
Für das Routing usw. benötigen wir sie separat.
Oder vielleicht können wir es sogar zusammen in einer Konfigurationsdatei bereitstellen und es dann in die Codebasis next.js aufteilen. In diesem Fall ist AssetPrefix leider nicht der richtige Name.

Als Nebeneffekt führt dies auch zu weniger Codeänderungen.
Es ist ziemlich offensichtlich, wenn Sie diese beiden PRs vergleichen:
https://github.com/panter/next.js/pull/2 (aufgeteilt)
https://github.com/panter/next.js/pull/1 (beide bestehen)

Meiner Meinung nach sollten sie getrennt sein. Der Grund dafür ist, dass es nicht kaputt und flexibler ist, assetPrefix zu behalten und basePath separat zu haben.

Ist assetPrefix der richtige Name? Beide Variablen sind eigentlich ein Präfix, oder?

assetPrefix gilt für Assets, z. B. die Seitenpakete. basePath ist für den Router.

Die Art und Weise, wie es funktionieren sollte, ist:

  • Wenn assetPrefix definiert ist, verwenden Sie assetPrefix , um Bundles zu laden. Berühren Sie nicht den Router (aktuelles Verhalten).
  • Wenn assetPrefix und basePath bereitgestellt werden, verwenden Sie assetPrefix , um Bundles zu laden, und fügen Sie basePath zum Router hinzu
  • Wenn assetPrefix nicht definiert ist und basePath ist, verwenden Sie basePath , um Bundles zu laden, und fügen Sie basePath zum Router hinzu
  • Wenn weder assetPrefix noch basePath definiert sind, machen wir nichts anderes (aktuelles Verhalten, wenn assetPrefix nicht angegeben ist)

cc @alexindigo @DullReferenceException @ 3rd-Eden

Könnten Sie Feedback zu dem oben genannten Vorschlag geben: https://github.com/zeit/next.js/issues/4998#issuecomment -414978297

@tomaswitek Ich assetPrefix für Sie nicht funktioniert hat. Dies ist das Asset-Präfix, das wir in der Produktion verwenden: "assetPrefix":"https://static.trulia-cdn.com/javascript" und es funktioniert wie erwartet.

Und im Allgemeinen verwenden wir mehrere Zonen (wir nennen sie Inseln) in derselben Domäne, und "basePathing" für jede Insel ist uns nie in den Sinn gekommen, da dies die Interoperabilität zwischen den Inseln erschweren würde. Lassen Sie mich noch etwas näher darauf eingehen:

Wir haben also zwei Inseln A und B , und die Hauptidee dabei ist Transparenz für die Benutzer, die im Rahmen ihrer Erfahrung mit einer Website von Insel zu Insel navigieren. Es sollte also Verbindungen zwischen den Inseln geben. Dann gibt es Bedenken hinsichtlich der Bereitstellung und der Anwendung.

  1. Bedenken hinsichtlich der Bereitstellung und der Anwendung - Die Anwendung hat keine Ahnung, wo sie bereitgestellt werden könnte. Sie weiß nur, wie eingehende http-Anforderungen behandelt werden. Sie hat Routen festgelegt, auf die sie reagieren kann.
    Wenn es irgendwo bereitgestellt wird - es können verschiedene Domänen, verschiedene Ports und theoretisch verschiedene basePath sein, die für die App über einen Proxy oder andere Mittel transparent gemacht werden.

  2. Querverbindungen zwischen den Inseln - um den Geist der Inseln als separate einsetzbare Einheiten zu bewahren, sollten keine internen Implementierungswissenslecks zwischen verschiedenen Inseln auftreten.
    Der beste Weg für Inseln, Seiten voneinander zu referenzieren, besteht darin, verfügbare Routen für andere Inseln zu exportieren, um sie zu konsumieren (_und in der nächsten Welt sieht es so aus, als wären benutzerdefinierte <IslandALink> -Komponenten bevorzugt Weg_).
    Bisher ist alles unkompliziert - alle Inseln gehen davon aus, dass sie dieselbe Domain teilen und ihre absoluten Pfade haben ( /path1 , path2 usw.). Auf diese Weise importiert die zweite Insel diese Liste von Pfaden und verlässt sich darauf, dass sie stabil ist. Gleichzeitig ist es ziemlich minimal, dass jede Insel ihre Pfade abwärtskompatibel hält (was im Web sowieso gut ist) :)

Wenn wir einen implementierungsspezifischen basePath hinzufügen, erhöhen wir automatisch die Komplexität des gesamten Systems. Sollte jede Insel ihren eigenen basePath für die Bereitstellung kennen (und möglicherweise diktieren)? Wie unterscheidet es sich dann von der aktuellen Arbeitsweise? Oder sollte Insel A unabhängig von ihrem Einsatzpfad sein? Wie wird dann Insel B die eingesetzte Insel A finden, da sie nur weiß, was Insel A über sich selbst weiß? Oder müssten Sie basePath für alle bereitgestellten Inseln an alle anderen Inseln liefern? Und mit der modernen Art der Bereitstellung bedeutet dies, dass alle Inseln erneut bereitgestellt werden, wenn Sie eine neue hinzufügen müssen.

Oder wie haben Sie sich diesen Teil der Geschichte vorgestellt?

Vielen Dank.

^ Es wurde vor dem Morgenkaffee geschrieben. Bitte lassen Sie mich wissen, wenn Sie eine kohärentere Erklärung für Teile davon benötigen. :) :)

Zunächst einmal vielen Dank, dass Sie sich die Zeit genommen haben, mein Problem zu überprüfen.

@timneutkens Ja assetPrefix hat Vorrang vor basePath , genau das haben wir zu Beginn besprochen. Nachdem ich gesehen hatte, wie viele Dateien ich ändern musste, dachte ich, der zweite Weg wäre sauberer. Aber ich werde zur ersten Lösung zurückkehren. Lassen Sie es uns völlig getrennt halten, überhaupt kein Problem. Ich habe nur laut nachgedacht.

@alexindigo Danke für deine ausführliche Antwort. Lassen Sie mich versuchen, Ihre Fragen zu beantworten 😏

Ich bin mir nicht sicher, was genau mit dem aktuellen AssetPrefix für Sie nicht funktioniert hat

Ich habe hier zwei Probleme:

  1. Ich kann im aktuellen Projekt nicht mit mehreren Domänen oder Subdomänen arbeiten. (Domain-Einschränkungen und kein Wildcard-SSL-Zertifikat)
  2. Die aktuelle Implementierung von assetPrefix in einer einzelnen Domain erfordert weitere Anpassungen beim Proxy-Routing, bei statischen Dateien usw. Wir könnten diese Anpassungen durch die Einführung von basePath reduzieren. Es wird nichts bremsen und die Komplexität nicht erhöhen, da Sie nicht die basePath angeben müssen, wie

Die Anwendung hat keine Ahnung, wo sie bereitgestellt werden könnte

Wir haben hier natürlich das gleiche Ziel! Wir definieren AssetPrefixes dynamisch in der aktuellen Lösung, die wir haben. Es wird über Anforderungsheader vom Proxy bereitgestellt.

Wie unterscheidet es sich dann von der aktuellen Arbeitsweise?

Der Router kennt contextPath und reduziert die Menge an benutzerdefiniertem Code.

Sollte jede Insel ihren eigenen Deployment BasePath kennen (und vielleicht diktieren)? Oder sollte Insel A unabhängig von ihrem Einsatzpfad sein?

Das muss nicht sein. Der Entwickler sollte hier Freiheit haben. Es sollte möglich sein, basePath dynamisch auf dieselbe Weise wie assetPrefix bereitzustellen.

Wie wird dann Insel B die eingesetzte Insel A finden, da sie nur weiß, was Insel A über sich selbst weiß? Oder müssten Sie basePath für alle bereitgestellten Inseln an alle anderen Inseln liefern? Und mit der modernen Art der Bereitstellung bedeutet dies, dass alle Inseln erneut bereitgestellt werden, wenn Sie eine neue hinzufügen müssen.

Vielleicht können Sie den basePath auch zum Routenexport hinzufügen. Ich weiß es nicht. Ich sage nicht, dass die Variable basePath für jeden Anwendungsfall wichtig ist. Es sieht so aus, als wäre es nicht die beste Lösung für Sie. Aber das ist völlig in Ordnung. Die Sache ist, dass Sie immer noch nur assetPrefix und sich für Ihre Inseln nichts ändern wird. Es sieht so aus, als hätten Sie sowieso Ihr eigenes Routing. Querverbindungen zwischen Zonen sind für unser Projekt nicht einmal wichtig, unsere Zonen sind wirklich unabhängig und voneinander isoliert.

Und mit der modernen Art der Bereitstellung bedeutet dies, dass alle Inseln erneut bereitgestellt werden, wenn Sie eine neue hinzufügen müssen.

Ich sehe keinen Grund warum. Ich kann mir sogar vorstellen, dass einige Zonen basePaths haben und andere nicht. Und vielleicht verwenden einige Apps die basePath-Konfiguration auch ohne Einrichtung mehrerer Zonen.

@alexindigo Könnten Sie uns bitte zwei echte Insel-URLs zur Verfügung stellen, die von next.js gerendert werden, damit ich sie in Aktion sehen kann? Ich habe versucht, eine zu finden, konnte jedoch keine Seite in Ihrer Domain mit _next -Anfragen 😄 finden
Haben alle Ihre Inseln die gleiche Konfiguration?
"assetPrefix":"https://static.trulia-cdn.com/javascript"

@tomaswitek

Ich kann im aktuellen Projekt nicht mit mehreren Domänen oder Subdomänen arbeiten. (Domain-Einschränkungen und kein Wildcard-SSL-Zertifikat)

Oh, Sie verwenden CDN also nicht im klassischen Sinne, sondern verlassen sich darauf, dass Assets direkt von jeder App abgerufen werden? Aha.

Die aktuelle Implementierung von AssetPrefix in einer einzelnen Domäne erfordert weitere Anpassungen beim Proxy-Routing, bei statischen Dateien usw. Wir könnten diese Anpassungen durch die Einführung von basePath reduzieren. Es wird nichts bremsen und die Komplexität nicht erhöhen, da Sie den basePath nicht wie bereits erwähnt als @timneutkens angeben

Übrigens war es nicht "Nein, füge diese Funktion nicht hinzu" :) Es war eher wie - "Wahrscheinlich können wir diesen Ansatz ganzheitlicher betrachten" :)

Das muss nicht sein. Der Entwickler sollte hier Freiheit haben. Es sollte möglich sein, basePath dynamisch auf dieselbe Weise wie assetPrefix bereitzustellen.

Ja. Es funktioniert jedoch nur, wenn keine Verbindung zwischen den Inseln besteht. Und das klingt so, als wäre dies Ihr Anwendungsfall. Gleichzeitig fällt es mir schwer zu verstehen, was sie zu Inseln macht, anstatt nur eine Reihe von eigenständigen Anwendungen zu sein, wenn sie zu 100% unabhängig sind. :) :)

Vielleicht können Sie den basePath auch zum Routenexport hinzufügen.

Ich sehe nicht, wie es (einfach) gemacht werden könnte, da der Routenexport zur Erstellungszeit erfolgt und basePath zur Bereitstellungszeit definiert wird und es mehr als eine Bereitstellung desselben Code-Artefakts geben könnte (Stage, Preprod, Prod, Testen von env usw.).


Haben alle Ihre Inseln die gleiche Konfiguration?
"assetPrefix": " https://static.trulia-cdn.com/javascript "

Ja, alle Inseln teilen ihr Vermögen, da als nächstes Content-Hashing durchgeführt wird, ist dies nicht nur kein Problem, sondern auch sehr vorteilhaft. (Wir extrahieren erstellte Assets aus jedem Artefakt und veröffentlichen sie zur Bereitstellungszeit auf CDN.)

Auf diese Weise haben wir nur "reguläre HTML" -Anfragen an unsere App-Server. Deshalb werden auf trulia.com keine "_next" -Pfade angezeigt

Beispiele für die Inseln:

Unsere frische brandneue Insel - Nachbarschaftsseite - https://www.trulia.com/n/ca/san-francisco/pacific-heights/81571 (mehr davon finden Sie hier: http: //www.trulia. com / Nachbarschaften)
Diese Insel ist für alle /n/* Pfade verantwortlich.

Und eine andere Insel ist unsere Anmeldeseite - https://login.trulia.com/login - es sieht aus wie eine andere Domain, aber es ist wirklich nicht so, es sieht aus verschiedenen Gründen so aus, aber technisch gesehen ist es die gleiche Bereitstellung. :) :)
Und diese Insel verarbeitet URLs wie /login , /signup .

Lassen Sie mich wissen, wenn Sie weitere Fragen haben.

@alexindigo vielen Dank für Ihre Beispiele.
Ich habe ein paar Fragen, nachdem ich die Beispiele analysiert habe 😄

Sie rendern immer noch Server für jede Insel, aber Sie versuchen, so viele mögliche Assets wie möglich in ein gemeinsames CDN zu extrahieren, oder?

Können Sie bitte etwas genauer beschreiben, was genau passiert, wenn https://www.trulia.com/n/ca/san-francisco/pacific-heights/81571 aufgerufen wird? Weiß Ihr Proxy, dass /n für Nachbarschaftsübersicht steht und leitet sie an die richtige Insel weiter? Beeinflusst es irgendwie die Anfrage, bevor sie auf der Insel ankommt?

Verwenden Sie das integrierte Routing von next innerhalb einer Insel oder haben Sie eine benutzerdefinierte Lösung?
Ich wollte das Routing auf Ihrer Insel überprüfen. Leider hat Neighborhood overview mehr oder weniger nur eine modale Navigation, ohne die URL zu ändern. In Login scheint es eine vollständig benutzerdefinierte Lösung zu geben.

Ich hoffe, ich beantworte alle Ihre Fragen in diesem Kommentar 😏

Übrigens war es nicht "Nein, füge diese Funktion nicht hinzu" :) Es war eher wie - "Wahrscheinlich können wir diesen Ansatz ganzheitlicher betrachten" :)

Sicher, es wäre großartig, eine Lösung zu finden, bei der ich next.js 😏 nicht berühren muss

Ja. Es funktioniert jedoch nur, wenn keine Verbindung zwischen den Inseln besteht. Und das klingt so, als wäre dies Ihr Anwendungsfall. Gleichzeitig fällt es mir schwer zu verstehen, was sie zu Inseln macht, anstatt nur eine Reihe von eigenständigen Anwendungen zu sein, wenn sie zu 100% unabhängig sind. :) :)

Ich habe nie geschrieben oder gesagt, dass ich nach einer "Insel" -Lösung suche. Ich habe mich gerade mit @timneutkens unterhalten, wo ich mein Problem beschrieben habe und Tims Antwort war im Grunde next.js unterstützt keine Basispfade. Und nachdem ich ein bisschen gegoogelt hatte, wurde mir klar, dass ich nicht der einzige bin, der danach sucht. Also dachte ich, ich könnte ein bisschen dazu beitragen. Danach hat Tim Sie angerufen, um mir ein Feedback zu geben, und ich bin sehr dankbar für Ihr Feedback.

Ich sehe nicht, wie es (einfach) gemacht werden könnte, da der Routenexport zur Erstellungszeit erfolgt und basePath zur Bereitstellungszeit definiert wird und es mehr als eine Bereitstellung desselben Code-Artefakts geben könnte (Stage, Preprod, Prod, Testen von env usw.).

Wenn Sie Routen zur Erstellungszeit exportieren und für andere Inseln verfügbar machen möchten, besteht der einzige einfache Weg wahrscheinlich darin, den basePath in der Konfiguration fest zu codieren. Ich verstehe was sie meinen. Auf der anderen Seite, ist das wirklich so ein Problem? Sie können die App weiterhin für verschiedene Domänen und Ports bereitstellen und für jede Umgebung denselben basePath verwenden.

Guten Morgen @tomaswitek :)

Meine Erfahrung mit der "basePath" -Funktionalität, die in ihrer Komplexität sehr täuscht, und es ist normalerweise besser, solche Dinge zu implementieren, ohne sich mit einem bestimmten Problem darauf einzulassen.
aber aus mehreren Blickwinkeln betrachten. Ähnlich wie Sie sich dem Deep Merging nähern würden - skizzieren Sie mehrere Anwendungsfälle und sehen Sie, wie (und ob) sie alle unter einen Dach fallen. Da es sehr ärgerlich ist, inkompatible Funktionen zwischen (sogar Haupt-) Versionen des Frameworks zu haben :)

Sie können die App weiterhin für verschiedene Domänen und Ports bereitstellen und für jede Umgebung denselben basePath verwenden.

Klingt so, als wären Sie mit der Lösung einverstanden, bei der dieser "basePath" Teil Ihres Routing-Codes ist, was Sie am Anfang erwähnt haben - wie ein Unterordner im Verzeichnis pages (übrigens würde dieser Ansatz den ausgewählten Entwicklern signalisieren basePath ziemlich gut). Das einzige, was Sie daran gehindert hat, ist, dass der interne nextjs-Pfad für Assets _next nicht konfigurierbar ist.

Und das klingt nach einem engeren Problem, das wir mit weniger langfristigen Nebenwirkungen lösen können.

Und es könnte uns noch weiter bringen, beispielsweise wenn wir AssetPath pro Asset konfigurieren können (z. B. mit einer Map next.config). Dadurch können wir Assets zwischen den Apps gemeinsam nutzen, wodurch die Leistung verbessert wird, und andere Dinge.

Und für diese Funktion gibt es offene PR. ;) / cc @timneutkens klingt wie es Zeit ist, zu diesem Welpen zurückzukehren. :) :)

Wenn Sie dies nicht in Kürze hinzufügen, können wir dann ein Beispiel für eine expressbasierte server.js-Datei in die Readme-Datei aufnehmen, die dies tut und funktioniert? Ich habe einige ausprobiert, die in diesen Problemen herumschwirrten, sie aber nicht zum Laufen bringen konnten. Vielen Dank.

Hallo @ccarse, ich habe eine funktionierende Gabel, die wir bereits in der Produktion verwenden: https://github.com/panter/next.js/pull/2
Ich bin auch bereit, Zeit zu investieren, um eine PR für diese Funktion zu eröffnen.
@timneutkens @alexindigo Gibt es eine andere Möglichkeit, dieses Problem zu lösen?
Wenn wir keine basePath -Konfiguration benötigen, können Sie uns bitte ein minimales Beispiel mit assetPath ?

Auch meine Firma stößt darauf.

Wir übernehmen langsam eine Legacy-App, Abschnitt für Abschnitt, und ersetzen sie durch Next.js.

Als vereinfachtes Beispiel:

| URL | App |
| --- | --- |
| example.com | Vermächtnis |
| example.com/shop | weiter |
| example.com/search | Vermächtnis |
| example.com/members | weiter |

Das heißt, wir möchten, dass in jeder Next.js-App alles vorangestellt wird ... Seiten, Routen, Assets usw.

Es ist auch erwähnenswert, dass wir Now nicht verwenden, sodass wir das Routing von now.json nicht nutzen können. Wir haben unseren eigenen Load Balancer, der vor der gesamten Domäne sitzt und dann den Datenverkehr basierend auf dem Unterpfad weiterleitet.

Wir verwenden auch einen benutzerdefinierten Server (Hapi). Es wäre also schön, wenn wir das, was hier erstellt wird, auch auf einem benutzerdefinierten Server nutzen könnten.

Vielleicht gibt es eine Kombination aus now.config.json -Einstellungen oder eine Verwendung von Mikro-Proxy, mit der wir dasselbe erreichen können, aber wir haben noch nicht die richtige Kombination gefunden.

Ich denke, wir haben das gleiche Problem mit mehreren statisch exportierten Next.js-Apps, die auf Now v2 gehostet werden.

| URL | App |
| - | - |
| example.com | weiter |
| example.com/dashboard | weiter |

Wie erwartet funktioniert die Root-App einwandfrei. Im zweiten geht es allerdings schief. Wir verpacken derzeit next/link was zusammen mit assetPrefix größten Teil des Problems löst:

export default ({ children, href, ...rest }) => (
      <Link href={process.env.NODE_ENV === "production" ? `/dashboard${href}` : href} {...rest}>
        {children}
      </Link>
);

Dies bricht jedoch prefetch da dann versucht wird, unter der falschen URL nach .js -Dateien zu suchen:

Unsere derzeitige Problemumgehung besteht darin, prefetch zu deaktivieren, was nicht ideal ist.

Wie ist der Status dazu?

Bitte suchen Sie auch nach einem Update dazu.

@timneutkens Ich bin bereit, Zeit zu investieren, um eine PR dafür zu eröffnen, wenn die Community interessiert ist. Wir verwenden bereits eine Lösung (https://github.com/panter/next.js/pull/1) in der Produktion und sind sehr zufrieden damit.

Auch dafür brauchen wir eine Lösung

Wir werden in Kürze eine neue API einführen, die diesen Vorschlag überflüssig macht.

Auch davon betroffen. Das nächste Projekt muss unter einem Unterverzeichnispfad ausgeführt werden. Ich freue mich auf das offizielle Feature. Gibt es eine ETA?

API

Wie geht's? : D.

Bitte spammen Sie den Thread nicht und verwenden Sie die H-Funktion von GitHub für das Problem.

@timneutkens Können Sie weitere Informationen bereitstellen? Welche API macht dies überflüssig? Was denkst du "bald"? Vielen Dank.

Dies hängt möglicherweise nicht genau mit mehreren Zonen zusammen, kann aber helfen ...

Ich habe etwas Ähnliches gelöst, indem ich einen benutzerdefinierten Server erstellt und Proxy-Middleware verwendet habe

Zum Beispiel: @Zertz
Bitte beachten Sie: Sie müssen das Link-Problem noch lösen. Wiederum habe ich dieses Problem gelöst, indem ich eine Link-Komponente erstellt und das Präfix über die Konfiguration an die App weitergegeben habe. Wenn ein Präfix vorhanden ist, verwenden Sie dieses oder nichts, ebenso für statische Bilder.

const proxy = require('http-proxy-middleware');

app.setAssetPrefix('/dashboard');

  // Express custom server
  // Proxy so it works with prefix and without...
  // So if asset prefix is set then it still works
  const server = express();
  server.use(
    proxy('/dashboard', {
      target: 'http://localhost:3000', 
      changeOrigin: true,
      pathRewrite: {
        [`^/dashboard`]: '',
      },
    }),
  );

Der Vorschlag, den ich erwähnte, ist # 7329

Der Vorschlag, den ich erwähnte, ist # 7329

@ Timneutkens
Können Sie uns bitte näher erläutern, wie der vorgeschlagene Haken unsere Basispfadprobleme lösen wird?
Und was ist mit Router-Weiterleitungen wie Router.push('/about') ? Wird dies auch durch einen Hook ersetzt?

Vielen Dank für Ihre Zeit 😏

Die Router-API würde sich ebenfalls ändern, da eine Komponente zum Verknüpfen erforderlich wäre. Zu diesem Zeitpunkt können Sie relative Pfade für die URL selbst verwenden.

Gibt es ein Update, wann wir eine Lösung oder zumindest eine Problemumgehung dafür finden können?

Verwenden Sie 👍 bei der ersten Ausgabe, anstatt ein Update zu veröffentlichen.

@ MMT-LD Ihre Lösung funktioniert für mich, aber jetzt wird die Seite bei jedem Link-Klick oder Router-Push-Ereignis neu geladen ☹️

Ich habe die Lösung von
Außerdem konnte ich das Problem prefetch beheben, indem ich Ausgabedateien in die vorabgerufenen Pfade kopierte.
https://github.com/fand/MDMT/blob/master/scripts/copy-preload.js

... es ist ein schmutziger Trick, aber er funktioniert trotzdem

@icholasbraun

Jetzt wird die Seite bei jedem Link-Klick oder Router-Push-Ereignis neu geladen ☹️

Ich hatte dieses Problem, wurde aber mit dem Parameter 'as' für den Link behoben, sodass der Link auf die interne Datei verweist, das 'as' jedoch relativ zum Pfad ist
z.B:
<Link href={"/${item.link}"} as={"./${item.link}"}>

@icholasbraun

Ihre Lösung funktioniert für mich, aber jetzt wird die Seite bei jedem Link-Klick oder Router-Push-Ereignis neu geladen ☹️

Das habe ich gemeint. Dies ist aus dem Gedächtnis ... aber ich bin sicher, Sie können nicht zu dem gelangen, was Sie von unten benötigen.

// WithConfig component
import getConfig from 'next/config';

const { publicRuntimeConfig } = getConfig();

const WithConfig = ({ children }) =>
  children && children({ config: publicRuntimeConfig });

export default WithConfig;
// Extended Link component

 import React from 'react';
import PropTypes from 'prop-types';
import Link from 'next/link';
import { WithConfig } from '../WithConfig';
/* 
    <Link> component has two main props:
    href: the path inside pages directory + query string. e.g. /page/querystring?id=1
    as: the path that will be rendered in the browser URL bar. e.g. /page/querystring/1

*/

const NextLink = ({
  browserHref,
  pagesHref,
  whatever,
}) => {
  return (
    <WithConfig>
      {({ config: { pathPrefix } = {} }) => (
        <Link
          as={pathPrefix ? `${pathPrefix}${browserHref}` : browserHref}
          href={pagesHref}
          passHref
        >
          <a>{whatever}</a> // this bit is up to you - children or whatever
        </Link>
      )}
    </WithConfig>
  );
};

NextLink.propTypes = {
  browserHref: PropTypes.string.isRequired,
  pagesHref: PropTypes.string,
};

NextLink.defaultProps = {
  pagesHref: undefined,
};

export default NextLink;

Verwendung:

import NextLink from '../NextLink'

<NextLink browserHref={`/page/1`} pagesHref={`/page?querystring=1`} whatever='I'm the link' />

Viel Glück: Smiley:

Da der useLink RFC jetzt abgelehnt wird (# 7329) und die Unterstützung von basePath uns sehr helfen würde, ist das Next.js-Projekt glücklich, PRs zu akzeptieren, die ihn implementieren? Ich bin bereit es zu tun.

Wenn man sich diese Implementierung von @tomaswitek ansieht , scheint sie in die richtige Richtung zu gehen, was den Router vor allem auf basePath . Gibt es andere nicht offensichtliche Dinge, die die Unterstützung von basePath schwierig machen würden?

Insgesamt denke ich, dass das Design klar ist, nur eine einzige Konfigurationsvariable:

module.exports = {
  basePath: '/demo'
}

Interaktionen mit assetPrefix sind hier genau definiert: https://github.com/zeit/next.js/issues/4998#issuecomment -414978297.


UPDATE : Ich habe auch darüber nachgedacht, ob es möglich ist, dies zu implementieren, indem ein benutzerdefinierter Router erstellt und der Standardrouter irgendwie ausgetauscht wird, aber es scheint nicht möglich zu sein, Next.js codiert seinen Router fest, siehe z. B. hier . Ich bin auch skeptisch, dass "nur" das Ersetzen des Routers ausreichen würde; Die Funktion muss wahrscheinlich von Next.js als Ganzes unterstützt werden.

Dieses Problem besteht seit 2017, gibt es eine Problemumgehung? Oder eine offizielle Antwort auf unsere basePath-Anfrage?

Nachdem Sie versucht haben, dies mit der Kombination aus assetPrefix und einer benutzerdefinierten <Link> -Komponente zum Laufen zu bringen, wie in z. B. https://github.com/zeit/next.js/issues/4998#issuecomment vorgeschlagen -464345554 oder https://github.com/zeit/next.js/issues/4998#issuecomment -521189412, ich glaube leider nicht, dass dies möglich ist.

Das Definieren von assetPrefix war relativ einfach, so etwas in next.config.js :

const assetPrefix = process.env.DEPLOYMENT_BUILD ? '/subdir' : '';

module.exports = {
  assetPrefix,
  env: {
    ASSET_PREFIX: assetPrefix,
  },
}

Der nächste Schritt ist eine benutzerdefinierte Link -Komponente. Die erste Idee, die z. B. in https://github.com/zeit/next.js/issues/4998#issuecomment -464345554 gegeben wird, besteht darin, href wie folgt vorangestellt zu haben (vereinfacht):

export default ({ children, href, ...rest }) => (
  <Link href={`${process.env.ASSET_PREFIX}${href}`} {...rest}>
    {children}
  </Link>
);

Wie von anderen in diesem Thread berichtet, wird das Vorabrufen unterbrochen, da die Anforderungen plötzlich an / subdir /example.js gesendet werden - das andere "Unterverzeichnis" sollte nicht vorhanden sein. Mit unserer benutzerdefinierten Komponente Link wir href auf /subdir/example . Kein Wunder, dass Next.js ein Bundle der Seite pages/subdir/example.js anfordert.

OK, problematisches Prefetching klingt nicht nach dem Ende der Welt (obwohl die UX ziemlich hässlich ist), aber in unserer App wird es schlimmer, wenn wir das dynamische Routing von Next.js 9 verwenden. Dazu müssen wir as richtig einstellen, damit die Entwicklung der benutzerdefinierten Link -Komponente folgendermaßen aussieht:

export default ({ children, href, as, ...rest }) => (
  <Link 
    href={`${process.env.ASSET_PREFIX}${href}`}
    as={`${process.env.ASSET_PREFIX}${as}`}
    {...rest}
  >
    {children}
  </Link>
);

Verwendung ist:

<CustomLink href='/post/[id]' as='/post/1'>...</CustomLink>

welches konvertiert wird zu:

<Link href='/subdir/post/[id]' as='/subdir/post/1'>...</Link>

und das hat bei der Bereitstellung auf Now überhaupt nicht funktioniert - der Versuch, zu https://deployment-id.now.sh/subdir/post/1 zu navigieren, führte zu 404. Ich bin mir nicht ganz sicher, warum, vielleicht ist es auch ein Problem mit @now/next builder ( UPDATE : Es liegt an https://github.com/zeit/next.js/pull/8426#issuecomment-522801831), aber letztendlich verwirren wir den Router von Next.js, wenn wir nach /subdir/post/[id] fragen.

In diesem Thread gibt es ein weiteres Beispiel, https://github.com/zeit/next.js/issues/4998#issuecomment -521189412, das nur wie folgt vorstellt, nicht href (vereinfacht):

export default ({ children, href, as, ...rest }) => (
  <Link href={href} as={`${process.env.ASSET_PREFIX}${as}`} {...rest}>
    {children}
  </Link>
);

aber das wird diesen Fehler im Browser auslösen:

Der <Link> as ist nicht mit dem Wert von href kompatibel. Dies ist ungültig.

Dieses Problem wurde unter https://github.com/zeit/next.js/issues/7488 gemeldet

Nach all dem glaube ich nicht, dass es eine Lösung gibt, bis so etwas wie basePath unterstützt wird, bei dem ich gerne helfen würde.

@borekb Ich bin auch bereit zu helfen, wie ich schon ein paar Mal erwähnt habe. Alle Problemumgehungen, die ich bisher gesehen habe, lösen nur einen Teil des Problems. Im Moment verwenden wir eine Abzweigung von next.js in der Produktion, die basePath implementiert.

Wir werden in Kürze eine neue API einführen, die diesen Vorschlag überflüssig macht.

@tim Ist es immer noch so oder wurde der neue Vorschlag für API geschlossen? https://github.com/zeit/next.js/issues/7329

Übrigens. morgen wird es genau ein Jahr dauern, bis ich diese Ausgabe eröffnet habe 🎉

Eine relativ wilde Idee ist es, Seiten in so etwas wie src/pages und sie dann mit dem richtigen Speicherort zu verknüpfen. Zum Beispiel:

  • Für die Bereitstellung auf myapp.example.com würde ich src/pages mit pages
  • Für die Bereitstellung auf example.com/myapp würde ich src/pages mit pages/myapp

In Kombination mit der benutzerdefinierten Komponente <Link> und assetPrefix es funktionieren, aber ich bin nicht mutig genug, es zu versuchen 😄.

Irgendein Update damit?

Irgendwelche Fortschritte basePath Unterstützung von

@icholasbraun

Jetzt lädt die Seite bei jedem Link-Klick oder Router-Push-Ereignis frowning_face neu

Ich hatte dieses Problem, wurde aber mit dem Parameter 'as' für den Link behoben, sodass der Link auf die interne Datei verweist, das 'as' jedoch relativ zum Pfad ist
z.B:
<Link href={"/${item.link}"} as={"./${item.link}"}>

Du hast meinen Tag gerettet! :)))

Ich mache das gleiche mit Router.push(`/route`, `${process.env.BASE_PATH}route`);

@icholasbraun

Jetzt wird die Seite bei jedem Link-Klick oder Router-Push-Ereignis neu geladen ☹️

Ich hatte dieses Problem, wurde aber mit dem Parameter 'as' für den Link behoben, sodass der Link auf die interne Datei verweist, das 'as' jedoch relativ zum Pfad ist
z.B:
<Link href={"/${item.link}"} as={"./${item.link}"}>

Diese Lösung funktioniert nicht mit dem nächsten 9 dateibasierten Routing. /route/[id] , ${process.env.BASE_PATH}/route${id} löst diesen Fehler aus

Dieser Kommentar erklärt das Problem sehr gut.

Obwohl ich einige Leute gesehen habe, die darüber diskutieren, wie die Lösungen hier das Vorabrufen unterbrechen. Für uns gibt es ein weiteres wichtigeres Thema.

Mit next9 führt die Verwendung eines AssetPrefix in Ihrem href dass next _ immer eine Serverroute ausführt. Ich habe in dieser Ausgabe ein Reproduktions-Repo erstellt, das die Ereignisse demonstriert.

Dies unterbricht im Wesentlichen unseren Apollo Client-Cache, da er auf jeder Route neu erstellt wird.

Ich denke, die Implementierung vergleicht die zugrunde liegende Seite href ohne ein AssetPrefix mit den nächsten Routen href (einschließlich eines AssetPrefix) - was zu einer tiefen Route führt.

Beispiel: Wenn Sie sich auf href /prefix/page (die zugrunde liegende Seite ist nur /page ) und Ihre nächste Route href /prefix/page/[id] (denn ohne das Präfix wird es 404) Dies ist eine völlig andere Route und eine flache Route ist nicht möglich.

Aktuelle Problemumgehungen mit Express-Routen untersuchen

Bei Verwendung Komponente mit den href Requisiten, die basePath ist, funktioniert der Prefetch nicht.
PLZ unterstützt basePath und Prefetch, es wird großartig

Ich könnte das wirklich gebrauchen. Ich führe mehrere Apps von einer einzigen Serverquelle aus und habe jede in ihre eigenen web/appX/{next project files} . Es wäre großartig, mehr Kontrolle über den basePath zu haben. Ich habe vorerst eine Problemumgehung gefunden, aber sie ist nicht sehr hübsch.

Für den statischen Export ist außerdem basePath 😊 erforderlich

scheint Arbeitserfolg 👏

{
  experimental:{
    basePath: '/some/dir',
  }
}

Dies ist leider eine ziemlich schlechte Einschränkung für uns :(

Wir haben alle Apps hinter einem Reverse-Proxy, daher müssen Pfade vorangestellt werden (im folgenden Beispiel ist dies das Präfix /auction-results ).

Wir verwenden bereits das Präfix assetPrefix - und dies ermöglicht es Apps, für serverseitige Anforderungen in Ordnung zu sein.
Beispiel: mydomain.com/auction-results/ funktioniert gut, wenn Sie ein Express-Routing wie das folgende verwenden:

router.get(`/${appPrefix}/`, (req, res) => {
  nextApp.render(req, res, '/national', req.params);
});

Aber wenn wir versuchen, eine clientseitige Navigation über next/link durchzuführen, z.

Dabei ist /auction-results das Anwendungspräfix und /national die Seite in ~pages/national

<Link href="/national" as="/auction-results/">
  <a>Goto National Page</a>
</Link>

Dies macht nichts (Geisterklick)

Es ist nicht ideal, Links zum Aktualisieren ganzer Seiten zu haben.

Wenn es eine Möglichkeit gibt, wie ich dabei helfen kann, würde ich gerne

Jedes Update dazu ... letztes Jahr um diese Zeit bin ich auf dieses Problem gestoßen. Jetzt, ein Jahr später, arbeite ich an einer neuen App und muss die gleichen Problemumgehungen wie im letzten Jahr durchführen ... irgendwie alarmierend für eine "produktionsbereite" Reaktion fw. Basispfade sollten ein Vanille-Merkmal sein.

Jedes Update dazu ... letztes Jahr um diese Zeit bin ich auf dieses Problem gestoßen. Jetzt, ein Jahr später, arbeite ich an einer neuen App und muss die gleichen Problemumgehungen wie im letzten Jahr durchführen ... irgendwie alarmierend für eine "produktionsbereite" Reaktion fw. Basispfade sollten ein Vanille-Merkmal sein.

Ich bin mir nicht sicher, was Sie erwarten, wenn Sie dies veröffentlichen.

Next.js wird von meinem Team (5 Personen) in Vollzeit bearbeitet, und wir arbeiten gleichzeitig an vielen Funktionen. Im vergangenen Jahr haben wir daran gearbeitet:

Effektiv machen Next.js-Anwendungen (neu und vorhanden) erheblich kleiner, schneller und skalierbarer.

Wenn Sie Ihre "Gegenstimme" für eine Funktion äußern möchten, können Sie. Verwenden Sie die Funktion 👍 für den ersten Thread.

Ich bin definitiv der Meinung, dass basePath eine integrierte Funktion sein sollte. Es ist bereits auf der Roadmap und ich habe sogar eine erste PR geschrieben, die Sie durch Zurücklesen des Threads hätten sehen können.

Hier ist die PR: https://github.com/zeit/next.js/pull/9872

Wenden Sie sich an [email protected], wenn Sie einen finanziellen Beitrag zur Umsetzung dieser Funktion leisten möchten.

Wie ist der Status dazu? wir sind wirklich darauf angewiesen: /

Die Unterstützung von

vgl. https://github.com/zeit/next.js/pull/9872

Die Unterstützung von

vgl. # 9872

@martpie habe ich schon gesehen, aber für. Mein Fall basePath ist nicht nur einer, es kann sich um mehrere basePath handeln, da wir unsere App über verschiedene "URLs" bereitstellen und das Einrichten von basePath während der Erstellungszeit keine Option ist (obwohl dies der Fall ist) ein Array von Pfaden anstelle einer einzelnen Zeichenfolge zu unterstützen)

@ Timneutkens Danke für das Update. Würdest du so nett sein, ein weiteres Update zu geben? Dies ist für uns ein Schlüsselmerkmal und wir müssen wissen ...

  1. Wird dies nur für Unternehmen gelten (Ihr Hinweis auf den Kontakt mit Unternehmensverkäufen hat einige Irritationen verursacht)?

  2. Es scheint auf der Roadmap zu stehen, laut PR wird es nicht wieder entfernt; Können Sie einen Hinweis geben, ob es sicher ist, diese Funktion jetzt zu nutzen, ohne in den nächsten Monaten Überraschungen zu erleben, wie eine verkrüppelte Open-Source-Version und eine andere mit voller Unterstützung, nachdem wir Wochen mit einigen zufälligen Verkäufern über willkürliche Preise verhandelt haben?

Ich verstehe, dass ihr an vielen Funktionen arbeitet und jeder seine Prioritäten hat, aber auch kleinere Setups müssen als Nächstes einen Proxy erstellen, mehrere Instanzen ausführen und ihm einen dedizierten basePath pro Service geben. Bevor wir nun beginnen, mehrere Dienste auf Next aufzubauen, müssen wir wissen, wie wahrscheinlich und bald diese Funktion als vollständige Open Source verfügbar ist. Andernfalls wäre es einfach zu riskant, weitere Zeit in Next zu investieren.

Vielen Dank für Ihr Verständnis und freuen uns auf Ihr Feedback.

FWIW, ich habe es jetzt zum Laufen gebracht und für andere, die vorbeifahren:

Tragen Sie dies in Ihr next.config.js :

module.exports = {
  experimental: {
    basePath: '/custom',
  },
}

Dann musste ich den Server neu starten und meine Webserver-Middleware richtig einrichten:

Ich fange alle Anfragen über einen benutzerdefinierten Pfad ab, z. app.use('/custom', (req, res...) => { ... und dann (was wichtig war) muss ich einen Proxy für die URL des Systems erstellen, auf dem Next ausgeführt wird (also die interne Adresse Ihrer Container-Orchestrierung und erneut den entsprechenden Pfad, wenn Sie http-proxy => zB ... target: 'http://next:3000/custom ), also nicht nur der Host ohne den benutzerdefinierten Pfad. Wenn Sie http-proxy-middleware verwenden, benötigen Sie dies nicht.

Es fühlt sich ganz ok an, ich hoffe, dass diese Funktion keine EE-Lizenz benötigt. Wenn Ihr Team Hilfe benötigt, um diese Funktion ausgereift zu machen, lassen Sie es uns bitte wissen, vielleicht können wir Ihnen helfen!

Bearbeiten: Habe es gerade auch im Next-Produktionsmodus versucht und es scheint auch zu funktionieren.

@ Timneutkens Danke für das Update. Würdest du so nett sein, ein weiteres Update zu geben? Dies ist für uns ein Schlüsselmerkmal und wir müssen wissen ...

  1. Wird dies nur für Unternehmen gelten (Ihr Hinweis auf den Kontakt mit Unternehmensverkäufen hat einige Irritationen verursacht)?
  2. Es scheint auf der Roadmap zu stehen, laut PR wird es nicht wieder entfernt; Können Sie einen Hinweis geben, ob es sicher ist, diese Funktion jetzt zu nutzen, ohne in den nächsten Monaten Überraschungen zu erleben, wie eine verkrüppelte Open-Source-Version und eine andere mit voller Unterstützung, nachdem wir Wochen mit einigen zufälligen Verkäufern über willkürliche Preise verhandelt haben?

Ich verstehe, dass ihr an vielen Funktionen arbeitet und jeder seine Prioritäten hat, aber auch kleinere Setups müssen als Nächstes einen Proxy erstellen, mehrere Instanzen ausführen und ihm einen dedizierten basePath pro Service geben. Bevor wir nun beginnen, mehrere Dienste auf Next aufzubauen, müssen wir wissen, wie wahrscheinlich und bald diese Funktion als vollständige Open Source verfügbar ist. Andernfalls wäre es einfach zu riskant, weitere Zeit in Next zu investieren.

Vielen Dank für Ihr Verständnis und freuen uns auf Ihr Feedback.

@ pe-s Ich denke du verstehst meinen Beitrag falsch.

Derzeit gibt es keine "Enterprise Next.js-Version". Ich bezog mich auf die zahlreichen Gelegenheiten, in denen externe Unternehmen für die Beratung aufbrachten, um Funktionen wie diese in kürzerer Zeit zu entwickeln. ZB wurde die Zonenunterstützung in Zusammenarbeit mit Trulia aufgebaut.

Diese Funktion wird noch bearbeitet und steht auf der Roadmap. Alle Funktionen, an denen gearbeitet wird, sind Open Source, wie gesagt, es gibt keine Unternehmensversion von Next.js. Wir haben mehrere Prioritäten von High-Impact - Arbeit auf der Roadmap allerdings damit , warum ich zu kontaktieren bezeichnen [email protected] wenn Sie diese Funktion so schnell wie möglich benötigen / Enterprise - Support zu diskutieren für Next.js.

@ Timneutkens TX für Ihre schnelle Antwort und großartig! Dann können wir alles rein :)
Mach weiter so!

Die Basepath-Unterstützung ist derzeit auf next@canary verfügbar, sie ist nicht mehr experimentell. Es wird bald auf dem stabilen Kanal sein.

Ich bin ziemlich spät dran, aber haben Sie darüber nachgedacht, tatsächlich HTML <base> anstatt dies manuell zu handhaben?

Die Basepath-Unterstützung ist derzeit auf next@canary verfügbar, sie ist nicht mehr experimentell. Es wird bald auf dem stabilen Kanal sein.

@ Timneutkens , danke für diesen Zusatz. Wissen Sie, wann der nicht experimentelle basePath-Support offiziell veröffentlicht wird?

Wenn ich den basePath einstelle, werden die Assets (im öffentlichen Ordner) erwartungsgemäß an die entsprechende URL geliefert. Wenn ich sie jedoch in meinem Code referenziere, muss ich den Basispfad manuell zum src hinzufügen, da sie sonst weiterhin vom normalen Pfad referenziert werden. Ist dies die erwartete Verwendung von basePath? Ich habe auch versucht, AssetPrefix zu verwenden, aber es hatte keine Auswirkungen auf meinen Code, die ich erkennen konnte.

Beispiel :

  1. mit next v9.4.5-canary.24
  2. basePath /alerts in next.config.js auf
const basePath = '/alerts';
module.exports = {
  basePath: basePath,
  env: {
    BASE_PATH: basePath,
  },
};
  1. Vermögenswert befindet sich in public/images/example.png
  2. Beispiel für die Verwendung eines Assets in einer Reaktionskomponente:
const ExampleImage = () => (
  <img src={`${process.env.BASE_PATH}/images/example.png`} />
);

In meinen Tests werden die URLs der Assets nicht aktualisiert.

Ich habe den neuesten Kanarienvogel installiert:
npm install [email protected]

next.config.js

const isProd = process.env.NODE_ENV === 'production';

module.exports = {
  basePath: isProd ? '/example' : ''
}

Alle Seiten und Links werden korrekt geladen:
http: // localhost : 3000 / example / posts / Pre-Rendering
http: // localhost : 3000 / example / posts / ssg-ssr
http: // localhost : 3000 / example / posts / Pre-Rendering

Bilder, Favoriten usw. werden jedoch nicht zugeordnet:
http: // localhost : 3000 / favicon.ico 404
http: // localhost : 3000 / images / profile.jpg 404

Hat jemand das getestet? Ich habe auch versucht, AssetPrefix zu verwenden, aber das hat auch nicht funktioniert.

Außerdem bin ich verwirrt, warum nicht die eingebaute Browser-Funktionalität dafür verwenden?
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base

Vielen Dank, dass Sie sich auch mit @kmturley befasst haben . Ich bin froh zu wissen, dass es nicht nur ich bin.
@ Timneutkens , sollten wir dieses Problem erneut öffnen / ein neues Problem für diesen Fehler erstellen?

Sie müssen Bilder manuell voranstellen. Sie können den basePath mit abrufen

const {basePath} = useRouter()

https://nextjs.org/docs/api-reference/next.config.js/cdn-support-with-asset-prefix

Next.js verwendet Ihr Präfix automatisch in den geladenen Skripten, dies hat jedoch keinerlei Auswirkungen auf den öffentlichen Ordner.

Jetzt stelle ich fest, dass es mehrere Möglichkeiten gibt, auf Dateien in / public zu verlinken. zB <img/> <link/> ...
Müssen wir deshalb den basePath für jeden manuell angeben?

Wenn eine Komponente wie die folgende verfügbar wäre, würde dies meiner Meinung nach Zeit sparen und die Verwirrung vieler Menschen verringern.

<WithinBasePath>
  {/* automatically fixes the path with basePath */}
  <img src="/logo.png" />
</WithinBasePath>

Ich denke wirklich nicht, dass dies angemessen ist, aber das habe ich gemeint.

// src/components/WithinBasePath/index.tsx

import React from "react"
import path from "path"
import { useRouter } from "next/router"
interface Props {}

const WithinBasePath: React.FC<Props> = (props) => {
  const { basePath } = useRouter()
  const children = [props.children].flatMap((c) => c) as React.ReactElement[]
  return (
    <>
      {children.map((child, key) => {
        let newChild = null

        switch (child.type) {
          case "img":
            newChild = React.createElement(child.type, {
              ...child.props,
              src: path.join(basePath, child.props.src),
              key,
            })
            break
          case "link":
            newChild = React.createElement(child.type, {
              ...child.props,
              href: path.join(basePath, child.props.href),
              key,
            })
            break
          default:
            newChild = React.createElement(child.type, {
              ...child.props,
              key,
            })
        }
        return newChild
      })}
    </>
  )
}
export default WithinBasePath

// pages/test.tsx

import React from "react"
import WithinBasePath from "@src/components/WithinBasePath"
interface Props {}

const test: React.FC<Props> = (props) => {
  return (
    <WithinBasePath>
      <img src="/123.jpg" />
      <link href="/abc.jpg" />
      <div>other element</div>
    </WithinBasePath>
  )
}
export default test

Verwenden Sie für diejenigen, die versuchen, const {basePath} = useRouter() , einen Hook, um mit Klassen und Komponenten zu arbeiten und den folgenden Fehler zu erhalten:

Ungültige Hook-Call-Warnung

https://reactjs.org/warnings/invalid-hook-call-warning.html

Sie können es zum Laufen bringen mit:

import { withRouter, Router } from 'next/router'

class Example extends Component<{router: Router}, {router: Router}> {
  constructor(props) {
    super(props)
    this.state = {
      router: props.router
    }
  }
  render() {
    return (
      <Layout home>
        <Head><title>Example title</title></Head>
        <img src={`${this.state.router.basePath}/images/creators.jpg`} />
      </Layout>
    )
  }
}
export default withRouter(Example)

Wenn Sie basePath mit Markdown verwenden möchten, müssen Sie anscheinend in der Zeichenfolge suchen und ersetzen:

const content = this.state.doc.content.replace('/docs', `${this.state.router.basePath}/docs`);
return (
<Layout>
  <Container docs={this.state.allDocs}>
    <h1>{this.state.doc.title}</h1>
    <div
      className={markdownStyles['markdown']}
      dangerouslySetInnerHTML={{ __html: content }}
    />
  </Container>
</Layout>
)

Sie müssen Bilder manuell voranstellen. Sie können den basePath mit abrufen

const {basePath} = useRouter()

Diese Lösung berücksichtigt jedoch keine in eine CSS- oder SCSS-Datei importierten Bilder. Haben Sie eine Lösung zum Festlegen des Basispfads beim Importieren eines Assets aus einer CSS- oder SCSS-Datei?
Bei dieser Lösung müssen wir sicherstellen, dass alle Bilder entweder über ein IMG-Tag, ein Inline-Styling oder über das Style-Tag importiert werden. Es ist nicht ideal, da es Ihre Stile aufteilt, um sie an mehreren Stellen zu implementieren.

@peetjvv Hier ist eine suboptimale Lösung für die Verwendung von Assets mit vorangestellten basePaths in CSS. Erstellen, importieren und fügen Sie eine <CSSVariables> -Komponente in _app.tsx , die ein globales inline <style> -Element mit CSS-Variablen einfügt, das Sie dann in allen Ihren Stylesheets verwenden können.

ZB bei der Eröffnung von <body> Variablen erstellen und injizieren:

<style>
:root {
      --asset-url: url("${basePath}/img/asset.png");
}
</style>

Um diesen basePath zu erhalten, verwende ich den @ kmturley -Ansatz mit withRouter .
So könnte diese Komponente aussehen:

import { withRouter, Router } from "next/router";
import { Component } from "react";

export interface IProps {
  router: Router;
}

class CSSVariables extends Component<IProps> {
  render() {
    const basePath = this.props.router.basePath;
    const prefixedPath = (path) => `${basePath}${path}`;
    const cssString = (value) => `\"${value}\"`;
    const cssURL = (value) => `url(${value})`;
    const cssVariable = (key, value) => `--${key}: ${value};`;
    const cssVariables = (variables) => Object.entries(variables)
      .map((entry) => cssVariable(entry[0], entry[1]))
      .join("\n");
    const cssRootVariables = (variables) => `:root {
      ${cssVariables(variables)}
    }`;

    const variables = {
      "asset-url": cssURL(
        cssString(prefixedPath("/img/asset.png"))
      ),
    };

    return (
      <style
        dangerouslySetInnerHTML={{
          __html: cssRootVariables(variables),
        }}
      />
    );
  }
}

export default withRouter(CSSVariables);
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen