NextJS - Issue routing between Multi Zones - next.js

I have Multi Zone setup between two applications:
Home App
Blog App
When I am on a page within the Blog app and try to link back to the Home app, either using Link or router.push("/"), it takes me to the base path of the Blog app.
Inside the next.config.js, I've set it up as following:
/** #type {import('next').NextConfig} */
const withTM = require('next-transpile-modules')(['#workflow/shared-core']);
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
experimental: {
externalDir: true
},
basePath: '/blog',
rewrites: async () => {
return [
{
source: "/",
destination: "http://localhost:5001",
basePath: false
}
]
}
}
module.exports = withTM(nextConfig)
My understanding was that when a rewrite is setup with the basePath set to false, it would fallback completely the URL in the destination property.
Any ideas?

Unfortunately you can't use next router to jump between multi zones. Each new multi zone is basically a new next app with its own instance of router, so for your blog app the base route would be /blog/. To jump to the other app you will have to use either an <a href="#"> tag with href attribute or manually change the window.location.href = .... pointing to the route you want. For example if base path is '/account' and you want to navigate to that from '/blog', you will have to do window.location.href = '/account'.

Related

Next.js custom url name (url re-writing)

I have a project in Next.js where I have 2 different users: admin and employee.
I have set up 2 folders inside pages; /admin and /users. Each folder/users has its own subpages. for example /admin/dashboard and /employee/dashboard etc
I am trying to obfuscate the role, so that instead of displaying the url: "/admin/dashboard", if the user is an admin, I would like the url to display "/dashboard" which actually gets the "admin/dashboard" page.
I have tried next.js.config and that works perfectly when I do a full page refresh on /dashboard
module.exports = {
async rewrites() {
return [
{
source: '/:path*',
destination: '/admin/:path*',
},
]
},
}
However, if I set my link to "/dashboard", it does not work. I have tried middleware, and I can get "/" to redirect to "/admin", but I want the opposite. ie if I go to "/" it will use the "/admin/" page, but cannot work out how to achieve my goal (if it is possible !)
if (request.nextUrl.pathname.startsWith('/dashboard')) {
url.pathname = "/admin/dashboard";
return NextResponse.redirect(url);
}
Any help greatly appreciated
You can use as from router.push and the Link component.
For example:
import Link from 'next/link';
import { useRouter } from 'next/router';
export default function Example() {
const router = useRouter();
const handleEmployeeClick = () => {
// will show page from /employee/dashboard but show as /dashboard
router.push('/employee/dashboard', '/dashboard');
};
return (
<>
<button onClick={handleEmployeeClick}>
Go to dashboard (employee only)
</button>
<Link href="/admin/dashboard" as="/dashboard">
Go to dashboard (admin only)
</Link>
</>
);
}

NextJS config: Move redirects to it's own file

I'm moving from a wordpress site to a new, shiny nextjs site. However, I have hundreds of redirects and I don't want to put them all in the nextjs config file. I like things clean and tidy. I searched around for awhile and didn't find any results on how to do this. Any suggestions?
You need to import it via require, tho remember that u also need to export it as module, so ex.:
const redirectsArray = [
{ source: "/about", destination: "/", permanent: true },
];
async function redirects() {
return redirectsArray;
}
module.exports = {
redirects,
};
and then
const { redirects } = require("./redirects.js");
I got it working while module exporting it as an array instead of an object in the redirects.js
module.exports = redirects
And then add it to the next.config.js like so
async redirects() {
return redirects
}

How to rewrite homepage based on hostname

