React router 404 error when refreshing page with url params - javascript

I'm trying to use Url params in react router 5.2.0, something like
<Switch>
<Route path="/home" component={ Home } />
<Route path="/user/:id" component={ User } />
</Switch >
It's working but when the I'm on a user's page (localhost:8080/user/1) and I refresh the page it'll trigger a 404.
I think the issue may come from my webpack config.
If I add publicPath: '/' in the output it'll work but the app is not able to load images anymore, it'll try to access //assets/images/... instead of /assets/images/....
Here is my webpack config:
const HtmlWebPackPlugin = require('html-webpack-plugin')
const ReactIntlPlugin = require('react-intl-webpack-plugin')
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath')
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin')
const fs = require('fs')
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const appDirectory = fs.realpathSync(process.cwd())
const resolveApp = relativePath => path.resolve(appDirectory, relativePath)
const publicPath = getPublicUrlOrPath(
process.env.NODE_ENV === 'development',
require(resolveApp('package.json')).homepage,
process.env.PUBLIC_URL
)
const publicUrl = process.env.NODE_ENV === 'development' ? publicPath + "public/assets" : ""
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
},
{
test: /\.(png|jpg|gif|svg|ico)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[contenthash].[ext]',
outputPath: 'assets/img/'
}
},
],
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
exclude: [/images/],
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/fonts/'
}
},
],
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
},
output:{
filename: 'main.[contenthash].js',
publicPath: '/' //now I can refresh the page but assets folder is not accessible anymore
},
plugins: [
new HtmlWebPackPlugin({
template: "./public/index.html",
filename: "./index.html",
favicon: "./public/assets/favicon.ico"
}),
new ReactIntlPlugin(),
new InterpolateHtmlPlugin(HtmlWebPackPlugin, {
PUBLIC_URL: publicUrl,
}),
new CleanWebpackPlugin()
],
devServer: {
historyApiFallback: true
}
}
Thanks for your help

I fixed it.
So the solution to make the refresh working was to add webpackConfig.output.publicPath = '/' as I tried but the reason why the images were not loading anymore was because in my code I access the images this way:
import Image from '../../images/image.png'
<img src={`/${Image }`} alt="Image"/>
So I just removed the / from src={`/${Image }`} and now it's working and now the images url looks like /assets/images/... instead of //assets/images/...
It was kind of an easy one but I missed it.

Related

ReactJS buttons or submit functions created by webpack isn't working

so I'm creating a ReactJS app and configuring webpack for it.
below's my webpack config:
webpack.config.js
const webpack = require('webpack');
const HtmlWebPackPlugin = require( 'html-webpack-plugin' );
const path = require( 'path' );
const dotenv = require('dotenv');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const env = dotenv.config().parsed;
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(env[next]);
return prev;
}, {});
module.exports = {
context: __dirname,
entry: ['./src/js/index.js','./src/sass/index.scss'],
output: {
path: path.resolve( __dirname, 'dist' ),
filename: 'main.js',
publicPath: '/',
},
devtool: 'eval-source-map',
devServer: {
historyApiFallback: true,
contentBase: path.join(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: [/node_modules/],
query: {
presets: ['#babel/react', "#babel/preset-env"]
}
},
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: [/node_modules/],
query: {
presets: ['#babel/react', "#babel/preset-env"]
}
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(gif|png|jpe?g|svg|webp)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true, // webpack#1.x
disable: true, // webpack#2.x and newer
},
},
],
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: path.resolve( __dirname, 'public/index.html' ),
filename: 'index.html',
}),
new webpack.ProvidePlugin({
"React": "react",
}),
new CopyWebpackPlugin({
patterns: [
{ from: 'public/assets' }
]
}),
new webpack.DefinePlugin(envKeys),
]
};
It was all going well until I realized that all my buttons aren't working, I checked all the functions and the syntax to make sure if I get it wrong, but turns out I am making no mistake about it
here's the function to my button:
const submitMail = e => {
console.log('here')
alert('here')
e.preventDefault()
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation();
console.log('test')
}
I tried to call it in my test button, but it wouldn't work, it sent no alert, it won't even log all my console.logs
<button onClick={e => submitMail(e)}>test</button>
I also tried to put them in my form to trigger it at onSubmit along with another button inside just to see if it triggers the "console.log" which is also not working:
<form onSubmit={e => submitMail(e)}>
<input id="banner-text-input-email-input-wrapper-email-input" placeholder="Enter your email here"/>
<input id="banner-text-input-email-input-wrapper-submit-input" onClick={()=>console.log('hi')} type="button" value="Button Value"/>
</form>
NOTE:
I've tried to run the normal react app:
react-script start
and all the buttons are working!! at this point, I can only think that the reason it's not working is because of my webpack config, here's also my webpack command just in case:
webpack serve --open --mode=development --config=webpack.config.js
--hot
Instead of
<button onClick={e => submitMail(e)}>test</button>
did you try to use
<button onClick={submitMail}>test</button>
It will implicitly send the event if I'm not mistaken...
okay, it turns out, I'm very silly at this thing, I'm very new to webpacks, so I thought I needed to put
<script type="text/javascript" src="main.js"></script>
in my public/index.html file
after I deleted that part, it all went well.

