React-hot-loader doesn't propagate changes - reactjs

My problem is that react-hot-reload detect the changes and the modules that need to be update, and apparently does update the modules, but nothing in my browser changes.
Here's the version of the libraries I'm using:
react - 16.8.3
react-dom (patched by react-hot-loader ) - 16.8.3
react-hot-loader - 4.8.0
webpack - 4.29.6
Below, my webpack-dev-server config:
historyApiFallback: true,
hot: true,
stats: 'none',
quiet: true,
port: port,
host: host,
Relevant part of my webpack config
entry: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./src/index.js',
],
resolve : {
alias: {
'react-dom': '#hot-loader/react-dom'
}
},
My .babelrc:
"plugins": [
"#babel/plugin-transform-flow-strip-types",
"#babel/plugin-proposal-class-properties",
"react-hot-loader/babel"
]
My initial component:
import React, { Component } from 'react'
import { hot } from 'react-hot-loader/root'
class App extends Component<PropTypes, StateTypes> {
render (): React$Element<*> {
return (
<Router>
<Switch>
<Route
path="/home"
render={ (props: Object): React$Element<*> => <HomeView {...props } /> }
/>
<Route component={ IntroView } />
</Switch>
</Router>
)
}
}
export default hot(App)
Lastly, my entry file:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './app'
const appContainer = document.getElementById('appContainer')
if (module.hot) {
module.hot.accept()
if (appContainer) ReactDOM.render(<App />, appContainer)
} else if (appContainer) {
ReactDOM.render(<App />, appContainer)
}
If I do any code change that was supposed to trigger an update, that's my console:
[WDS] App updated. Recompiling...
[WDS] App hot update...
[HMR] Checking for updates on the server...
XHR finished loading: GET "http://localhost:8080/df32ff4...hot-update.json.
[HMR] Updated modules:
[HMR] - ./src/library/protons/ModalWorkflow/sandbox/workflowStepOne.js
[HMR] - ./src/library/protons/ModalWorkflow/sandbox/index.js
[HMR] - ./src/configs/routes.js
[HRM] - ./src/views/intro/index.js
[HRM] - ./src/view/home/index.js
[HRM] - ./src/app.js
[HRM] App is up to date.
Browser doesn't reflect the code changes at all.
No errors, no warnings.
Tried several different approaches to check any potential mistake, but as of right now I'm in this hopeless spot, no idea what else I could try.

Related

ReactJS and Webpack Module Federation Application contains urls with undefined when deployed to cloudfront

