Next.js: Demande de fonctionnalité: prise en charge de Basepath

Cr√©√© le 21 ao√Ľt 2018  ¬∑  73Commentaires  ¬∑  Source: vercel/next.js

Demande de fonctionnalité

Votre demande de fonctionnalité est-elle liée à un problème? Décrivez s'il vous plait.

Multi zones est une fonctionnalit√© int√©ressante qui permet d'ex√©cuter plusieurs applications next.js sur le m√™me domaine, mais elle ne permet pas de d√©finir un chemin de base qui sera accept√© par toutes les parties de next.js. √Čtant donn√© que nous ne sommes pas en mesure de nommer les applications pour le moment, il n'est pas possible d'avoir les m√™mes noms pour les pages dans diverses applications.

Décrivez la solution que vous souhaitez

Je veux pouvoir configurer un basepath dans le fichier next.config.js. Gr√Ęce √† cette configuration, toutes les parties de next.js (routeur, lien, actifs statiques, etc.) conna√ģtront le chemin de base et g√©n√©reront automatiquement et correspondront aux chemins corrects.

Décrivez les alternatives que vous avez envisagées

Une alternative consiste à imbriquer toutes les pages souhaitées dans un dossier qui correspond au chemin de base. Cela résout juste un petit problème de routage et est assez moche car la plupart de mes chemins de base ne sont pas des chemins à un niveau.
La deuxième alternative consiste à configurer un proxy de manière à ce que le chemin de base soit automatiquement supprimé avant que la demande n'arrive dans une application next.js et à implémenter également un composant Link personnalisé qui ajoute automatiquement le chemin de base à tous les liens. Je ne veux tout simplement pas maintenir le fork personnalisé de next.js. Cela n'a pas de sens à mon avis.

Contexte supplémentaire

La solution assetPrefix nous permet de d√©finir un pr√©fixe diff√©rent pour chaque application. Mais aussi juste que je sache, cela ne fonctionne qu'avec des h√ītes diff√©rents.

exemple with-zones

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

Si j'y ajoute un chemin de base, tout échoue

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

screen shot 2018-08-21 at 10 47 08

À mon avis, nous devrions le diviser en 2 variables:

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

Problèmes liés

story needs investigation

Commentaire le plus utile

Toute mise √† jour √† ce sujet ... l'ann√©e derni√®re √† cette √©poque, j'ai rencontr√© ce probl√®me. Maintenant, un an plus tard, je travaille sur une nouvelle application et je dois faire les m√™mes solutions de contournement que l'ann√©e derni√®re ... un peu alarmant pour une r√©action ¬ępr√™te pour la production¬Ľ. Les basepaths devraient √™tre une fonctionnalit√© de vanille.

Je ne suis pas s√Ľr de ce que vous attendez en publiant ceci.

Next.js est travaillé à plein temps par mon équipe (5 personnes), et nous travaillons sur de nombreuses fonctionnalités en même temps. Au cours de la dernière année, nous avons travaillé sur ceux-ci:

Rendre les applications Next.js (nouvelles et existantes) nettement plus petites, plus rapides et plus évolutives.

Si vous souhaitez exprimer votre ¬ęvote favorable¬Ľ pour une fonctionnalit√©, vous pouvez. utilisez la fonction ūüĎć sur le thread initial.

Je suis tout à fait d'accord que basePath devrait être une fonctionnalité intégrée. C'est déjà sur la feuille de route et j'ai même écrit un premier PR, que vous auriez pu voir en relisant sur le fil.

Voici le PR: https://github.com/zeit/next.js/pull/9872

N'h√©sitez pas √† contacter [email protected] si vous souhaitez contribuer financi√®rement √† la r√©alisation de cette fonctionnalit√©.

Tous les 73 commentaires

cc @jxnblk

cc @alexindigo @DullReferenceException

J'adorerais avoir vos commentaires ūüĎć

Après avoir joué avec le code, j'ai réalisé qu'il serait beaucoup plus facile de diviser assetPrefix en plusieurs parties:

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

Nous pouvons toujours conserver la variable assetPrefix interne, mais l'utilisateur doit définir plus précisément ce dont il a besoin.

Pour la partie actif, il est vraiment normal de fournir ces deux variables ensemble.
Pour le routage, etc., nous en avons besoin séparément.
Ou peut-être pouvons-nous même le fournir ensemble dans un fichier de configuration, puis le diviser dans la base de code next.js. Dans ce cas, assetPrefix n'est pas le bon nom, j'ai peur.

En tant qu'effet secondaire, cela entra√ģne √©galement moins de changements de code.
C'est assez évident si vous comparez ces deux PR:
https://github.com/panter/next.js/pull/2 (divisé)
https://github.com/panter/next.js/pull/1 (passez les deux)

À mon avis, ils devraient être séparés, la raison en est qu'il n'est pas cassant et plus flexible de garder assetPrefix et d'avoir basePath séparément.

Est-ce que assetPrefix le bon nom alors? Les deux variables sont en fait un préfixe, non?

assetPrefix est pour les actifs, par exemple: les groupes de pages. basePath sera pour le routeur.

La façon dont cela devrait fonctionner est:

  • si assetPrefix est d√©fini, utilisez assetPrefix pour charger les bundles, ne touchez pas au routeur (comportement actuel)
  • si assetPrefix et basePath sont fournis, utilisez assetPrefix pour charger les bundles, ajoutez basePath au routeur
  • si assetPrefix n'est pas d√©fini et que basePath est, utilisez basePath pour charger les bundles et ajoutez basePath au routeur
  • si ni assetPrefix ni basePath n'est d√©fini, nous ne faisons rien de diff√©rent (comportement actuel lorsque assetPrefix n'est pas fourni)

cc @alexindigo @DullReferenceException @ 3rd-Eden

Pourriez-vous nous faire part de vos commentaires sur la proposition ci-dessus: https://github.com/zeit/next.js/issues/4998#issuecomment -414978297

@tomaswitek Je ne sais pas exactement ce qui n'a pas fonctionné pour vous avec assetPrefix actuel, c'est le préfixe d'actif que nous utilisons en production: "assetPrefix":"https://static.trulia-cdn.com/javascript" et cela fonctionne comme prévu.

Et en g√©n√©ral, nous utilisons plusieurs zones (nous les appelons des √ģles) sur le m√™me domaine et "basePathing" chaque √ģle ne nous est jamais venu √† l'esprit, car cela compliquerait l'interop√©rabilit√© entre les √ģles. Permettez-moi de vous expliquer un peu plus:

Nous avons donc deux √ģles A et B , et l'id√©e principale est la transparence pour les utilisateurs qui naviguent d'√ģle en √ģle dans le cadre de leur exp√©rience sur un seul site Web. Il devrait donc y avoir des liens entre les √ģles. Ensuite, il y a le probl√®me de d√©ploiement et le probl√®me d'application.

  1. Probl√®me de d√©ploiement vs probl√®me d'application - l'application n'a aucune id√©e de l'endroit o√Ļ elle pourrait √™tre d√©ploy√©e, elle sait juste comment g√©rer les requ√™tes http entrantes - elle a d√©fini les itin√©raires auxquels elle peut r√©pondre.
    Lorsqu'il est déployé quelque part, il peut s'agir de domaines différents, de ports différents, et oui, théoriquement, il peut s'agir de basePath différent, qui sera rendu transparent pour l'application via un proxy ou d'autres moyens.

  2. Liens crois√©s entre les √ģles - pour conserver l'esprit des √ģles en tant qu'entit√©s d√©ployables distinctes, il ne devrait y avoir aucune fuite de connaissances internes sur la mise en Ňďuvre entre les diff√©rentes √ģles.
    Donc, le meilleur moyen pour les √ģles de r√©f√©rencer les pages les unes des autres est d'exporter les routes disponibles pour les autres √ģles √† consommer (_et dans le monde nextjs, il semble que des composants personnalis√©s <IslandALink> seraient pr√©f√©r√©s fa√ßon_).
    Jusqu'√† pr√©sent, tout est simple - toutes les √ģles supposent partager le m√™me domaine et avoir leur ensemble de chemins absolus ( /path1 , path2 , etc.). De cette fa√ßon, la deuxi√®me √ģle importe cette liste de chemins et compte sur elle pour √™tre stable. Dans le m√™me temps, il est assez minimal pour chaque √ģle de garder ses chemins r√©trocompatibles (ce qui est une bonne chose sur le Web de toute fa√ßon) :)

Lorsque nous ajoutons un basePath sp√©cifique au d√©ploiement, nous augmentons automatiquement la complexit√© de l'ensemble du syst√®me - chaque √ģle devrait-elle conna√ģtre (et peut-√™tre dicter) son propre basePath de d√©ploiement? Alors en quoi est-ce diff√©rent de la fa√ßon dont les choses fonctionnent actuellement? Ou l'√ģle A devrait-elle √™tre ind√©pendante de son chemin de d√©ploiement? Alors comment l'√ģle B trouvera-t-elle l'√ģle d√©ploy√©e A, puisqu'elle ne sait que ce que l'√ģle A sait d'elle-m√™me? Ou vous devrez fournir basePath pour toute l'√ģle d√©ploy√©e √† toutes les autres √ģles? Et avec une mani√®re moderne de d√©ployer des choses, cela signifie red√©ployer toutes les √ģles lorsque vous devez en ajouter une nouvelle.

Ou comment avez-vous envisagé cette partie de l'histoire?

Je vous remercie.

^ il a été écrit avant le café du matin, alors faites-le moi savoir si vous avez besoin d'explications plus cohérentes pour l'une ou l'autre de ses parties. :)

Tout d'abord merci les gars que vous avez pris le temps de revoir mon problème.

@timneutkens Oui assetPrefix a la priorité sur basePath , c'est exactement ce dont nous avons discuté au début. Après avoir vu le nombre de fichiers que je devais modifier, j'ai pensé que la deuxième méthode serait plus propre. Mais je reviendrai à la première solution. Gardons-le totalement séparé, pas de problème du tout. Je pensais juste fort.

@alexindigo Thx pour votre r√©ponse d√©taill√©e. Laissez-moi essayer de r√©pondre √† vos questions ūüėŹ

Je ne sais pas exactement ce qui n'a pas fonctionné pour vous avec l'actif actuel

J'ai deux problèmes ici:

  1. Je ne peux pas travailler avec plusieurs domaines ni sous-domaines dans le projet actuel. (Restrictions de domaine et pas de certificat SSL générique)
  2. L'implémentation actuelle de assetPrefix sur un seul domaine nécessite plus d'ajustements dans le routage proxy, les fichiers statiques etc. Nous pourrions réduire ces ajustements en introduisant basePath . Cela ne freine rien et n'augmente pas la complexité car vous n'avez pas à fournir les basePath comme @timneutkens déjà mentionné.

l'application n'a aucune id√©e de l'endroit o√Ļ elle pourrait √™tre d√©ploy√©e

Nous avons le m√™me objectif ici bien s√Ľr! Nous d√©finissons dynamiquement des assetPrefixes dans la solution actuelle que nous avons. Il est fourni via des en-t√™tes de requ√™te par proxy.

Alors en quoi est-ce différent de la façon dont les choses fonctionnent actuellement?

Le routeur sera conscient de contextPath et réduira la quantité de code personnalisé.

chaque √ģle doit-elle savoir (et peut-√™tre dicter) son propre chemin de base de d√©ploiement? Ou l'√ģle A devrait-elle √™tre ind√©pendante de son chemin de d√©ploiement?

Ça ne doit pas être. Le développeur devrait avoir la liberté ici. Il devrait être possible de fournir dynamiquement basePath de la même manière que assetPrefix.

Alors comment l'√ģle B trouvera-t-elle l'√ģle d√©ploy√©e A, puisqu'elle ne sait que ce que l'√ģle A sait d'elle-m√™me? Ou vous devrez fournir basePath pour toute l'√ģle d√©ploy√©e √† toutes les autres √ģles? Et avec une mani√®re moderne de d√©ployer des choses, cela signifie red√©ployer toutes les √ģles lorsque vous devez en ajouter une nouvelle.

