nested url routing using react-router and webpack dev server - reactjs

I'm having some issues working with react-router and webpack-dev-server to achieve nested url routing.
webpack.config.js
output: {
path: path.resolve(__dirname, 'build'),
publicPath: "/", <-- this enabled routing to /register/step2
filename: "js/bundle.js",
},
routes.js
const routes = {
childRoutes: [
{ path: '/', component: Home },
{ path: '/login', component: Login },
{ path: '/register', component: Register },
{ path: '/register/step2', component: SecondStep },
]
};
export default (<Router routes={routes} history={createBrowserHistory()} />);
When clicking around in the appliation, I can get to /register/step2 but once I hit refresh in the browser, my common.js and bundle.js is missing: 404, since it's trying to load everything from /register/ directory.
Can anyone help? Thanks.

I figured it out. 2 things that is needed to enable this.
webpack.config.js
devServer: {
historyApiFallback: true <-- this needs to be set to true
}
routes.js
const routes = {
childRoutes: [
{ path: '/', component: Home },
{ path: '/login', component: Login },
{ path: '/register', component: Register, childRoutes: [
{ path: 'step2', component: SecondStep },
] },
]
};

Make sure your webpack configuration file contains following code:
output: {
publicPath: '/'
},
devServer: {
historyApiFallback: true
}
See more in this article

If you use hashHistory instead of createBrowserHistory() it will keep the server from requesting to your current url on your server.
export default (<Router routes={routes} history={hashHistory} />);

Related

How to lazy load route with react location?

I am quite new to React, and I have a project that uses react-location
I would like to load some routes lazily only if the path is activated.
My current config is:
my base routing module
export const routes: Route[] = [
...HomeModuleRoutes, // I want this to be instantly loaded.
...LazyRoutes, // I want this to be lazy loaded.
{ path: '/', element: <Navigate to="/home" /> },
];
those 2 constants look like this :
home.routing.ts
export const routes: Route[] = [
{
path: 'home',
element: <HomeTemplate />,
children: [
{
path: '/',
element: <HomePage />,
},
],
},
];
lazy.routing.ts
export const LazyRoutes: Route[] = [
{
path: 'test',
element: <LazyTemplate />,
children: [
{
path: '/',
element: <LazyList />,
},
{
path: 'add',
element: <LazyAdd />,
},
{
path: 'detail',
element: <LazyDetail />,
},
],
},
];
I don't quite see documentation or an example on this, is it just wrapping the component with <Suspense>?
You should import your component with React.lazy like:
const HomeTemplate = React.lazy(() => import("./HomeTemplate "));
check this example for react-router v6 lazy loading

AWS-S3 and AWS-CloudFront With React routes, multi application

I have the following scenario.
S3 bucket and several directories, one directory for each react application
All the paths of each react application start with the name of the directory hosted in the s3 bucket
For example:
S3 Directories
|--/
|--/first-app/
|--/second-app/
React routes of first-app
const routes = [
{
path: '/',
component: Empty,
exact: true,
},
{
path: '/first-app',
component: Layout,
routes: [
{ path: '/first-app/create', component: CreateCommponent},
{ path: '/first-app/login', component: Login },
{ path: '/first-app/logout', component: Logout },
],
},
]
React routes of second-app
const routes = [
{
path: '/',
component: Empty,
exact: true,
},
{
path: '/second-app',
component: Layout,
routes: [
{ path: '/second-app/create', component: OtherComponent},
{ path: '/second-app/login', component: Login },
{ path: '/second-app/logout', component: Logout },
],
},
]
How do I make cloudFront serve each application in each directory independently but under the same domain?
https://my.domain.com/first-app >> serve react application middle index.html of first-app
https://my.domain.com/second-app>> serve react application middle index.html of second-app
You can do this using Lambda#Edge in order to manipulate the request parameters before sending the request to the bucket. here is a similar example: here

[React Webpack]: Module not found: Error: Can't resolve 'src/views/UserList' in 'C:\Users\....'