I have a micro-frontends app that consists of a container application with several remote applications. It is using ReactJS with Webpack 5 module federation and works fine on my local environment. However, when I deploy it to AWS CloudFront it doesn't work as expected.
It seems that the container app loads on the correct path but 'undefined' is added to the url of the remoteEntry.js file of the remotes.
Please see screenshot below:
The container projects webpack production config is as follows:
const prodConfig = {
mode: "production",
output: {
filename: "[name].[contenthash].js",
publicPath: "/container/latest/",
},
plugins: [
new ModuleFederationPlugin({
name: "container",
remotes: {
auth: `auth#${domain}/auth/latest/remoteEntry.js`,
marketing: `marketing#${domain}/marketing/latest/remoteEntry.js`,
dashboard: `dashboard#${domain}/dashboard/latest/remoteEntry.js`,
},
shared: packageJson.dependencies,
}),
],
};
The remote projects webpack production config is as follows:
const prodConfig = {
mode: "production",
output: {
filename: "[name].[contenthash].js",
publicPath: "/marketing/latest/",
},
plugins: [
new ModuleFederationPlugin({
name: "marketing",
filename: "remoteEntry.js",
exposes: {
"./MarketingApp": "./src/bootstrap",
},
shared: packageJson.dependencies,
}),
],
};
The container projects App.js is as follows:
import React, { lazy, Suspense, useState, useEffect } from "react";
import { Router, Route, Switch, Redirect } from "react-router-dom";
import {
StylesProvider,
createGenerateClassName,
} from "#material-ui/core/styles";
import { createBrowserHistory } from "history";
import Progress from "./components/Progress";
import Header from "./components/Header";
const MarketingLazy = lazy(() => import("./components/MarketingApp"));
const AuthLazy = lazy(() => import("./components/AuthApp"));
const DashboardLazy = lazy(() => import("./components/DashboardApp"));
const generateClassName = createGenerateClassName({
productionPrefix: "co",
});
const history = createBrowserHistory();
export default () => {
const [isSignedIn, setIsSignedIn] = useState(false);
useEffect(() => {
if (isSignedIn) {
history.push("/dashboard");
}
}, [isSignedIn]);
return (
<Router history={history}>
<StylesProvider generateClassName={generateClassName}>
<div>
<Header
onSignOut={() => setIsSignedIn(false)}
isSignedIn={isSignedIn}
/>
<Suspense fallback={<Progress />}>
<Switch>
<Route path="/auth">
<AuthLazy onSignIn={() => setIsSignedIn(true)} />
</Route>
<Route path="/dashboard">
{!isSignedIn && <Redirect to="/" />}
<DashboardLazy />
</Route>
<Route path="/" component={MarketingLazy} />
</Switch>
</Suspense>
</div>
</StylesProvider>
</Router>
);
};
I am struggling to figure out where the error is. I am not sure if its an error with:
React
React Router
Webpack Module Federation
AWS CloudFront
Any help would be appreciated
If you look carefully at your browser logs.
There is a undefined/marketing/latest/remoteEntry.js in your url loading the module federated remote urls.
It is likely you need to setup your domain variable to be the cloudfront endpoint.
A little late,
Problem:
The problem is maybe you are just deploying the marketing app alone and the container app is not aware of marketing app changes until it is redeployed.
Solution;
All you need to do is just make changes to both Marketing and container app and commit to git to trigger a workflow for both apps.
hope this may help someone with same issue.

React webpack hotload get stuck on index.html after refreshing webpage

Webpack hotload feature gets stuck on index.html after refreshing web page. It stucks and never goes further than index.html file of the project, which is located under /public/index.html. After it get stucks, I'm able to fix it by editing anything in index.html and refresing webpage, or stop/run project again.
create-react-app's own webpack replaced by our own. This is a must to configure a 3rd party library we use.
I tried like 30+ solutions accross the web, mostly stackoverflow but couldn't managed to solve it.
npm run start script used in package.json:
"start": "webpack serve --mode development --progress",
Here some code snippets from configurations made to enable hotload and solve this problem:
(since webpack file is too large i only copied the relevant parts. I can copy all if it helps.)
webpack.config.js
//...
devServer: {
historyApiFallback: true,
hot: true,
port: 3001,
open: false
},
plugins: [
//...
...(isProduction ? [] : [new webpack.HotModuleReplacementPlugin()])
]
.babelrc
{
"presets": [
[
"#babel/preset-env",
{
"modules": false
}
],
"#babel/preset-react"
],
"plugins": [
"#babel/plugin-transform-runtime",
"react-hot-loader/babel",
[
"#babel/plugin-proposal-class-properties",
{
"loose": true
}
]
]
}
index.js
// Internet Explorer 11 requires polyfills and partially supported by this project.
// import 'react-app-polyfill/ie11';
// import 'react-app-polyfill/stable';
import React from 'react';
import ReactDOM from 'react-dom';
import 'typeface-muli';
import './i18n';
import './react-chartjs-2-defaults';
import './styles/index.css';
import App from 'app/App';
import { AppContainer } from 'react-hot-loader';
import * as serviceWorker from './serviceWorker';
require('react-hot-loader/patch');
const render = () => {
ReactDOM.render(
<AppContainer>
<App />
</AppContainer>,
document.getElementById('root')
);
};
serviceWorker.unregister();
render();
if (process.env.NODE_ENV === 'development' && module.hot) {
module.hot.accept('./app/App', render);
}
App.js
import MomentUtils from '#date-io/moment';
import FuseAuthorization from '#fuse/core/FuseAuthorization';
import FuseLayout from '#fuse/core/FuseLayout';
import FuseTheme from '#fuse/core/FuseTheme';
import history from '#history';
import { createGenerateClassName, jssPreset, StylesProvider } from '#material-ui/core/styles';
import { MuiPickersUtilsProvider } from '#material-ui/pickers';
import { create } from 'jss';
import jssExtend from 'jss-plugin-extend';
import rtl from 'jss-rtl';
import React from 'react';
import Provider from 'react-redux/es/components/Provider';
import { Router } from 'react-router-dom';
import { hot } from 'react-hot-loader/root';
import AppContext from './AppContext';
import { Auth } from './auth';
import routes from './fuse-configs/routesConfig';
import store from './store';
const jss = create({
...jssPreset(),
plugins: [...jssPreset().plugins, jssExtend(), rtl()],
insertionPoint: document.getElementById('jss-insertion-point')
});
const generateClassName = createGenerateClassName();
const App = () => {
return (
<AppContext.Provider
value={{
routes
}}
>
<StylesProvider jss={jss} generateClassName={generateClassName}>
<Provider store={store}>
<MuiPickersUtilsProvider utils={MomentUtils}>
<Auth>
<Router history={history}>
<FuseAuthorization>
<FuseTheme>
<FuseLayout />
</FuseTheme>
</FuseAuthorization>
</Router>
</Auth>
</MuiPickersUtilsProvider>
</Provider>
</StylesProvider>
</AppContext.Provider>
);
};
export default hot(App);
Any ideas/solutions will be much appreciated.
Thanks.