Peut-√™tre pourriez-vous √©galement ajouter le basePath dans l'exportation des routes. Je ne sais pas. Je ne dis pas que la variable basePath est importante pour chaque cas d'utilisation. Il semble que ce ne soit pas la meilleure solution pour vous. Mais c'est tout √† fait bien. Le fait est que vous pouvez toujours utiliser seulement assetPrefix et rien ne changera pour vos √ģles. Il semble que vous ayez de toute fa√ßon votre propre itin√©raire. Les liens crois√©s entre zones n'ont m√™me pas d'importance pour notre projet, nos zones sont vraiment ind√©pendantes et isol√©es les unes des autres.

Et avec une mani√®re moderne de d√©ployer des choses, cela signifie red√©ployer toutes les √ģles lorsque vous devez en ajouter une nouvelle.

Je ne vois pas pourquoi. Je peux même imaginer que certaines zones ont des basePaths et d'autres pas. Et peut-être que certaines applications utiliseront la configuration basePath même sans configuration multi-zones.

@alexindigo pourriez-vous nous fournir deux vraies URL d'√ģle, qui sont rendues par next.js pour que je puisse le voir en action? J'ai essay√© d'en trouver une, mais je n'ai pas trouv√© de page sur votre domaine avec des requ√™tes _next ūüėĄ
Toutes vos √ģles ont-elles la m√™me configuration?
"assetPrefix":"https://static.trulia-cdn.com/javascript"

@tomaswitek

Je ne peux pas travailler avec plusieurs domaines ni sous-domaines dans le projet actuel. (Restrictions de domaine et pas de certificat SSL générique)

Oh, vous n'utilisez donc pas CDN au sens classique du terme, mais comptez-vous sur les ressources extraites directement de chaque application? Je vois.

L'implémentation actuelle de assetPrefix sur un seul domaine nécessite plus d'ajustements dans le routage proxy, les fichiers statiques, etc. Nous pourrions réduire ces ajustements en introduisant basePath. Cela ne freine rien et n'augmente pas la complexité car vous n'avez pas à fournir le basePath comme @timneutkens déjà mentionné.

Btw, ce n'√©tait pas "non, n'ajoutez pas cette fonctionnalit√©" :) C'√©tait plut√īt - "Nous pouvons probablement penser √† cette approche de mani√®re plus holistique" :)

Ça ne doit pas être. Le développeur devrait avoir la liberté ici. Il devrait être possible de fournir dynamiquement basePath de la même manière que assetPrefix.

Oui. Cela ne fonctionne que lorsqu'il n'y a pas de liaison entre les √ģles. Et cela ressemble √† votre cas d'utilisation. Dans le m√™me temps, j'ai du mal √† comprendre ce qui en fait des √ģles au lieu d'√™tre simplement un tas d'applications autonomes, si elles sont 100% ind√©pendantes? :)

Peut-être pourriez-vous également ajouter le basePath dans l'exportation des routes.