Webpack can't extract boostrap.css with min-css-extract plugin

I have a react application that I'm trying to extract the css into separate files but I'm having some issues here. I'm suing the MiniCssExtractPlugin for this. My current webpack configuration included below works fine when I include my own css files but it fails when I include my bootstrap.css from node_modules.
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import MyApp from './scenes/MyApp/MyApp'
import 'bootstrap/dist/css/bootstrap.css'
import './index.css'
import './assets/stylesheets/scenes.scss'
ReactDOM.render(<MyApp />, document.getElementById('root'))
webpack.config.js
const appConstants = function() {
switch (process.env.NODE_ENV) {
case 'local':
const localConfig = require('./config/local');
return localConfig.config();
case 'development':
const devConfig = require('./config/development');
return devConfig.config();
case 'production':
default:
const prodConfig = require('./config/production');
return prodConfig.config();
}
};
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const webpack = require('webpack');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const htmlWebpackPlugin = new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html",
hash: true
});
let webpackConfig = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(css|scss)$/,
exclude: [/node_modules/],
include: [/node_modules\/bootstrap\/dist/],
use: [
{
loader: process.env.NODE_ENV !== 'local' ? MiniCssExtractPlugin.loader : 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.(pdf|jpg|png|gif|svg|ico)$/,
exclude: [/node_modules/],
use: [
{
loader: 'file-loader'
},
]
},
{
test: /\.(woff|woff2|eot|ttf|svg|otf)$/,
exclude: [/node_modules/],
use: {
loader: 'url-loader?limit100000'
}
}
]
},
entry: [ "#babel/polyfill", "./src/index.js"],
output: {
publicPath: appConstants().DS_BASENAME ? JSON.parse(appConstants().DS_BASENAME) : '/'
},
optimization: {
splitChunks: {
chunks: 'all'
}
},
plugins: [
htmlWebpackPlugin,
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en/),
new BundleAnalyzerPlugin({
analyzerMode: 'disabled',
generateStatsFile: true,
statsOptions: { source: false }
}),
new webpack.DefinePlugin({
'process.env': appConstants()
}),
new webpack.EnvironmentPlugin(['NODE_ENV']),
new MiniCssExtractPlugin({
filename: (process.env.NODE_ENV == "local") ? "[name].css" : "[name].[hash].css",
chunkFilename: (process.env.NODE_ENV == "local") ? "[id].css" : "[id].[hash].css"
}),
new OptimizeCSSAssetsPlugin()
],
devServer: {
historyApiFallback: true,
port: 9090
},
watchOptions: {
aggregateTimeout: 300,
poll: 1000
}
};
// configure source map per-env
if (process.env.NODE_ENV === 'local') {
webpackConfig.devtool = 'eval-source-map';
} else {
webpackConfig.devtool = 'hidden-source-map';
}
module.exports = webpackConfig;
Here is the error I get during build:
ERROR in ./node_modules/bootstrap/dist/css/bootstrap.css 7:0
Module parse failed: Unexpected token (7:0)
You may need an appropriate loader to handle this file type.
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
| */
:root {
| --blue: #007bff;
| --indigo: #6610f2;
That error makes me think I'm missing the proper loader but I don't know what other loader I would need for this.
TL;DR
I want to extract all my css files including bootstrap.css into a separate file from my main.js .

React app compiles but errors in console

I've just started building a React.js app with webpack and while the code compiles fine, I get:
Uncaught TypeError: Cannot read property 'array' of undefined
at Object.<anonymous> (RoutingContext.js:28)
in the browser console. I don't even know where to start with where this issue could be.
The RoutingContext is in react-router's own code not mine, specifically this part:
var _React$PropTypes = _react2['default'].PropTypes;
var array = _React$PropTypes.array;
var func = _React$PropTypes.func;
var object = _React$PropTypes.object;
The code I think is causing the issue is:
render((
<Router history={hashHistory}>
<Route path="/" component={App}>
<Route path="adverts" name="adverts" component={Adverts}></Route>
<Route path="ads" name="ads" component={Adverts}></Route>
</Route>
</Router>
), document.getElementById('root'));
webpack configuration:
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: ["babel-polyfill", "./index.js"],
module: {
rules: [
{ test: /\.json$/, loader: 'json-loader' }
],
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'],
}
},
{
test: /\.css$/,
include: /node_modules/,
loaders: ['style-loader', 'css-loader'],
}
]
},
output: {
path: __dirname + "/src/",
filename: "index.min.js"
},
plugins: debug ? [] : [
new webpack.IgnorePlugin(/(locale)/, /node_modules.+(momentjs)/),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
],
};
You're probably using an old version of react-router with a peer dependency of React 15 while using React 16 in your app. React 16 removed PropTypes from the main package, and it looks like react-router is expecting it. Update react-router.