React-hot-loader: `hot` could not find the `name` of the the `module` you have provided

I'm using Webpack 4 to create a React project with hooks and I'm trying to get the changes to reload on page live using react-hot-loader following this tutorial.
But I when I try npm start I get following error on the browser:
Error: React-hot-loader: hot could not find the name of the the
module you have provided
This is my App.js contents:
import React from 'react';
import { hot } from 'react-hot-loader';
import Header from './Header';
function App() {
return (
<section className="main">
<Header />
</section>
);
}
export default hot(App);
Alternately I tried importing hot from react-hot-loader/root, but this way I get a different error:
Error: React-Hot-Loader: react-hot-loader/root is not supported on
your system. Please use import {hot} from "react-hot-loader" instead
How could I solve this issue?
You should be requiring it before react:
import { hot } from 'react-hot-loader/root';
import React from 'react';
The package documentation mentions this.
Well, looking at my webpack configs:
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(env.NODE_ENV) }),
],
devServer: {
contentBase: './dist',
hot: true,
},
I had used webpack.HotModuleReplacementPlugin() in plugins and hot: true in devServer which made the second error if I would use react-hot-loader/root.
So removing new webpack.HotModuleReplacementPlugin() from the webpack.config.js, solved my problem.
import { hot } from 'react-hot-loader';
export default hot(module)(App);
or
import { hot } from 'react-hot-loader/root';
export default hot(App);

React router: adding dynamic URL