Je ne vois pas comment cela pourrait être fait (facilement), car l'exportation des routes se produit au moment de la construction, et basePath étant défini au moment du déploiement, et il pourrait y avoir plus d'un déploiement du même artefact de code (étape, préprod, prod, test d'env, etc.).


Toutes vos √ģles ont-elles la m√™me configuration?
"assetPrefix": " https://static.trulia-cdn.com/javascript "

Oui, toutes les √ģles partagent leurs actifs, puisque la prochaine √©tape consiste √† hacher le contenu, ce n'est pas seulement un probl√®me, mais en fait tr√®s b√©n√©fique. (Nous extrayons les actifs construits de chaque artefact et publions sur CDN au moment du d√©ploiement).

Et de cette façon, nous n'avons que des requêtes "html régulières" à nos serveurs d'applications, c'est pourquoi je ne verrai aucun chemin "_next" sur trulia.com

Quant aux exemples d'√ģles:

Notre toute nouvelle √ģle - page Quartiers - https://www.trulia.com/n/ca/san-francisco/pacific-heights/81571 (et vous pouvez en trouver plus ici: http: //www.trulia. com / quartiers)
Cette √ģle est responsable de tous les chemins /n/* .

Et une autre √ģle est notre page de connexion - https://login.trulia.com/login - cela ressemble √† un domaine diff√©rent, mais ce n'est vraiment pas le cas, cela ressemble √† un ensemble de raisons diff√©rentes, mais techniquement, c'est le m√™me d√©ploiement. :)
Et cette √ģle g√®re des URL comme /login , /signup .

Dites moi si vous avez d'autres questions.

@alexindigo merci beaucoup pour vos exemples.
J'ai quelques questions apr√®s avoir analys√© les exemples ūüėĄ

Vous faites toujours le rendu de serveur pour chaque √ģle, mais vous essayez d'extraire autant d'actifs possibles dans un CDN commun, n'est-ce pas?

Pouvez-vous d√©crire un peu plus ce qui se passe exactement lorsque https://www.trulia.com/n/ca/san-francisco/pacific-heights/81571 est appel√©? Votre mandataire sait-il que /n repr√©sente un aper√ßu du quartier et le transmet √† la bonne √ģle? Cela affecte-t-il d'une mani√®re ou d'une autre la demande avant qu'elle n'arrive sur l'√ģle?

Utilisez-vous le routage int√©gr√© de la prochaine √† l'int√©rieur d'une √ģle ou disposez-vous d'une solution personnalis√©e?
Je voulais v√©rifier le routage √† l'int√©rieur de votre √ģle. Malheureusement, Neighborhood overview a plus ou moins simplement une navigation modale sans changer l'URL. Dans Login, il semble y avoir une solution compl√®tement personnalis√©e.

J'esp√®re que je r√©pondrai √† toutes vos questions dans ce commentaire ūüėŹ

Btw, ce n'√©tait pas "non, n'ajoutez pas cette fonctionnalit√©" :) C'√©tait plut√īt - "Nous pouvons probablement penser √† cette approche de mani√®re plus holistique" :)

Bien s√Ľr, ce serait formidable de trouver une solution o√Ļ je n'ai pas √† toucher next.js ūüėŹ

Oui. Cela ne fonctionne que lorsqu'il n'y a pas de liaison entre les √ģles. Et cela ressemble √† votre cas d'utilisation. Dans le m√™me temps, j'ai du mal √† comprendre ce qui en fait des √ģles au lieu d'√™tre simplement un tas d'applications autonomes, si elles sont 100% ind√©pendantes? :)

Je n'ai jamais √©crit ni dit que je cherchais une solution ¬ęinsulaire¬Ľ. Je viens de discuter avec @timneutkens o√Ļ j'ai d√©crit mon probl√®me et la r√©ponse de Tim √©tait essentiellement next.js ne supportant pas les chemins de base. Et apr√®s avoir cherch√© un peu sur Google, j'ai r√©alis√© que je ne suis pas le seul √† le chercher. J'ai donc pens√© que je pourrais contribuer un peu. Ensuite, Tim vous a demand√© de me faire part de vos commentaires et je suis tr√®s reconnaissant pour vos commentaires.

Je ne vois pas comment cela pourrait être fait (facilement), car l'exportation des routes se produit au moment de la construction, et basePath étant défini au moment du déploiement, et il pourrait y avoir plus d'un déploiement du même artefact de code (étape, préprod, prod, test d'env, etc.).

Eh bien, si vous voulez exporter des routes au moment de la construction et les rendre disponibles pour d'autres √ģles, le seul moyen simple est probablement de coder en dur le basePath dans la configuration. Je comprends ton point de vue. De l'autre c√īt√©, est-ce vraiment un probl√®me? Vous pouvez toujours d√©ployer l'application sur diff√©rents domaines et ports et utiliser le m√™me basePath pour chaque env.

Bonjour @tomaswitek :)

Mon exp√©rience avec la fonctionnalit√© "basePath", qu'elle est tr√®s d√©cevante dans sa complexit√©, et il est g√©n√©ralement pr√©f√©rable de mettre en Ňďuvre ce genre de choses sans se pr√©cipiter avec un probl√®me sp√©cifique,
mais en le regardant sous plusieurs angles. Similaire à la façon dont vous aborderiez la fusion profonde - décrivez plusieurs cas d'utilisation et voyez comment (et si) ils relèvent tous d'un même parapluie. Depuis avoir des fonctionnalités incompatibles entre les versions (même majeures) du framework est très ennuyeux :)

Vous pouvez toujours déployer l'application sur différents domaines et ports et utiliser le même basePath pour chaque env.

On dirait que vous seriez d'accord avec la solution o√Ļ ce "basePath" fait partie de votre code de routage, quelque chose que vous avez mentionn√© au d√©but - comme un sous-dossier dans le r√©pertoire pages (btw, cette approche signalerait aux d√©veloppeurs choisis basePath plut√īt bien). Mais la seule chose qui vous a arr√™t√© est que le chemin interne nextjs pour les actifs _next n'est pas configurable.

Et cela semble être un problème plus restreint que nous pouvons résoudre avec moins d'effets secondaires à long terme.

Et cela pourrait nous amener encore plus loin, comme si nous pouvions configurer assetPath par actif (par exemple avec une carte next.config) - cela nous permettra d'avoir des actifs partagés entre les applications, ce qui améliorera les performances, et d'autres choses.

Et il y a des relations publiques ouvertes pour cette fonctionnalité. ;) / cc @timneutkens semble qu'il est temps de revenir à ce chiot. :)

Si vous n'allez pas l'ajouter de si t√īt, pourrions-nous obtenir un exemple de server.js bas√© sur express ajout√© au readme qui fait cela et fonctionne? J'en ai essay√© quelques-uns qui ont flott√© dans ces probl√®mes mais qui n'ont pas pu les faire fonctionner. Merci.

Salut @ccarse J'ai une fourchette de travail que nous utilisons déjà en production: https://github.com/panter/next.js/pull/2
Je suis également prêt à investir du temps pour ouvrir un PR pour cette fonctionnalité.
@timneutkens @alexindigo existe-t-il un autre moyen de résoudre ce problème?
Si nous n'avons pas besoin d'une configuration basePath , pouvez-vous nous donner un exemple minimal en utilisant assetPath ?

Mon entreprise se heurte également à cela.

Nous reprenons lentement une ancienne application, section par section, et la remplaçons par Next.js.

À titre d'exemple simplifié:

| URL | App |
| --- | --- |
| example.com | héritage |
| example.com/shop | suivant |
| example.com/search | héritage |
| example.com/members | suivant |

Cela signifie que nous voulons que tout soit préfixé dans chaque application Next.js ... Pages, itinéraires, ressources, etc.

Il est également intéressant de noter que nous n'utilisons pas Now, nous ne pouvons donc pas profiter du routage now.json . Nous avons notre propre équilibreur de charge assis devant tout le domaine, puis acheminant le trafic en fonction du sous-chemin.

Nous utilisons également un serveur personnalisé (hapi), donc ce serait bien si nous pouvions également tirer parti de tout ce qui est créé ici dans un serveur personnalisé.

Peut-être qu'il y a une combinaison de paramètres now.config.json ou une utilisation de micro-proxy que nous pouvons utiliser pour accomplir la même chose, mais nous n'avons pas encore trouvé la bonne combinaison.

Nous rencontrons, je pense, le même problème avec plusieurs applications Next.js exportées statiquement et hébergées sur Now v2.

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

Comme prévu, l'application racine fonctionne très bien. Les choses tournent mal dans le second. Nous emballons actuellement next/link qui, combiné avec assetPrefix , résout la plupart du problème:

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

Cependant, cela casse prefetch car il essaie alors de rechercher des fichiers .js à la mauvaise URL:

Notre solution actuelle consiste à désactiver prefetch , ce qui n'est pas idéal.

Quel est le statut à ce sujet?

Vous recherchez √©galement une mise √† jour √† ce sujet s'il vous pla√ģt.

@timneutkens Je suis prêt à investir du temps pour ouvrir un PR pour cela si la communauté est intéressée. Nous utilisons déjà une solution (https://github.com/panter/next.js/pull/1) en production et nous en sommes très satisfaits.

Nous avons également besoin d'une solution pour cela

Nous allons bient√īt introduire une nouvelle API qui rendra cette proposition obsol√®te.

√Čgalement impact√© par cela. Besoin d'ex√©cuter le projet suivant sous un chemin de sous-r√©pertoire. Dans l'attente de la fonctionnalit√© officielle. Y a-t-il un ETA?

API

Alors comment √ßa se passe? :R√Č

Veuillez ne pas spammer le fil de discussion et utiliser la fonctionnalit√© ūüĎć de GitHub sur le probl√®me lui-m√™me.

@timneutkens Pouvez-vous fournir plus d'informations? Quelle est l'API qui rendra cela obsol√®te? Que consid√©rez-vous comme ¬ębient√īt¬Ľ? Je vous remercie.

Cela peut ne pas être exactement lié aux multi-zones mais peut aider ...

J'ai résolu quelque chose de similaire en créant un serveur personnalisé et en utilisant un middleware proxy

par exemple: @Zertz
Remarque: vous devez toujours résoudre le problème de lien - Encore une fois, j'ai résolu ce problème en créant un composant de lien et en passant le préfixe à l'application via config et si un préfixe existe, utilisez-le ou n'utilisez rien, même chose pour les images statiques.

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

La proposition que je mentionnais est # 7329

La proposition que je mentionnais est # 7329

@timneutkens
Pouvez-vous fournir plus de détails sur la façon dont le crochet proposé résoudra nos problèmes de parcours de base?
Et qu'en est-il des redirections de routeur comme Router.push('/about') , cela sera-t-il également remplacé par un hook?

Merci pour votre temps ūüėŹ

L'API du routeur changerait également, car elle aurait besoin d'un composant auquel se connecter. À ce stade, vous pouvez utiliser des chemins relatifs pour l'URL elle-même.

Une mise √† jour sur le moment o√Ļ nous pouvons obtenir une solution ou au moins une solution de contournement pour cela?

Utilisez ūüĎć sur le probl√®me initial au lieu de publier une mise √† jour.

@ MMT-LD Votre solution fonctionne en quelque sorte pour moi, mais maintenant, √† chaque clic de lien ou √©v√©nement push de routeur, la page se recharge ‚ėĻÔłŹ

J'ai essayé la solution de @Zertz et cela a parfaitement fonctionné!
Je pourrais également résoudre le problème de prefetch en copiant les fichiers de sortie dans les chemins pré-extraits.
https://github.com/fand/MDMT/blob/master/scripts/copy-preload.js

... c'est un sale tour, mais ça marche quand même

@nicholasbraun

D√©sormais, √† chaque clic de lien ou √©v√©nement push du routeur, la page se recharge ‚ėĻÔłŹ

J'ai eu ce problème mais corrigé en utilisant le paramètre `` as '' sur le lien, donc le lien pointe vers le fichier interne, mais le `` as '' est relatif au chemin
par exemple:
<Link href={"/${item.link}"} as={"./${item.link}"}>

@nicholasbraun

Votre solution fonctionne en quelque sorte pour moi, mais maintenant, √† chaque clic de lien ou √©v√©nement push de routeur, la page se recharge ‚ėĻÔłŹ

C'est un peu ce que je voulais dire. C'est de m√©moire ... mais je suis s√Ľr que vous ne pouvez pas obtenir ce dont vous avez besoin par le dessous.

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

Usage:

import NextLink from '../NextLink'

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

Bonne chance: smiley:

Comme le useLink RFC est maintenant refusé (# 7329) et que le support de basePath nous aiderait grandement, le projet Next.js est-il heureux d'accepter les PR l'implémentant? Je suis prêt à le faire.

En regardant cette implémentation par @tomaswitek , elle semble aller dans la bonne direction, surtout en sensibilisant le routeur à basePath . Y a-t-il d'autres choses non évidentes qui rendraient le support basePath difficile?

Dans l'ensemble, je pense que le design est clair, juste une seule variable de configuration:

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

Les interactions avec assetPrefix sont bien définies ici: https://github.com/zeit/next.js/issues/4998#issuecomment -414978297.


MISE √Ä JOUR : Je me demandais √©galement s'il serait possible de mettre en Ňďuvre cela en cr√©ant un routeur personnalis√© et en √©changeant le routeur par d√©faut, mais cela ne semble pas possible, Next.js code en dur son routeur, voir par exemple ici . Je suis √©galement sceptique quant au fait que ¬ęseul¬Ľ le remplacement du routeur suffirait; la fonctionnalit√© doit probablement √™tre prise en charge par Next.js dans son ensemble.

Ce problème existe depuis 2017, existe-t-il une solution de contournement? Ou une réponse officielle à notre demande basePath?

Donc, après avoir essayé de faire fonctionner cela avec la combinaison de assetPrefix et d'un composant personnalisé <Link> comme suggéré par exemple https://github.com/zeit/next.js/issues/4998#issuecomment -464345554 ou https://github.com/zeit/next.js/issues/4998#issuecomment -521189412, je ne crois pas que cela puisse être fait, malheureusement.

Définir assetPrefix était relativement simple, quelque chose comme ça dans next.config.js :

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

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

L'étape suivante est un composant personnalisé Link . La première idée, donnée par exemple dans https://github.com/zeit/next.js/issues/4998#issuecomment -464345554, est de préfixer href comme ceci (simplifié):

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

Comme indiqué par d'autres dans ce fil, cela interrompt la prélecture car les requêtes sont soudainement vers / subdir /_next/static/.../pages/ subdir /example.js - l'autre "sous-répertoire" ne devrait pas être là. Mais avec notre composant personnalisé Link , nous définissons href sur /subdir/example , donc pas étonnant que Next.js demande un bundle de la page pages/subdir/example.js .

Alors OK, la prélecture problématique ne semble pas être la fin du monde (bien que l'UX soit assez moche) mais dans notre application, les choses empirent lorsque nous utilisons le routage dynamique de Next.js 9. Pour cela, nous devons définir correctement as afin que l'évolution du composant personnalisé Link ressemble à ceci:

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

L'utilisation est:

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

qui est converti en:

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

et cela ne fonctionnait pas du tout pour moi lors du déploiement sur Now - essayer de naviguer vers https://deployment-id.now.sh/subdir/post/1 mène à 404. Je ne sais pas vraiment pourquoi, c'est peut-être aussi un problème avec @now/next builder ( MISE À JOUR : c'est à cause de https://github.com/zeit/next.js/pull/8426#issuecomment-522801831) mais en fin de compte, nous confondons le routeur de Next.js lorsque nous demandons /subdir/post/[id] component lorsqu'aucun fichier de ce type n'existe sur le disque.

Il y a un autre exemple dans ce fil, https://github.com/zeit/next.js/issues/4998#issuecomment -521189412, qui préfixe uniquement comme , pas href, comme ceci (simplifié):

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

mais cela jettera cette erreur dans le navigateur:

La <Link> as votre <Link> est incompatible avec la href . Ceci n'est pas valide.

C'est un problème signalé dans https://github.com/zeit/next.js/issues/7488.

Après tout cela, je ne pense pas qu'il y ait de solution tant que quelque chose comme basePath n'est pas pris en charge, ce que je serais heureux de vous aider.

@borekb Je suis également prêt à aider, comme je l'ai mentionné quelques fois auparavant. Toutes les solutions de contournement que j'ai vues jusqu'à présent ne résolvent qu'une partie du problème. En ce moment, nous utilisons un fork de next.js en production qui implémente basePath.

Nous allons bient√īt introduire une nouvelle API qui rendra cette proposition obsol√®te.

@tim Est-ce toujours le cas ou la nouvelle proposition d'API a-t-elle √©t√© cl√ītur√©e? https://github.com/zeit/next.js/issues/7329

Btw. demain √ßa fera exactement un an que j'ai ouvert ce num√©ro ūüéČ

Une idée relativement folle est d'avoir des pages dans quelque chose comme src/pages et de les relier ensuite à l'emplacement approprié. Par exemple:

  • Pour d√©ployer sur myapp.example.com , je ferais un lien symbolique src/pages vers pages
  • Pour d√©ployer sur example.com/myapp , je ferais un lien symbolique src/pages vers pages/myapp

En combinaison avec <Link> composant personnalis√© assetPrefix , cela pourrait fonctionner, mais je ne suis pas assez courageux pour l'essayer ūüėĄ.

Une mise à jour avec ça?

Des progrès sur le support basePath ? :)

@nicholasbraun

Désormais, à chaque clic de lien ou événement push du routeur, la page se recharge frowning_face

J'ai eu ce problème mais corrigé en utilisant le paramètre `` as '' sur le lien, donc le lien pointe vers le fichier interne, mais le `` as '' est relatif au chemin
par exemple:
<Link href={"/${item.link}"} as={"./${item.link}"}>

Tu as sauvé ma journée! :)))

je fais la même chose avec Router.push(`/route`, `${process.env.BASE_PATH}route`);

@nicholasbraun

D√©sormais, √† chaque clic de lien ou √©v√©nement push du routeur, la page se recharge ‚ėĻÔłŹ

J'ai eu ce problème mais corrigé en utilisant le paramètre `` as '' sur le lien, donc le lien pointe vers le fichier interne, mais le `` as '' est relatif au chemin
par exemple:
<Link href={"/${item.link}"} as={"./${item.link}"}>

Cette solution ne fonctionne pas avec le routage basé sur les 9 fichiers suivants. /route/[id] , ${process.env.BASE_PATH}/route${id} renvoie cette erreur

Ce commentaire explique très bien le problème.

Bien que j'aie vu quelques personnes discuter de la façon dont les solutions ici interrompent la pré-récupération. Pour nous, il y a une autre question plus importante.

Avec next9, l'utilisation d'un assetPrefix dans votre href permet à next _always_ d'effectuer une route serveur. J'ai créé un repo de reproduction dans ce numéro qui montre comment cela se passe.

Cela brise essentiellement notre cache du client Apollo, car il est recréé sur chaque route.

Je pense que l'impl√©mentation compare la page sous-jacente href sans assetPrefix, aux routes suivantes href (qui comprend un assetPrefix) - ce qui entra√ģne une route profonde.

Par exemple, si vous êtes sur href /prefix/page (la page sous-jacente est juste /page ) et votre prochaine href route est /prefix/page/[id] (car sans le préfixe, ce sera 404) c'est un itinéraire complètement différent et un itinéraire peu profond n'est pas possible.

Examiner les solutions de contournement à la minute avec les itinéraires express

Lors de l'utilisation composant avec les accessoires href qui est basePath, la prélecture ne fonctionne pas.
PLZ supporte basePath et prefetch, ce sera génial

Je pourrais vraiment l'utiliser. J'ex√©cute plusieurs applications √† partir d'une seule source de serveur et chacune d'entre elles est s√©par√©e en son propre web/appX/{next project files} . Ce serait formidable d'avoir plus de contr√īle sur basePath. J'ai trouv√© une solution de contournement pour le moment, mais ce n'est pas tr√®s joli.

l'exportation statique n√©cessite √©galement basePath ūüėä

semble r√©ussir au travail ūüĎŹ

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

C'est une très mauvaise limitation pour nous malheureusement :(

Nous avons toutes les applications derrière un proxy inverse, donc les chemins doivent être préfixés (dans l'exemple ci-dessous, il s'agit du préfixe /auction-results )

Nous utilisons d√©j√† le pr√©fixe assetPrefix - et cela permet aux applications de fonctionner correctement pour les requ√™tes c√īt√© serveur.
Par exemple: mydomain.com/auction-results/ fonctionne bien en utilisant un routage express comme celui-ci:

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

Mais lorsque nous essayons de faire une navigation c√īt√© client via next/link , par exemple:

O√Ļ /auction-results est le pr√©fixe de l'application et /national est la page dans ~pages/national

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

Cela ne fait rien (clic fant√īme)

Avoir des liens de rafra√ģchissement de page compl√®te n'est pas id√©al.

S'il y a un moyen pour que je puisse vous aider, j'aimerais beaucoup

Toute mise √† jour √† ce sujet ... l'ann√©e derni√®re √† cette √©poque, j'ai rencontr√© ce probl√®me. Maintenant, un an plus tard, je travaille sur une nouvelle application et je dois faire les m√™mes solutions de contournement que l'ann√©e derni√®re ... un peu alarmant pour une r√©action ¬ępr√™te pour la production¬Ľ. Les basepaths devraient √™tre une fonctionnalit√© de vanille.

Toute mise √† jour √† ce sujet ... l'ann√©e derni√®re √† cette √©poque, j'ai rencontr√© ce probl√®me. Maintenant, un an plus tard, je travaille sur une nouvelle application et je dois faire les m√™mes solutions de contournement que l'ann√©e derni√®re ... un peu alarmant pour une r√©action ¬ępr√™te pour la production¬Ľ. Les basepaths devraient √™tre une fonctionnalit√© de vanille.

Je ne suis pas s√Ľr de ce que vous attendez en publiant ceci.

Next.js est travaillé à plein temps par mon équipe (5 personnes), et nous travaillons sur de nombreuses fonctionnalités en même temps. Au cours de la dernière année, nous avons travaillé sur ceux-ci:

Rendre les applications Next.js (nouvelles et existantes) nettement plus petites, plus rapides et plus évolutives.

Si vous souhaitez exprimer votre ¬ęvote favorable¬Ľ pour une fonctionnalit√©, vous pouvez. utilisez la fonction ūüĎć sur le thread initial.

Je suis tout à fait d'accord que basePath devrait être une fonctionnalité intégrée. C'est déjà sur la feuille de route et j'ai même écrit un premier PR, que vous auriez pu voir en relisant sur le fil.

Voici le PR: https://github.com/zeit/next.js/pull/9872

N'h√©sitez pas √† contacter [email protected] si vous souhaitez contribuer financi√®rement √† la r√©alisation de cette fonctionnalit√©.

Quel est le statut à ce sujet? nous en dépendons vraiment: /

Le support

cf. # 9872

@martpie je l'ai d√©j√† vu, mais pour. mon cas basePath n'est pas qu'un, il peut s'agir de plusieurs basePath, car nous servons notre application via diff√©rentes "URL" et la configuration de basePath pendant la construction n'est pas une option (m√™me si elle a pour prendre en charge un tableau de chemins plut√īt qu'une seule cha√ģne)

@timneutkens Merci pour la mise à jour. Auriez-vous la gentillesse de donner une autre mise à jour. C'est pour nous une caractéristique clé et nous devons savoir ...

  1. S'agira-t-il uniquement d'une entreprise (votre référence aux ventes aux entreprises de contact a causé une certaine irritation)?

  2. Il semble √™tre sur la feuille de route, selon le PR, il ne sera plus supprim√©; pouvez-vous donner une indication s'il est s√Ľr de construire autour de cette fonctionnalit√© maintenant sans avoir de surprises dans les prochains mois, comme une version open source paralys√©e et une autre avec un support complet apr√®s avoir n√©goci√© des semaines avec des vendeurs al√©atoires sur des prix arbitraires?

Je comprends que vous travaillez sur de nombreuses fonctionnalit√©s et que chacun a ses priorit√©s, mais m√™me les plus petites configurations doivent utiliser le proxy Next, ex√©cuter plusieurs instances et lui donner un basePath d√©di√© par service. Avant de commencer √† cr√©er plusieurs services sur Next, nous devons savoir dans quelle mesure cette fonctionnalit√© sera bient√īt disponible en open source. Sinon, il serait trop risqu√© d'investir plus de temps dans Next.

Merci de votre compréhension et de vos commentaires.

FWIW, je l'ai fait fonctionner maintenant et pour d'autres conduisant par:

Mettez ceci dans votre next.config.js :

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

Ensuite, j'ai d√Ľ red√©marrer le serveur et configurer correctement mon middleware de serveur Web:

J'attrape toutes les demandes via un chemin personnalis√©, par exemple. app.use('/custom', (req, res...) => { ... et ensuite (ce qui √©tait important), je dois envoyer un proxy √† l'URL du syst√®me sur lequel Next est ex√©cut√© (donc l'adresse interne de l'orchestration de votre conteneur et √† nouveau avec le chemin respectif si vous utilisez http-proxy => par exemple ... target: 'http://next:3000/custom ), donc pas seulement l'h√īte sans le chemin personnalis√©. Si vous utilisez http-proxy-middleware vous n'en avez pas besoin.

Cela semble tout à fait correct, j'espère que cette fonctionnalité n'aura pas besoin de licence EE. Si votre équipe a besoin d'aide pour faire évoluer cette fonctionnalité, veuillez nous le faire savoir, peut-être que nous pouvons vous aider!

Edit: Je viens d'essayer cela également avec le mode de production de Next et cela semble fonctionner également.

@timneutkens Merci pour la mise à jour. Auriez-vous la gentillesse de donner une autre mise à jour. C'est pour nous une caractéristique clé et nous devons savoir ...

  1. S'agira-t-il uniquement d'une entreprise (votre référence aux ventes aux entreprises de contact a causé une certaine irritation)?
  2. Il semble √™tre sur la feuille de route, selon le PR, il ne sera plus supprim√©; pouvez-vous donner une indication s'il est s√Ľr de construire autour de cette fonctionnalit√© maintenant sans avoir de surprises dans les prochains mois, comme une version open source paralys√©e et une autre avec un support complet apr√®s avoir n√©goci√© des semaines avec des vendeurs al√©atoires sur des prix arbitraires?

Je comprends que vous travaillez sur de nombreuses fonctionnalit√©s et que chacun a ses priorit√©s, mais m√™me les plus petites configurations doivent utiliser le proxy Next, ex√©cuter plusieurs instances et lui donner un basePath d√©di√© par service. Avant de commencer √† cr√©er plusieurs services sur Next, nous devons savoir dans quelle mesure cette fonctionnalit√© sera bient√īt disponible en open source. Sinon, il serait trop risqu√© d'investir plus de temps dans Next.

Merci de votre compréhension et de vos commentaires.

@ pe-s Je pense que vous ne comprenez pas mon message.

Il n'y a pas de "version entreprise Next.js" pour le moment. Je faisais r√©f√©rence aux nombreuses occasions o√Ļ des entreprises externes ont sollicit√© des services de conseil pour d√©velopper des fonctionnalit√©s comme celle-ci dans un laps de temps plus court. Par exemple, le support des zones a √©t√© construit en collaboration avec Trulia.

Cette fonctionnalit√© est toujours en cours d'√©laboration et est sur la feuille de route. Toutes les fonctionnalit√©s en cours de travail sont open-source, comme je l'ai dit, il n'y a pas de version entreprise de Next.js. Nous avons plusieurs priorit√©s de travail √† fort impact sur la feuille de route, c'est pourquoi je me suis r√©f√©r√© √† contacter [email protected] si vous avez besoin de cette fonctionnalit√© d√®s que possible / pour discuter du support d'entreprise pour Next.js.

@timneutkens tx pour votre réponse rapide et géniale! Ensuite, on peut tout faire :)
Continuez ce bon travail!

Le support Basepath est maintenant disponible sur next@canary , il n'est plus exp√©rimental. Il sera bient√īt sur la cha√ģne stable.

J'en suis assez tard mais avez-vous envisagé d'utiliser du HTML réel

Le support Basepath est maintenant disponible sur next@canary , il n'est plus exp√©rimental. Il sera bient√īt sur la cha√ģne stable.

@timneutkens , merci pour cet ajout. Savez-vous quand le support non expérimental de basePath sera officiellement publié?

De plus, lorsque je définis le basePath, les actifs (situés dans le dossier public) sont servis à l'URL appropriée comme prévu. Mais, lorsque je les référence dans mon code, je dois ajouter manuellement le chemin de base au src, car sinon, ils seront toujours référencés à partir du chemin normal. Est-ce l'utilisation prévue de basePath? J'ai également essayé d'utiliser assetPrefix, mais cela n'a eu aucun effet sur mon code que je pourrais dire.

Exemple :

  1. en utilisant next v9.4.5-canary.24
  2. basePath mis à /alerts dans next.config.js:
const basePath = '/alerts';
module.exports = {
  basePath: basePath,
  env: {
    BASE_PATH: basePath,
  },
};
  1. actif situé dans public/images/example.png
  2. exemple d'utilisation d'actif dans le composant de réaction:
const ExampleImage = () => (
  <img src={`${process.env.BASE_PATH}/images/example.png`} />
);

Dans mes tests, cela ne met pas à jour les URL des ressources.

J'ai installé le dernier Canary:
npm install [email protected]

next.config.js

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

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

Toutes les pages et tous les liens se chargent correctement:
http: // localhost : 3000 / exemple / posts / pré-rendu
http: // localhost : 3000 / exemple / posts / ssg-ssr
http: // localhost : 3000 / exemple / posts / pré-rendu

Mais les images, favicons, etc. ne sont pas mappés:
http: // localhost : 3000 / favicon.ico 404
http: // localhost : 3000 / images / profile.jpg 404

Quelqu'un a-t-il testé cela? J'ai également essayé d'utiliser assetPrefix, mais cela n'a pas fonctionné non plus.

De plus, je suis confus, pourquoi ne pas utiliser la fonctionnalité de navigateur intégrée pour cela?
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base

Merci d'avoir examin√© cela de votre c√īt√© √©galement @kmturley . Heureux de savoir que ce n'est pas seulement moi.
@timneutkens , devrions-nous rouvrir ce problème / créer un nouveau problème pour ce bogue?

Vous devez préfixer les images manuellement. Vous pouvez obtenir le basePath en utilisant

const {basePath} = useRouter()

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

Next.js utilisera automatiquement votre préfixe dans les scripts qu'il charge, mais cela n'a aucun effet sur le dossier public;

Maintenant, je me rends compte qu'il existe plusieurs façons de lier des fichiers dans / public. par exemple <img/> <link/> ...
Est-ce pourquoi nous devons spécifier manuellement le basePath à chacun?

S'il y avait un composant comme ci-dessous disponible, je pense que cela permettrait de gagner du temps et de réduire les confusions pour beaucoup de gens?

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

Je ne pense vraiment pas que ce soit approprié, mais c'est ce que je voulais dire.

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

Pour ceux qui essaient d'utiliser const {basePath} = useRouter() qui est un Hook, pour travailler avec des classes et des composants et obtenir cette erreur:

Avertissement d'appel de crochet non valide

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

Vous pouvez le faire fonctionner en utilisant:

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)

Si vous souhaitez utiliser basePath avec markdown, il semble que vous deviez effectuer une recherche et un remplacement dans la cha√ģne:

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

Vous devez préfixer les images manuellement. Vous pouvez obtenir le basePath en utilisant

const {basePath} = useRouter()

Cette solution ne prend cependant pas en compte les images importées dans un fichier css ou scss. Avez-vous une solution pour définir le chemin de base lors de l'importation d'un actif à partir d'un fichier css ou scss?
Avec cette solution, nous devrons nous assurer que toutes les images sont import√©es soit via une balise img, un style en ligne ou dans la balise de style. Ce n'est pas id√©al, car cela divisera vos styles pour √™tre mis en Ňďuvre √† plusieurs endroits.

@peetjvv Voici une solution sous-optimale pour utiliser des actifs avec des chemins de base préfixés dans CSS. Créez, importez et ajoutez un composant <CSSVariables> dans _app.tsx , qui injecte un élément global en ligne <style> contenant des variables CSS, que vous pouvez ensuite utiliser dans toutes vos feuilles de style.

Par exemple à l'ouverture de <body> build et injecter des variables:

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

Pour obtenir ce basePath, j'utilise l' approche de withRouter .
Voici à quoi pourrait ressembler ce composant:

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);
Cette page vous a été utile?
0 / 5 - 0 notes