-
Notifications
You must be signed in to change notification settings - Fork 27k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: Basepath support #4998
Comments
cc @jxnblk |
cc @alexindigo @DullReferenceException Would love to have your feedback 👍 |
After playing with the code I realized that it would be much easier to split
We can still keep the For the asset part is really ok to provide these two variables together. As a sideffect this also leads to less code changes. |
In my opinion, they should be separate, the reason for this is that it's not breaking and more flexible to keep |
Is |
The way it should work is:
|
cc @alexindigo @DullReferenceException @3rd-Eden Could you give feedback on the above proposal: #4998 (comment) |
@tomaswitek Not sure what exactly didn't work for you with current |
And in general, we're using multiple zones (we call them islands) on the same domain and "basePathing" each island never came to our minds, since it'd complicate interoperability between the islands. Let me elaborate on tat a little bit more: So we have two islands
When we add deployment specific basePath, we automatically increase complexity of the whole system – should each island know (and maybe dictate) it's own deployment basePath? Then how is it different from the way thing work currently? Or should island A be agnostic of it's deployment path? Then how island B will find deployed island A, since it only knows what island A knows about itself? Or you'd have to supply basePath for all the deployed island to all other islands? And with modern way off deploying things, it means redeploying all the islands when you need to add new one. Or how you envisioned that part of the story? Thank you. |
^ it was written before morning coffee, so please let me know if you need more coherent explanation for any parts of it. :) |
First of all thank you guys that you took the time for reviewing my issue. @timneutkens Yes @alexindigo Thx for your detailed answer. Let me try to answer your questions 😏
I have two problems here:
We have the same goal here of course! We are defining assetPrefixes dynamically in the current solution we have. It is provided via request headers by proxy.
Router will be aware of contextPath and will reduce the amount of custom code.
It doesn't have to be. The developer should have freedom here. It should be possible to provide basePath dynamically the same way as assetPrefix.
Maybe you could also add the basePath into the routes export. I don't know. I am not saying that the basePath variable is important for every use case. It looks like it's not the best solution for you. But that's totally fine. The thing is that you can still use just
I don't see a reason why. I can even imagine that some zones have basePaths and some not. And maybe some apps will use the basePath config even without multi zones setup. |
@alexindigo could you pls provide us with a two real island urls, which are rendered by next.js so I could see it in action? I tried to find one, but could't find a page on your domain with |
Oh, so you don't use CDN in the classical sense, but rely on assets being fetched from each app directly? I see.
Btw, it wasn't "no, don't add that feature" :) It was more like – "Probably we can think about this approach more holistically" :)
Yes. It only works though when there is no linking between the islands. And sounds like this is your use case. In the same time, I'm having hard time understanding what makes them islands instead of just being a bunch of standalone applications then, if they're 100% independent? :)
I don't se how it could be done (easily), since routes export happens at build time, and basePath being defined at deployment time, and there could be more than one deployment of the same code artifact (stage, preprod, prod, testing env, etc).
Yes, all islands share their assets, since next does content hashing, it's not only non-issue, but actually very beneficial. (We extract built assets from each artifact and publish on CDN at deployment time). And that way we have only "regular html" requests to our app servers, this is why I won't see any "_next" paths on trulia.com As for the islands examples: Our fresh brand new island – Neighborhoods page – https://www.trulia.com/n/ca/san-francisco/pacific-heights/81571 (and you can find more of them here: http://www.trulia.com/neighborhoods) And another island is our login page – https://login.trulia.com/login – it looks like different domain, but it's really not, it looks that way for different set of reasons, but technically it's the same deployment. :) Let me know if you have more questions. |
@alexindigo thank you very much for your examples. You still do server rendering for every island, but you try to extract as much possibles assets into a common CDN right? Can you pls describe a little bit more what exactly happens when https://www.trulia.com/n/ca/san-francisco/pacific-heights/81571 is called? Does your proxy know that Do you use built-in routing from next inside an island or do you have a custom solution? |
I hope I'll answer all your questions in this comment 😏
Sure, it would be great to find a solution where I don't have to touch next.js 😏
I never wrote nor said that I search for an "island" solution. I just had a chat with @timneutkens where I described my problem and Tim's answer was basically
Well if you want to export routes at build time and make them available for other islands then the only straightforward way is probably to hardcode the basePath in the config. I get your point. On the other side, is that really such a problem? You could still deploy the app to different domains and ports and you could use the same basePath for each env. |
Good morning @tomaswitek :) My experience with the "basePath" functionality, that it very deceiving in it's complexity, and it's usually better to implement that kind of things without rushing into it with one specific problem,
Sounds like you'd be ok with the solution where that "basePath" is part of your routing code, something that you mentioned in the beginning – like subfolder inside And that sounds like more narrow problem we can solve with less long term side effects. And it could bring us even further, like if we can configure assetPath per asset (e.g. with next.config map of some sort) – it will allow us to have shared assets between the apps, which will improve performance, and other things. And there is open PR for that feature. ;) /cc @timneutkens sounds like it's time to get back to that puppy. :) |
If you're not going to add this any time soon, could we get an example express based server.js added to the readme that does this and works? I've tried a few that have been floating around in these issues but couldn't get them to work. Thanks. |
Hi @ccarse I have a working fork which we use in production already: panter#2 |
My company is also coming up against this. We're slowly taking over a legacy app, section by section, and replacing it with Next.js. As a simplified example:
That means we want everything to be prefixed within each Next.js app... Pages, routes, assets, etc. It's also worth noting that we're not using Now, so we cannot take advantage of We're also using a custom server (hapi), so it'd be nice if we could leverage whatever is create here within a custom server too. Maybe there's some combination of |
We're running into, I think, the same problem with multiple statically exported Next.js apps hosted on Now v2.
As expected, the root app works just fine. Things go awry in the second one though. We're currently wrapping
However, this breaks
Our current workaround is to disable |
I'm not sure what you're expecting by posting this. Next.js is being worked on full-time by my team (5 people), and we're working on many features at the same time. In the past year we've worked on these:
Effectively making Next.js applications (new and existing) significantly smaller, faster and more scalable. If you want to voice your "upvote" for a feature you can. use the 👍 feature on the initial thread. I definitely agree Here's the PR: #9872 Feel free to reach out to [email protected] if you want to financially contribute to making this feature happen. |
which is known not to work vercel/next.js#4998
What is the Status on this? we are really depending on this :/ |
@Sletheren basePath support is experimental right now, use at your owm risks. cf. #9872 |
@martpie I already saw it, but for. my case |
@timneutkens Thanks for the update. Would you be so kind to give another update. This is for us a key feature and we need to know...
I understand that you guys work on many features and everyone has his/her priorities but even smaller setups need to proxy Next, run multiple instances and give it a dedicated Thanks for your understanding and looking fwd to your feedback. |
FWIW, I got it now working and for others driving by: Put this in your
Then, I needed to restart the server and to setup my web server middleware properly: I catch all requests via a custom path, eg. It feels quite ok, I hope that this feature won't need any EE license. If your team needs any help to get this feature mature, pls let us know, maybe we can help! Edit: Just tried this also in with Next's production mode and it seems to work as well. |
@pe-s I think you're misunderstanding my post. There is no "enterprise Next.js version" as of now. I was referring to the numerous occasions where external companies reached out to pay for consulting to build out features like this one in a shorter timespan. E.g. zones support was built in collaboration with Trulia. This feature is being worked on still and is on the roadmap. All features being worked on are open-source, like I said there's no enterprise version of Next.js. We have multiple priorities of high-impact work on the roadmap though hence why I referred to contacting [email protected] if you need this feature as soon as possible / to discuss enterprise support for Next.js. |
@timneutkens tx for your quick response and great! Then, we can go all in :) |
Basepath support is out on |
I'm pretty late to this but did you consider using actual HTML |
@timneutkens, thank you for this addition. Do you know when the non-experimental basePath support will be officially released? Also, when I set the basePath the assets (located in the public folder) gets served to the appropriate url as expected. But, when I reference them in my code then I have to add the base path to the src manually, because otherwise they will still be referenced from the normal path. Is this the expected use of basePath? I have also tried using assetPrefix, but it didn't have any effect to my code that I could tell. Example:
const basePath = '/alerts';
module.exports = {
basePath: basePath,
env: {
BASE_PATH: basePath,
},
};
const ExampleImage = () => (
<img src={`${process.env.BASE_PATH}/images/example.png`} />
); |
In my tests, it's not updating assets urls. I installed the latest canary: next.config.js
All pages and links load correctly: But images, favicons etc are not mapped: Did anyone test this? I also tried using assetPrefix, but that didn't work either. In addition i'm confused, why not use the built in browser functionality for this? |
Thank you for looking into this on your end as well @kmturley . Glad to know it's not just me. |
You have to prefix images manually. You can get the basePath using const {basePath} = useRouter() |
https://nextjs.org/docs/api-reference/next.config.js/cdn-support-with-asset-prefix
Now, I come to realize there are multiple ways to link to files in /public. e.g. If there was a component like below available, I think it would save time and reduce confusions for a lot of people? <WithinBasePath>
{/* automatically fixes the path with basePath */}
<img src="/logo.png" />
</WithinBasePath> |
I really don't think this is appropriate, but this is what I meant. // 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 |
For those trying use
https://reactjs.org/warnings/invalid-hook-call-warning.html You can get it working using:
|
If you want to use basePath with markdown, it looks like you need to do a find and replace in the string:
|
This solution doesn't take images imported in a css or scss file into account though. Do you have a solution for how to set the base path when importing an asset from within a css or scss file? |
@peetjvv Here's a suboptimal solution for using assets with prefixed basePaths in CSS. Create, import and add a E.g. at the opening of
To get that basePath I use the @kmturley's approach using
|
This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Feature request
Is your feature request related to a problem? Please describe.
Multi zones is a great feature which allows to run multiple next.js apps on the same domain, but it doesn't allow to define a basepath which will be accepted by all parts of next.js. Since we are not able to namespace apps right now it is not possible to have the same names for pages in various apps.
Describe the solution you'd like
I want to be able to configure a
basepath
in the next.config.js file. Thanks to this configuration all parts of next.js (Router, Link, Static assets etc.) will be aware of the basepath and will automatically generate and match to the correct paths.Describe alternatives you've considered
One alternative is to nest all desired pages into a folder which matches the basepath. This solves just one small issue with routing and is quite ugly because most of the my basepaths are not one level paths.
The second alterantive is to configure a proxy in a way where the basepath is automatically removed before the request arrives into a next.js app and also implement a custom Link component which automatically adds basepath to all links. I just don't want to maintain custom fork of next.js. It doesn't make sense in my opinion.
Additional context
The
assetPrefix
solution allows us to define a different prefix for each app. But as fair as I know it works only with different hosts.with-zones example
If I add a basepath to it everything fails
In my opinion we should split it into 2 variables:
Related issues
assetPrefix
for global prefixing #4146The text was updated successfully, but these errors were encountered: