React Routing Issue (Without create-react-app) - javascript

I have created react app without using CRA command and also installed react router dom v6.
When I have 1 path in url, I don't get any error (like http://localhost:3000 /firstPath ). But, when I have 2 paths in URL (like http://localhost:3000 /firstPath/secondPath ), I get 404 firstPath/main.js not found error. It is searching for main.js inside a folder called firstPath.
In the following code, the index, add and test URLs are working. But the edit URL is not working.
Console Log Image
Sources Tab Image
rootRouter.js code: [BrowserRouter tag is given in the parent file]
import React from "react";
import { Route, Routes } from "react-router-dom";
import Home from "../views/Home";
import Add from "../views/Add";
import Edit from "../views/Edit";
const rootRouter = () => {
return (
<Routes>
<Route exact path="/" element={<Home />} />
<Route path="add" element={<Add />} />
<Route path="edit/:id" element={<Edit />} />
<Route path="test" element={<div>test</div>} />
</Routes>
);
};
export default rootRouter;
webpack.config.js code:
const path = require("path");
const port = process.env.PORT || 3000;
module.exports = {
mode: "development",
entry: "./index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
target: "web",
devServer: {
host: "localhost",
port: port,
static: ["./public"],
open: true,
hot: true,
liveReload: true,
historyApiFallback: true,
},
resolve: {
extensions: [".js", ".jsx", ".json", ".ts", ".tsx"],
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.png?$/,
use: ["file-loader"],
},
],
},
};

Related

Problem with filename and path resolve in Webpack with React

I have following webpack config settings for .css, .js files:
const cssLoaders = (extra) => {
const loaders = [{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: isDev,
reloadAll: true
}
},
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: {
localIdentName: '[path][name]__[local]--[hash:base64:5]',
},
}
},
];
if (extra) {
loaders.push(extra);
}
return loaders;
};
const filename = ext => isDev ? `[name].${ext}` : `[name].[contenthash].${ext}`;
.
.
.
module.exports = {
context: path.resolve(__dirname, 'src'),
mode: 'development',
entry: {
main: ['#babel/polyfill', './index.jsx']
},
output: {
filename: filename('js'),
path: path.resolve(__dirname, 'dist')
},
.
.
.
plugins: [
new MiniCssExtractPlugin({
filename: filename('css'),
})
],
.
.
.
module: {
rules: [
{
test: /\.css$/,
use: cssLoaders()
},
{
test: /\.less$/,
use: cssLoaders('less-loader')
},
{
test: /\.s[ac]ss$/,
use: cssLoaders('sass-loader')
},
.
.
.
The problem is when I add new page (react component) with a new path (/car/model/:id) I see an error that webserver cannot find files:
Can't find http://localhost:4200/cars/model/main.css
Can't find http://localhost:4200/cars/model/main.js
I also have root Application component with following routing code:
class Application extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className={Styles.container}>
<Switch>
<Route exact path="/" component={Catalogue} />
<Route exact path="/cars/model/:id" component={CarModel} />
<Route path="*" component={NotFound} />
</Switch>
</div>
);
}
}
Everything is ok for the main page, it renders well.
<Route exact path="/" component={Catalogue} />
What should I change to fix it for <Route exact path="/cars/model/:id" component={CarModel} /> ?

React-router cannot get component when manually modifying url or page refresh [duplicate]

