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:

/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

Questions connexes

YarivGilad picture YarivGilad  ·  3Commentaires

knipferrc picture knipferrc  ·  3Commentaires

sospedra picture sospedra  ·  3Commentaires

renatorib picture renatorib  ·  3Commentaires

lixiaoyan picture lixiaoyan  ·  3Commentaires