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.
Related
I was having a problem with SEO in my react app so I did Server-side rendering. At first, I changed '.render' to '.hydrate' in src/index.js. I created a server folder in it server.js and index.js. But it's still showing only the script tag with 'root' in the source code in the browser after deploying to firebase.
src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import "bootstrap/dist/css/bootstrap.css";
import { hydrateRoot } from "react-dom/client";
const container = document.getElementById("root");
const root = hydrateRoot(container, <App />);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
server.js
import path from "path";
import fs from "fs";
import express from "express";
import React from "react";
import ReactDOMServer from "react-dom/server";
import App from "../src/App";
const PORT = 3000;
const app = express();
const router = express.Router();
const serverRenderer = (req, res, next) => {
fs.readFile(path.resolve("./build/index.html"), "utf8", (err, data) => {
if (err) {
console.error(err);
return res.status(500).send("An error occurred");
}
return res.send(
data.replace(
'<div id="root"></div>',
`<div id="root">${ReactDOMServer.renderToString(<App />)}</div>`
)
);
});
};
router.use("^/$", serverRenderer);
router.use(
express.static(path.resolve(__dirname, "..", "build"), { maxAge: "30d" })
);
// tell the app to use the above rules
app.use(router);
// app.use(express.static('./build'))
app.listen(PORT, () => {
console.log(`SSR running on port ${PORT}`);
});
index.js
require("ignore-styles");
require("#babel/register")({
ignore: [/(node_modules)/],
presets: ["#babel/preset-env", "#babel/preset-react"],
});
require("./server");
It is working when I'm running 'node server/server.js' in the terminal but when I'm running 'npm start' it's not working or when I'm deploying it to firebase with 'firebase deploy' after 'npm run build'.
Thank you.
When i try to the run app it shows a red screen with this error in the terminal
Error: Unable to resolve module `../../../../src/assets/images` from `node_modules/#reduxjs/toolkit/dist/redux-toolkit.cjs.production.min.js`:
but It occuurs on iOS as well
The only way to make it go so far has been uninstalling react-redux. I do not have any imports in my code that point to src/assets/images as I dont have an assets/images directory to begin with.
My index.js:
import React from 'react';
import 'expo-asset';
import 'react-native-gesture-handler';
import {AppRegistry, View} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import { Provider as ReduxProvider } from 'react-redux';
import store from 'src/redux';
import React from 'react';
import 'expo-asset';
import 'react-native-gesture-handler';
import {AppRegistry, View} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import { Provider as ReduxProvider } from 'react-redux';
import store from 'src/redux';
const reduxApp = () => (
<ReduxProvider store={store}>
<App />
</ReduxProvider>
)
AppRegistry.registerComponent('main', () => reduxApp);
Redux store:
import { configureStore, getDefaultMiddleware} from '#reduxjs/toolkit';
import logger from 'redux-logger';
import { persistStore } from 'redux-persist';
import reducer from './reducers'
const middleware = [...getDefaultMiddleware(), logger]
const store = configureStore({
reducer,
middleware,
})
export const persistor = persistStore(store);
export default store;
metro.config.js:
module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
};
babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
[
'module-resolver',
{
alias: {
src: './src',
screens: './src/screens',
redux: './src/assets/images',
assets: './assets',
},
},
],
],
};
};
The problem is your babel.config.js file. I'm guessing that you copy and pasted some code from somewhere else without understanding what it means.
redux: './src/assets/images',
This line right here tells the compiler that the location of the redux module is ./src/assets/images. It will look for the redux source code in that folder, which doesn't exist, instead of the default location which is ./node_modules/redux.
You don't want this so delete that line.
I am trying to dynamically import react component library from API. The js file is fetched succesfully. The babel transpilation has happened successfully too. If I dynamically import the Dummy.js file from localhost like import Dummy from './components/js/Dummy.js', it works. However API import fails with below error. The same error occurs with react lazy too. I basically want to dynamically load the lib and publish events to it. I am newbie to react and front-end development. Please excuse if this is too silly!.
Error resolving module specifier: react
My App.js
import React, { lazy, Suspense } from 'react';
import './App.css';
import ErrorBoundary from './ErrorBoundary';
class App extends React.Component {
render(){
const loader = () => import( /*webpackIgnore: true*/ `https://example.com/Dummy.js`);
const Dummy = ReactDynamicImport({ loader });
const LoadingMessage = () => (
"I'm loading..."
)
return (
<div className="App">
<h1>Simplewidget</h1>
<div id="simplewidget">
<ErrorBoundary>
<Suspense fallback={LoadingMessage}>
<Dummy />
</Suspense>
</ErrorBoundary>
</div>
</div>
);
}
}
export default App;
rollup.config.js, After multiple attempts I arrived at below configuration https://github.com/jaebradley/example-rollup-react-component-npm-package/blob/master/rollup.config.js
// node-resolve will resolve all the node dependencies
import resolve from '#rollup/plugin-node-resolve';
import babel from 'rollup-plugin-babel';
import commonjs from '#rollup/plugin-commonjs';
import filesize from 'rollup-plugin-filesize';
import localResolve from 'rollup-plugin-local-resolve';
export default {
input: 'src/components/js/Dummy.js',
output: {
file: 'dist/Dummy.js',
format: 'es',
globals: {
react: 'React',
'react-dom': 'ReactDOM'
}
},
// All the used libs needs to be here
external: [
'react',
'react-dom'
],
plugins: [
babel({
exclude: 'node_modules/**',
}),
localResolve(),
resolve({
browser: true,
}),
commonjs(),
filesize()
]
}
Dummy.js. I verified in dist/dummy.js that babel transpilation happened correctly. I uploaded the transpiled version to my static hosting site.
import React from "react";
import ReactDOM from "react-dom";
class Dummy extends React.Component {
render() {
return (
<h1>Hello</h1>
);
}
}
export default Dummy;
I have different targets to build, start up my server, create rollup bundle, etc in same app. So, I am pretty confident my rollup doesn't interfere with running the app.
The rollup bundling configuration isn't correct. I was trying to create an es output with commonjs plugin while actually I required an esm module. The error on 'react' is because it is unresolved. Had to make it to use window.React while doing rollup bundle. Also, the App.js should be rolled up as esm bundle to make it dynamically import Dummy.js. In the HTML where app.js's bundle is included, I had to include react and react js umd scripts.
export default {
input: "./src/components/js/Dummy.js",
output: {
file: './dist/Dummy.js',
format: 'esm'
},
plugins: [
babel({
exclude: "node_modules/**"
}),
resolve(),
externalGlobals({
"react": "window.React",
"react-dom": "window.ReactDOM",
})
]
};
I just upgraded to the latest version of React, Webpack, Redux, Babel, etc.
React hot loading works, but there's an error from react-redux: <Provider> does not support changing `store` on the fly.
I noticed that upon reload, it says module App.js needs updating, and then it calls createApp all over again, which creates the store again. I'm not quite sure how to avoid this.
I have over a dozen React apps, so it'd be awesome if I could somehow keep the createApp boilerplate method.
webpack.config.js:
{
devServer: {
hot: true,
host: '0.0.0.0',
},
entry: {
Bundle: __dirname + '/../src/App.js',
},
mode: 'development',
module: {
...
},
output: {
filename: '[name].js',
path: RootDir,
publicPath: 'http://localhost/',
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
resolve: {
alias: {
'react-dom': '#hot-loader/react-dom',
},
},
};
App.js:
import 'react-hot-loader';
import Reducers from './Reducers';
import Routes from './Routes';
import createApp from './createApp';
import { hot } from 'react-hot-loader/root';
const app = createApp(Routes, Reducers);
export default hot(app);
createApp.js
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { applyRouterMiddleware, browserHistory, Router } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import { ReduxAsyncConnect } from 'redux-connect';
import configureStore from './configureStore';
import scrollMiddleware from './scrollMiddleware';
export default function createApp(routes, reducers) {
const store = configureStore(reducers);
const history = syncHistoryWithStore(browserHistory, store);
const app = () => routes;
render((
<Provider store={store}>
<Router
history={history}
render={(props) => (
<ReduxAsyncConnect
{...props}
render={applyRouterMiddleware(scrollMiddleware)}
/>
)}>
{app()}
</Router>
</Provider>
), document.getElementById('app'));
return app;
}
I'm trying to build a project with this simple structure:
app
|-- components
| |-- App.jsx
| |-- Root.jsx
|-- index.jsx
index.jsx looks like this:
import React from 'react';
import { createStore } from 'redux';
import { render } from 'react-dom';
import Root from 'app/components/core/Root';
const store = createStore();
render(<Root store={ store } />, document.getElementById('root'));
and Root.jsx looks like this:
import React from 'react';
import { Provider } from 'react-redux';
import { BrowserRouter, Route } from 'react-router-dom';
import App from 'app/components/core/App';
const Root = ({ store }) => {
return <Provider store={ store }>
<BrowserRouter>
<Route path='/' component={ App } />
</BrowserRouter>
</Provider>
};
Root.propTypes = {
store: React.PropTypes.object.isRequired,
};
export default Root;
I create a gulp file this way, specifying the (I think) correct processors for Babelify:
var gulp = require('gulp'),
buffer = require('vinyl-buffer'),
browserify = require('browserify'),
babelify = require('babelify'),
source = require('vinyl-source-stream'),
gutil = require('gulp-util');
gulp.task('build', function () {
var browserifyOptions = {
debug: true,
entries: './app/index.jsx',
extensions: ['.jsx', '.js'],
};
return browserify(browserifyOptions)
.transform(babelify.configure({
presets: ['es2015', 'react']
}))
.bundle()
.on('error', gutil.log)
.pipe(source('app.js'))
.pipe(buffer())
.pipe(gulp.dest('./lima/static'));
});
gulp.task('default', ['build']);
Now the strange thing is I get this:
Root.jsx:1
import React from 'react';
^
ParseError: 'import' and 'export' may appear only with 'sourceType: module'
The weird thing is that index.jsx seems to work just fine and if I remove any of the babel presets I get errors in that file instead. What can be wrong about Root.jsx or my gulpfile?
You need to add { modules: false } to your gulpfile:
presets: [['es2015', { modules: false }], 'react']