I have the following webpack config file:
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'src/client/public');
var APP_DIR = path.resolve(__dirname, 'src/client/app');
var config = {
entry: [
APP_DIR + '/config/routes.jsx',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8080'
],
output: {
publicPath: 'http://localhost:8080/src/client/public/'
},
module : {
loaders : [
{
test: /\.jsx?$/,
loader: 'babel-loader',
include: APP_DIR,
exclude: /node_modules/,
query: {
presets: ['es2015']
}
},
{
test: /\.scss$/,
loaders: [ 'style', 'css', 'sass' ]
},
{
test: /\.json$/,
loader: "json-loader"
}
]
}
};
module.exports = config;
all I am trying to do is run my app on localhost, however when I hit: "http://localhost:8080/src/client/home" (as per my routes.jsx and after running webpack-dev-server)
import React from 'react';
import { Route, Router, browserHistory } from 'react-router';
import ReactDOM from 'react-dom';
import Wrapper from './../components/wrapper.jsx';
import Home from './../components/home.jsx';
import Projects from './../components/projects.jsx';
import SingleProject from './../components/projectContent/singleProject.jsx';
import About from './../components/aboutUs.jsx'
ReactDOM.render((
<Router history={browserHistory} >
<Route path="/" component={Wrapper} >
<Route path="home" component={Home} />
<Route path="projects" component={Projects} />
<Route path="projects/:id" component={SingleProject} />
<Route path="about" component={About} />
</Route>
</Router>
), document.getElementById('app'));
I get
"Cannot GET /src/client/home".
First thing you have mentioned in your routes as the home component to have path /home. So you need to visit http://localhost:8080/home. Also if you try to access this url directly, it will give you this error since you are using browserHistory. If you want you can use hashHistory or HashRouter in react-router v4, in which case you will need to visit http://localhost:8080/#/home. If you want to continue using browserHistory or BrowserRouter as in react-router v4, then you will need to add historyApiFallback: true in you webpack
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'src/client/public');
var APP_DIR = path.resolve(__dirname, 'src/client/app');
var config = {
entry: [
APP_DIR + '/config/routes.jsx',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8080'
],
output: {
publicPath: 'http://localhost:8080/src/client/public/'
},
devServer: {
historyApiFallback: true
},
module : {
loaders : [
{
test: /\.jsx?$/,
loader: 'babel-loader',
include: APP_DIR,
exclude: /node_modules/,
query: {
presets: ['es2015']
}
},
{
test: /\.scss$/,
loaders: [ 'style', 'css', 'sass' ]
},
{
test: /\.json$/,
loader: "json-loader"
}
]
}
};
module.exports = config;
You need to add this in your webpack settings:
devServer: {
historyApiFallback: true,
},
And start your server like this:
webpack-dev-server --config webpack.config.js
Because you want React-Route to handle the route instead of your server. So no matter what the url is it should goes to index.html.

Fail to improve site first time loading performance