Webpack cannot read property 'Blob' of undefined

Entry file will build literally just fine, but the error occurs on client side, which makes the whole bundle file doesn't work with this issue Uncaught TypeError: Cannot read property 'Blob' of undefined
and i have attached the webpack.config.js which i have tried too
const path = require('path')
const webpack = require('webpack')
const HtmlPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const config = {
entry: './src/main-entry.js',
output: {
path: path.resolve(__dirname, 'views/dist'),
filename: 'bundle.js'
},
module: {
rules: [
{ test: /\.(png|woff|woff2|eot|ttf|svg|gif)$/, loader: 'url-loader?limit=100000' },
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader', fallback: 'style-loader'
})
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
},
plugins: [
new ExtractTextPlugin('bundle.css'),
new webpack.optimize.UglifyJsPlugin({
include: /\.min\.js$/,
minimize: true
})
]
}
module.exports = config
I am using webpack latest version. But i don't know why this is happening? can you help me?

React Universal Webpack App Crashes After ReactDOMServer.renderToString(<App />)

I'm new to universal rendering. I have a wildcard route in express that should catch anything that's not prepended with /api.
It looks like this:
module.exports = function(req, res){
const location = createLocation(req.url);
const store = configureStore();
match({routes, location}, (err, redirectLocation, renderProps) => {
if (err) {
console.error('Error!', err);
return res.status(500).end('Internal server error');
}
if (!renderProps) return res.status(404).end('Not found.');
const InitialComponent = (
<div style={{ width: '80%' }}>
<Provider store={store}>
<RoutingContext {...renderProps} />
</Provider>
</div>
);
const initialState = store.getState();
// | | | | | | | |
// v v v v running this will cause server to crash v v v v
const componentHTML = ReactDOMServer.renderToString(InitialComponent);
console.log('Component html? ', componentHTML);
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<base href="/" />
<title>rūh collective: server</title>
</head>
<body>
<div id="react-app">${html}</div>
<script src="bundle.js"></script>
</body>
</html>
`
res.send(html);
});
}
This successfully sends to the server, because I see that the title has the ruh:server included.
Right after the page loads, the server crashes saying pointing to events.js:82
If I comment out the ReactDOMServer.renderToString and I remove the reference in the html the server loads and does not crash.
If I run ReactDOMServer.renderToString and DO NOT EVEN REFERENCE IT, the server still crashes on load. Commenting out will allow the server to live.
Here is my webpack config:
var webpack = require('webpack');
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const commonLoaders = [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'react-hot',
}, {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
stage: 0,
}
},
{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
stage: 0,
}
},
{ test: /\.css$/, loader: "style-loader!css-loader" },
{
test: /\.html$/,
loader: 'file?name=[name].[ext]',
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'file?hash=sha512&digest=hex&name=[hash].[ext]',
'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false',
]
}
];
//const assetsPath = path.join(__dirname, 'dist');
const publicPath = path.join(__dirname, 'dist');
module.exports =
{
name: 'browser',
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./browser/js/main.js',
],
output: {
filename: 'bundle.js',
path: __dirname + '/dist',
publicPath: 'http://localhost:8080/',
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
],
module: {
loaders: commonLoaders.concat([
{test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
])
}
}
If I comment out the line const componentHTML etc, the server will run, but it's not rendering universally. I can try to replicate the issue if anyone is interested

Categories

Resources