I'd like to show two different pages at '/' depending on the hostname (the value for req.hostname). This is because I have a subdomain xxx.mydomain.com that needs to show just one page at the root URL. The idea is to have a CNAME for the subdomain that points to the same server as www. I'm using next version 11.1.2 .
My homepage (/pages/index.js) uses getStaticProps to get data for the page with a revalidate interval of 2 seconds. The page on the production branch works great currently without any rewriting.
I tried using the rewrites option in next.config.js and was able to use this to rewrite all other routes, but rewriting with source: '/' did not do anything. If the source was any other page it worked perfectly. This is pretty much what the next.config.js file looked liken when I tried the rewrite:
const withFonts = require('next-fonts');
const withTM = require('next-transpile-modules')(['#cal-frontends/shared']);
require('dotenv').config({ path: '../../.env' });
module.exports = withTM(withFonts({
async rewrites() {
return [
{
source: '/', // this one still showed the homepage at '/'
destination: '/mission',
},
{
source: '/foo', // this one showed the contact page at '/foo'
destination: '/contact',
},
]
},
webpack(config, options) {
return config;
},
}));
I tried many strategies, including this kind of configuration in server.js
server.get('/',function(req,res){
console.log('trying to redirect', )
console.log('req.hostname', req.hostname)
if (req.hostname === 'mission.mydomain.com') {
console.log('this should show mission', )
return app.render(req, res, '/mission', {})
} else {
handle(req, res);
}
});
This unfortunately did not seem to override the static caching that happens with getStaticProps – you will only see the correct page for the hostname if you load and then reload after it revalidates.
Is there an elegant way to do this?

Exposing Storybook via NextJS route

I have a NextJS app and am using Storybook to develop my components.
After looking through all the NextJS routing documentation, I can't find a way to route to my storybook from within NextJS. Only access pages within the /pages directory.
What I would like to do it to have my StoryBook available at /styleguide from within my Next app thought all environments.
Is someone able to help?
Short answer: No, you can not do that.
But you can always redirect the url /styleguide to another domain where Storybook is running, for example styleguide.example.com. Here, an example based on the official documentation:
// next.config.js
module.exports = {
async redirects() {
return [
{
source: '/styleguide',
destination: 'https://styleguide.example.com',
permanent: true,
},
]
},
}
If your URL's would have any parameters for it's origin that you would want to append to the redirects destination, NextJS provides a feature to do just that.
// next.config.js
module.exports = {
async redirects() {
return [
{
source: '/styleguide/:pageId/:slug',
destination: 'https://styleguide.example.com/:pageId/:slug',
permanent: true,
},
]
},
}

Redirect to Firebase Hosting custom domain

I have setup a custom domain with Firebase Hosting (eg. myapp.domain.com).
How can one redirect (or turn off) the default Firebase Hosting URL (eg. myapp.firebaseapp.com) so that the app is only accessible from the custom domain?
You cannot turn off the subdomain. Your app will always be available on https://myapp.firebaseapp.com and whatever custom domain you've set up.
To redirect people, you can add a canonical link to your HTML:
<link rel="canonical" href="http://myapp.domain.com/" />
Read more about that in Specify your canonical on the Google Webmaster Central Blog.
You could use Firebase Functions.
Free for 125K invocations/month - https://firebase.google.com/pricing
An example using Express middleware:
// functions/index.js
const functions = require('firebase-functions');
const express = require('express');
const url = require('url');
const app = express();
// Allowed domains
let domains = ['localhost:5000', 'example.com'];
// Base URL to redirect
let baseurl = 'https://example.com/';
// Redirect middleware
app.use((req, res, next) => {
if (!domains.includes(req.headers['x-forwarded-host'])) {
return res.status(301).redirect(url.resolve(baseurl, req.path.replace(/^\/+/, "")));
}
return next();
});
// Dynamically route static html files
app.get('/', (req, res) => {
return res.sendFile('index.html', { root: './html' });
});
// ...
// 404 middleware
app.use((req, res) => {
return res.status(404).sendFile('404.html', { root: './html' });
});
// Export redirect function
exports.redirectFunc = functions.https.onRequest(app);
The exported function name must be added to rewrites in firebase.json e.g.:
{
"hosting": {
"public": "public",
"rewrites": [
{
"source": "**",
"function": "redirectFunc"
}
]
}
}
In addition to specifying canonical link as mentioned in Frank van Puffelen's answer. We can also add front end JavaScript code to do the actual redirect like this without disclosing default url.
if (location.hostname.indexOf('custom.url') === -1) {
location.replace("https://custom.url");
}

Resources