I am using React Router Dom 4.2.2
Currently I have one Router as follows:
import React from 'react';
import {BrowserRouter, Route, Switch, Link, NavLink} from 'react-router-dom';
import ExpensesDashboardPage from "../components/ExpensesDashboardPage";
import AddExpensePage from "../components/AddExpensePage";
import EditExpensePage from "../components/EditExpensePage";
import HelpPage from "../components/HelpPage";
import NotFoundPage from "../components/NotFoundPage";
import Header from "../components/Header";
const AppRouter = () => (
<BrowserRouter>
<div>
<Header/>
<Switch>
<Route path='/' component={ExpensesDashboardPage} exact={true}/>
<Route path='/create' component={AddExpensePage}/>
<Route path='/edit/' component={EditExpensePage}/>
<Route path='/help' component={HelpPage}/>
<Route component={NotFoundPage}/>
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
And I have tested that we can navigate to each one of the Route.
Then I thought about using a dynamic URL as follows:
<Route path='/edit/:id' component={EditExpensePage}/>
So then the component which we should render is:
import React from 'react';
const EditExpensePage = (props) => {
console.log(props);
return (
<div>
This is the Edit Expenses page, enjoy!
</div>
);
};
export default EditExpensePage;
The question here is the following:
Why if we go to the following URL: http://localhost:8080/edit/33, the console outputs:
GET http://localhost:8080/edit/bundle.js 404 (Not Found)
33:1 Refused to execute script from 'http://localhost:8080/edit/bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
I would expect to see the page being loaded and into the match props, a params Object with the id: 33
I have also read
How to achieve Dynamic routing in React Router 4?
Thank you for your help!
I also had the same issue. My best bet you are watching the React Udemy tutorial of Andrew Mead. I tried the solution as provided by #mani.saffarnia. Didn't Work Out.
Here is how I got to make it work:
Setup the property public path as publicPath: '/'in your webpack.config.js in output block and devserver block.
Also change the default webpack server port from 8080 to 8082(any random unused port) in webpack dev server to ensure there is no caching.
Deleted Node Modules.
Clear npm cache using npm cache clean --force
Delete Public Folder and reinstalled node modules and created a fresh public folder to serve index.html and bundle.js
Finally run dev server for a working output
Here's my final webpack config for the fixed issue.
const path = require('path');
module.exports = {
entry: './src/app.js',
output:{
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/'
},
module:{
rules:[
{
loader:'babel-loader',
test: /\.js$/,
exclude: /node_modules/
},
{
test:/\.s?css$/,
use:[
'style-loader',
'css-loader',
'sass-loader'
]
}
]
},
devtool:'inline-source-map',
devServer:{
contentBase : path.resolve(__dirname, 'public'),
historyApiFallback: true,
publicPath: '/',
port: 8082
}
};
You didn't do anything wrong in your code. I know the tutorial that you are watching and I had the same problem. I just deleted my "public" and "node_modules" folders. after that, I created a new public folder(with a new index.html inside it), and also used "npm install" to install all dependencies and create node_modules again. It worked for me and I hope it works for you too.
In your index.html file.
does your script import say:
<script src="./bundle.js"></script>
if so. remove the "." in from of the "/". So the script import is
<script src="/bundle.js"></script>
This worked for me

Webpack 2 HMR on Preact App

I'm trying to setup Hot Module Reloading with Webpack 2 and Preact. It's "working", in that it's reloading the entire contents of the app every reload, but I'm getting errors between hot reloads (and I think that's why individual components aren't the only thing reloading).
Here's the relevant parts of my webpack setup:
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.NamedModulesPlugin(),
//etc.
],
entry: [
'webpack-dev-server/client?'+DEV_SERVER,
'webpack/hot/only-dev-server',
'./dev/jsx/index.jsx'
],
devServer: {
hot: true,
inline: true,
contentBase: path.join(__dirname, '/'),
publicPath: '/'
}
My index.jsx file looks like:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './AppProvider.jsx';
const renderApp = () => {
ReactDOM.render(<App/>, document.getElementById('root'));
};
renderApp();
if (module.hot) {
module.hot.accept();
module.hot.accept('./AppProvider.jsx', renderApp);
}
When I make a change in any of the project files, the app contents reload and I get the following errors:
Have any of you gotten this before? I've been Googling all day and haven't found anything...
You're rendering the old AppProvider module, which is null when HMR kicks in. You'll need to move the require()/import for AppProvider.jsx into your HMR handler as shown here.
import React from 'react';
import ReactDOM from 'react-dom';
const renderApp = () => {
let App = require('./AppProvider.jsx');
App = App.default || App; // if you're using ES Modules
ReactDOM.render(<App/>, document.getElementById('root'));
};
renderApp();
if (module.hot) {
module.hot.accept('./AppProvider.jsx', renderApp);
}

Resources