I am creating a site using HTML5, JavaScript and React.
I am using Google Chrome Lighthouse to check the performance of the site first load.
This is the Lighthouse Runtime environment:
User agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Device Emulation Nexus 5X: Enabled
Network Throttling 562.5ms RTT, 1.4Mbps down, 0.7Mbps up: Enabled
CPU Throttling 4x slowdown: Enabled
After many iteration and fixes these are the scores I have on Lighthouse so far:
Performance 57
Progressive Web App 100
Accessibility 100
Best Practices 88
SEO 100
The best Practices is not at 100 because:
the host I have does not provide HTTP/2 (I might change if that's really an issue)
I have Google Ads script with has document.write() (can't change anything about that)
My big problem is with the Performance Metrics.
I have a white blank screen for more than 3.3s and the is fully showing after 8.3s!
The First meaningful paint is at 5,750ms, the first Interactive is at 6,720ms (same for Consistent Interactive)
The Perceptual Speed Index is 4,228 (score 64)
And the Estimated Input Latency is 16ms (score 100)
This is the Critical Chain Request:
This is the Network overview:
This is what I have done/tried so far:
Moved all components in the start page to async load using react-code-splitting
Optimized the images to use the new J2P, JXR and WEBP format, and made them the correct size so the browser does not have to resize them.
Moved the content of App.js into index.js (before the loading would get index.js and vendor.js in parallel, then a js file with all the css files inside and app.js, and after that it would load in parallel the components that are used inside app.js
Moved some css import to the components they are associated with.
Used webpack-bundle-analyzer to try to find common libraries and how they are splitted. As you can see in the following screenshot there are a lot of duplicated modules in my bundles that I cannot find how to extract for efficiency. (lodash, react-overlays,...)
This is my webpack.config.js
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ChunkManifestPlugin = require('chunk-manifest-webpack-plugin');
const WebpackChunkHash = require('webpack-chunk-hash');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
//var SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
const OfflinePlugin = require('offline-plugin');
// To handle the regeneratorRuntime exception
require('babel-polyfill');
require('file-loader');
require('css-loader');
require('style-loader');
require('html-webpack-template');
/* Shared Dev & Production */
const config = {
context: path.resolve(__dirname, 'src'),
entry: {
index: [
// To handle the regeneratorRuntime exception
'babel-polyfill',
'./index.js'
],
vendor: ['offline-plugin/runtime', 'react', 'react-dom', 'react-router', 'react-redux', 'history', 'react-router-dom', 'redux', 'react-router-redux', 'redux-form', 'lodash'],
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(ico|jpg|png|gif|eot|otf|jp2|jxr|webp|svg|ttf|woff|woff2)(\?.*)?$/,
exclude: /\/favicon.ico$/,
use: [
{
loader: 'file-loader',
query: {
name: '[path][name][hash].[ext]',
publicPath: '/'
}
}
]
},
{
test: /\.css$/,
include: path.join(__dirname, 'src/style'),
use: [
'style-loader',
{
loader: 'css-loader',
options: {
minimize: true
}
}
]
},
{
test: /\.(ico)(\?.*)?$/,
exclude: /node_modules/,
use: {
loader: 'file-loader',
options: { name: '[name].[ext]' },
},
},
{
test: /\.xml/,
use: {
loader: 'file-loader',
options: { name: '[name].[ext]' },
},
},
],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js',
publicPath: '/',
},
resolve: {
extensions: ['.js'],
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
},
plugins: [
// New moment.js optimization
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: 2
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new HtmlWebpackPlugin({
appMountId: 'app-root',
inlineManifestWebpackName: 'webpackManifest',
template: 'templateIndex.html',
title: 'Our Site',
}),
new OfflinePlugin({
AppCache: false,
ServiceWorker: { events: true },
}),
new BundleAnalyzerPlugin({analyzerMode: 'static'}),
],
devServer: {
historyApiFallback: true,
},
};
//if (process.env.NODE_ENV === 'production') {
config.output.filename = '[name].[chunkhash].js';
config.plugins = [
...config.plugins,
new webpack.HashedModuleIdsPlugin(),
new WebpackChunkHash(),
/*new ChunkManifestPlugin({
filename: 'chunk-manifest.json',
manifestVariable: 'webpackManifest',
inlineManifest: true,
}),*/
];
//}
module.exports = config;
my .babelrc
{
"presets": [
[
"env",
{ "modules": false }
],
"react",
"stage-0",
"stage-2"
],
"plugins": [ "syntax-dynamic-import", "transform-react-jsx", "transform-decorators-legacy" ]
}
And my index.js
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import {Redirect, Route, Switch, withRouter} from 'react-router';
import { Provider } from 'react-redux';
import Async from 'react-code-splitting';
const TopBar = () => (<Async load={import('./containers/TopBar/TopBarAsync')} />);
const NavBar = () => (<Async load={import('./containers/NavBar/NavBarAsync')} />);
const BottomBar = () => (<Async load={import('./containers/BottomBar/BottomBarAsync')} />);
const UserHelpers = (props) => <Async load={import('./containers/UserHelpers')} componentProps={props} />
const Main = () => (<Async load={import('./containers/Main')} />);
const Blog = () => (<Async load={import('./containers/Blog')} />);
const PublicPage = () => (<Async load={import('./containers/PublicPage')} />);
import configureStore from './store/store';
const store = configureStore();
import './styles/font-awesome.min.css';
import './styles/app.css';
import './styles/TeamBrowser.css';
let googleTracking = null;
if(process.env.NODE_ENV==='production') {
// https://web-design-weekly.com/2016/07/08/adding-google-analytics-react-application/
ReactGA.initialize([my key here]);
googleTracking = function fireTracking() {
let page=window.location.pathname+window.location.search;
ReactGA.set({ page: page });
ReactGA.pageview(page);
}
const runtime=require('offline-plugin/runtime');
runtime.install({
onUpdateReady() {
runtime.applyUpdate();
},
onUpdated() {
window.location.reload();
},
});
}
render((
<Provider
store={store}>
<BrowserRouter
onUpdate={googleTracking}>
<div className="body">
<header>
<TopBar/>
<NavBar />
</header>
<main>
<Switch>
<Route path="/" exact component={Main} />
<Route path="/main" component={Main} />
<Route path="/Feed" component={Blog} />
<Route path="/Blog" component={Blog} />
<Route path="/:id" component={PublicPage} />
<Redirect to="/" />
</Switch>
</main>
<footer
className="footer">
<BottomBar />
</footer>
<UserHelpers />
</div>
</BrowserRouter>
</Provider>),
document.getElementById('app'));
Right now I am out of ideas about how to improve the loading speed to get a better Lighthouse score.
Can anyone spot anything that I do not know about?
To me it looks like chunk-manifest-webpack-plugin is not doing its job properly because it is not extracting all the common modules.
And second, the index.[hash].js bundle contains files that it should not (ex: utils.js, files under the 'actions' folder,... These are my own files, but they are not referenced in my index.js so why does it put them there?

React router can't find page after page refresh [duplicate]

This question already has answers here:
React-router with BrowserRouter / browserHistory doesn't work on refresh
(2 answers)
Closed 5 years ago.
My App is displaying a list of books with links to a detail page about the book.
When I am on the home component where the book list is rendered and click on a link to get to a specific book, the page is loading correctly...
But when I refresh the page, there is a 404 - Page not found error
(I'm using react-router v4, Node v6.11.1, Express v4.15.2)
React Router setup:
import { BrowserRouter as Router } from 'react-router-dom'
import { Switch, Route } from 'react-router-dom'
class App extends Component {
render() {
return (
<div>
<MyNavbar/>
<div style={{paddingTop: "5rem"}}>
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/book/:id' component={BookPage}/>
</Switch>
</div>
</div>
)
}
}
ReactDOM.render((
<Router>
<App />
</Router>
), document.getElementById('root'))
This is my webpack config:
var webpack = require('webpack')
var path = require('path')
module.exports = {
entry: {
app: './src/app.js'
},
output: {
filename: 'public/dist/bundle.js',
sourceMapFilename: 'public/dist/bundle.map.js'
},
devtool: '#source-map',
module: {
loaders: [
{
loader: 'babel-loader',
test: /\.js?$/,
exclude: /(node_modules)/,
query: {
presets: ['react', 'es2015']
}
}, {
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
{ loader: 'sass-loader', options: { sourceMap: true } }
]
},
{
test: /\.(png|jpg|)$/,
loader: 'url-loader?limit=200000&name=./imgs/[hash].[ext]'
}
]
},
}
this is the doc~
if you are use webpack-dev-server
if you write the webpack-dev-server config on webpack.config.js
You should add this historyApiFallback: true to devServer on your webpack config.
This will return index.html when 404.
devServer: {
...
historyApiFallback: true
}
if you only use cli,do this
webpack-dev-server --history-api-fallback
if you use the node express server.js,see here
If production, you can edit the server config, make every request,return index.html, sure, exclude static files and api requst~
Sorry. I write this on mobile phone.

Route giving error on reload

So I have routing working with redux, but I have a problem with reloading in one of the routes.
app.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute } from 'react-router';
import { Provider } from 'react-redux';
import store , { history } from './store';
import Connect from './components/Connect';
import PhotoList from './components/PhotoList';
import PhotoContent from './components/PhotoContent';
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={Connect}>
<IndexRoute component={PhotoList}></IndexRoute>
<Route path="view/:id" component={PhotoContent}></Route>
</Route>
</Router>
</Provider>,
document.getElementById("app")
);
webpack.config.js:
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
module.exports = {
context: path.join(__dirname, "src"),
devtool: debug ? "inline-sourcemap" : null,
entry: "./js/app.js",
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['react-html-attrs', 'transform-class-properties', 'transform-decorators-legacy'],
}
}
]
},
output: {
path: __dirname + "/src/",
filename: "app.min.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
],
};
This is my code, history = syncHistoryWithStore(store, browserHistory). Then I try to reload the page while inside one of the view/:id, and I get the error:
GET http://localhost:8080/view/app.min.js
Do you guys have any idea why this is happening?
Any help would be appreciated.Thanks!
I run the webpack server from command line with:
webpack-dev-server --content-base src --inline --hot --history-api-fallback
Make sure your index.html is referencing the correct bundle file.
For webpack, make sure your config uses this:
config.devServer = {
...
contentBase: 'src',
historyApiFallback: true,
...
};
or, if you declared it as a single object:
{
...
devServer: {
...
contentBase: 'src',
historyApiFallback: true
}
}
It will redirect your requests to / and have react handle it.
Run your webpack-dev-server like this: ./node_modules/.bin/webpack-dev-server --inline --hot
EDIT:
While working with you over chat, I noticed that the bundle reference in your index.html was incorrect. Moving it to ../app.min.js fixed it.

Categories

Resources