I have a create-react-app application working 100% , I want to integrate webpack4 to deploy my app but after configuring webpack when I 'npm dev run' I get those errors on every lazy import line:
Module not found: Error: Can't resolve 'src/views/UserList' in 'C:....'
My webpack.config.js :
// webpack.config.js
const path = require( 'path' );
const HtmlWebPackPlugin = require( 'html-webpack-plugin' );
const webpack=require('webpack');
module.exports = {
context: __dirname,
entry: {
bundle: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
},
devServer: {
historyApiFallback: true
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.((c|sa|sc)ss)$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|j?g|svg|gif)?$/,
use: 'file-loader',
include: path.resolve(__dirname, 'src')
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: path.resolve( __dirname, 'public/index.html' ),
filename: 'index.html'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
],
};
My routes.js :
/* eslint-disable react/no-multi-comp */
/* eslint-disable react/display-name */
import React, { lazy } from 'react';
import { Redirect } from 'react-router-dom';
import AuthLayout from './layouts/Auth';
import ErrorLayout from './layouts/Error';
import DashboardLayout from './layouts/Dashboard';
import DashboardView from './views/Dashboard';
export default [
{
path: '/',
exact: true,
component: () => <Redirect to="/dashboard" />
},
{
path: '/auth',
component: AuthLayout,
routes: [
{
path: '/auth/login',
exact: true,
component: lazy(() => import('src/views/Login'))
},
{
component: () => <Redirect to="/errors/error-404" />
}
]
},
{
path: '/errors',
component: ErrorLayout,
routes: [
{
path: '/errors/error-403',
exact: true,
component: lazy(() => import('src/views/Error403'))
},
{
path: '/errors/error-404',
exact: true,
component: lazy(() => import('src/views/Error404'))
},
{
path: '/errors/error-500',
exact: true,
component: lazy(() => import('src/views/Error500'))
},
{
component: () => <Redirect to="/errors/error-404" />
}
]
},
{
route: '*',
component: DashboardLayout,
routes: [
{
path: '/dashboard',
exact: true,
component: DashboardView
},
{
path: '/users',
exact: true,
component: lazy(() => import('src/views/UserList'))
},
{
path: '/brands',
exact: true,
component: lazy(() => import('src/views/BrandList'))
},
{
path: '/brands/new',
exact: true,
component: lazy(() => import('src/views/BrandForm/index'))
},
{
path: '/brands/:id',
exact: true,
component: lazy(() => import('src/views/BrandDetails'))
},
{
path: '/users/new',
exact: true,
component: lazy(() => import('src/views/AddUser'))
},
{
path: '/users/:id',
exact: true,
component: lazy(() => import('src/views/UserDetails'))
},
{
path: '/users/:id/:tab',
exact: true,
component: lazy(() => import('src/views/UserDetails'))
},
{
path: '/users/:id/:tab/:itemId',
exact: true,
component: lazy(() => import('src/views/ItemDetails'))
},
{
path: '/service-partners/providers',
exact: true,
component: lazy(() => import('src/views/ProviderList'))
},
{
path: '/service-partners/providers/:id',
exact: true,
component: lazy(() => import('src/views/ProviderDetails'))
},
{
path: '/service-partners/services',
exact: true,
component: lazy(() => import('src/views/ServiceList'))
},
{
path: '/service-partners/services/:id',
exact: true,
component: lazy(() => import('src/views/ServiceDetails'))
},
{
path: '/service-partners/categories',
exact: true,
component: lazy(() => import('src/views/ServiceCategoryList'))
},
{
path: '/feeds',
exact: true,
component: lazy(() => import('src/views/PersonalFeedList'))
},
{
path: '/feeds/:id',
exact: true,
component: lazy(() => import('src/views/PersonalFeedDetails'))
},
{
component: () => <Redirect to="/errors/error-404" />
}
]
}
];
App Structure:
public/
index.html
src/
views/
components/
index.js
routes.js
Any solutions please..
By default webpack only searches node_modules if you don't give it a relative/absoute path, so you need to add this to your webpack.config.js to tell it to search in project root directory aswell :
module.exports = {
//...
resolve: {
modules: ['.', 'node_modules']
}
};
More info here. Note that order here matters, it first searches in project root directory then node_modules, you can change it.

why redirect to is not working in angular routing?

here is my routerModule i want to redirect the blank (first page) should be the first child of the Maincompoenent. when is try it in browser it showing nothing but when i try /web it shows me that page.
export const rootRouterConfig: Routes = [
{ path: '', redirectTo: '/web', pathMatch: 'full' },
{
path : '',
component : MainComponent,
children: [
{
path : 'web',
loadChildren: './shop/shop.module#ShopModule'
},
{
path: 'pages',
loadChildren: './pages/pages.module#PagesModule'
},
{
path: 'blog',
loadChildren: './blog/blog.module#BlogModule'
}
]
},
{
path: '**',
redirectTo: 'web'
}
];
here is shop module , i want redirect to first route and use as a main page of site
const routes: Routes = [
{
path: '',
component: HomeFiveComponent,
},
{
path: 'left-sidebar/collection/:category',
component: CollectionLeftSidebarComponent
},
{
path: 'right-sidebar/collection/:category',
component: CollectionRightSidebarComponent
},
{
path: 'no-sidebar/collection/:category',
component: CollectionNoSidebarComponent
},
{
path: 'left-sidebar/product/:id',
component: ProductLeftSidebarComponent
},
{
path: 'right-sidebar/product/:id',
component: ProductRightSidebarComponent
},
{
path: 'no-sidebar/product/:id',
component: ProductNoSidebarComponent
},
{
path: 'col-left/product/:id',
component: ProductColLeftComponent
},
{
path: 'col-right/product/:id',
component: ProductColRightComponent
},
{
path: 'column/product/:id',
component: ProductColumnComponent
},
{
path: 'accordian/product/:id',
component: ProductAccordianComponent
},
{
path: 'left-image/product/:id',
component: ProductLeftImageComponent
},
{
path: 'right-image/product/:id',
component: ProductRightImageComponent
},
{
path: 'vertical/product/:id',
component: ProductVerticalTabComponent
},
{
path: 'search',
component: SearchComponent
},
{
path: 'wishlist',
component: WishlistComponent
},
{
path: 'compare',
component: ProductCompareComponent
},
{
path: 'cart',
component: CartComponent
},
{
path: 'checkout',
component: CheckoutComponent
},
{
path: 'checkout/success',
component: SuccessComponent
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ShopRoutingModule { }
this might be an old question but you have a '/' in your redirect url you should remove that and it would work.
{ path: '', redirectTo: 'web', pathMatch: 'full' },
for others that may stumble on this question like me always make sure that the redirect is on top.
I think this you need to specify where to redirect it in 'children'. Here you find the redirect snippets. This may help you.

Angular 2 routing with culture

I need to add culture before every route for application. I am still using RC4.
How can I modify my current routes to achieve the desired result?
export const routes: RouterConfig = [
...ItemRoutes,
...LibraryRoutes,
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: '**', redirectTo: 'dashboard' }
];
Now after authentication, my redirect link is
localhost/en
I have the application config with the current culture when App component is loaded, ultimately I would like to set the language there and have it as a prefix route.
With my current setup, I will get redirected to dashboard.
How can I add the culture parameter as the first parameter to all the routes?
Is there something I should know regarding the routing and culture/language settings? Whats the best way to set the language on the front end side?
Below solution is not exactly adding a prefix to all routes, but it may help,
export const routes: RouterConfig = [
...ItemRoutes,
...LibraryRoutes,
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: '**', redirectTo: 'dashboard' }
]
export const localeRoutes: RouterConfig = [
{ path: '', redirectTo: 'en' , pathMatch: 'full'},
{ path: 'en', children: routes },
{ path: 'fr', children: routes }
]
You have to make sure all your routes are configured from here only, If Routes are defined in the imported module, they will be treated separately. However this approach will work with Lazy loaded routes if configured here.
Hope this helps!!

Resources