HMR only updates sometimes - reactjs

Does anyone actually have HMR up and running smoothly? Mine is hot swapping sometimes only. How is that possible? I will edit a line of text and it will swap. Then I will go edit the same text and it will not see it. I'm using webpack 1.14. I've spent way too much time on this searching every example online and redoing and configuring my webpack.config. This thing is tough without some real documentation on exactly how to set it up with a webpack-dev-server that works everytime. With all of the unanswered questions on stackOverflow and the webpack GitHub issues section, you'd think nobody really understands it except for the creators and a few gurus.
I have a webpack config that looks like this:
var config = {
entry: [
'webpack-dev-server/client?http://localhost:8080',
// bundle the client for webpack-dev-server
// and connect to the provided endpoint
'webpack/hot/only-dev-server',
// bundle the client for hot reloading
// only- means to only hot reload for successful updates
DEV + "/index.jsx"],
output: {
path: OUTPUT,
filename: "app.js",
publicPath: '/',
},
devtool: 'inline-source-map',
devServer: {
hot: true,
// enable HMR on the server
contentBase: OUTPUT,
// match the output path
publicPath: '/'
// match the output `publicPath`
},
plugins: [
new ExtractTextPlugin('styles.css'),
new webpack.NamedModulesPlugin(),
/* new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin()*/
],
module: {
loaders: [
{
test: /\.jsx?$/,
include: DEV,
loaders: ["react-hot", "babel-loader"],
},
{
test: /\.css$/,
loader: 'style-loader'
}, {
test: /\.css$/,
loader: 'css-loader',
query: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
}
],
}
};
module.exports = config;
My file structure is:
-> EZTube
-> dev
->TabComponent
->other source code files
->index.jsx
-> output
->app.js
->index.html
->styles.css
-> webpack.config.js
-> package.json
My index.jsx looks like:
import React from "react";
import ReactDOM from "react-dom";
import TabComponent from './TabComponent/TabComponent.jsx';
import { AppContainer } from 'react-hot-loader';
ReactDOM.render(
<TabComponent />,
document.querySelector("#container")
);
if (module.hot) {
module.hot.accept('./TabComponent/TabComponent.jsx', () => {
const NewApp = require('./TabComponent/TabComponent.jsx').default
ReactDOM.render(NewApp)
});
}
The weird thing is sometimes hot swap happens when I make a change. Other times not at all. Just wondering if there was some wise internet sage out there who would understand why that is happening with the current set up.

I was having the same intermittent HMR problem, though I'm using
webpack-dev-middleware
webpack-hot-middleware
As HMR was working sometimes, I suspected the diffs were not always getting detected.
I'm running this on Windows, so I tried adding this configuration
watch: true,
watchOptions: {
aggregateTimeout: 300,
poll: 1000, //seems to stablise HMR file change detection
ignored: /node_modules/
},
https://webpack.js.org/configuration/watch/
My HMR is more consistently detected now.

Related

Module Federation, React, and Apollo 3 warnings

I'm building an app with micro-frontends using webpack 5's module federation plugin. Everything was fine until I started adding react hooks into my remote app. At that point I received errors about "invalid usage of hooks", i.e. I discovered I had TWO versions of react loaded, one from the remote and one from the app consuming the remote.
That problem was solved by adding a shared key to the ModuleFederationPlugin section of my webpack config that marked React as a singleton. Now everything compiles and seems to run just fine.
However, the webpack compiler is throwing some annoying warnings at me now. Its saying:
No required version specified and unable to automatically determine one. Unable to find required version for "react" in description file (/Users/myComputer/Development/myapp/node_modules/#apollo/client/react/context/package.json). It need to be in dependencies, devDependencies or peerDependencies.
Here is what my webpack config (in the remote) looks like currently:
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
const deps = require('./package.json').dependencies
module.exports = {
mode: 'development',
devServer: { port: 3001 },
entry: './src/index.tsx',
output: {
path: __dirname + '/dist/',
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json'],
},
use: 'ts-loader',
},
]
},
devtool: 'source-map',
plugins: [
new ModuleFederationPlugin(
{
name: 'myRemote',
filename: 'remoteEntry.js',
exposes: {
'./App':
'./src/App/App.tsx',
},
shared: {
'react': {
singleton: true,
version: deps['react'],
},
'react-dom': {
singleton: true,
version: deps['react-dom'],
},
},
}
),
new HtmlWebpackPlugin({
template:
'./index.html',
})
]
}
The consuming app's webpack config is almost the same, especially the shared section (there are some slight differences in that it declares the remotes).
What would be the way to tell webpack that the apollo package will be getting its react dependency from somewhere else? Or if thats not the right thing to tell webpack, what is and how can I get rid of these warnings?
Fixed my own problem by changing the key version to requiredVersion

Import line getting error in Firefox

I have a React project that uses OverlayLoader library. Although code runs just fine on Chrome, it gets "TypeError: can't convert null to object" in firefox. After taking some time tracking down the error, I found that it comes from import line where I import OverlayLoader library
import OverlayLoader from 'react-overlay-loading/lib/OverlayLoader';
There's also "Source map error: request failed with status 404". But that shouldn't matter though. Why this error only occurs in Firefox?
EDIT : This is content of webpack.config.js
var dotenv = require('dotenv').config({path: __dirname + 'path'});
var webpack = require('webpack');
module.exports = {
entry: ["./js/app.jsx", "./css/custom.scss", "./css/main.scss"],
output: {
path: "public/js",
publicPath: "/js",
filename: "bundle.js"
},
module: {
loaders: [
{
test: /\.jsx?|\.js$/,
exclude: /(node_modules|bower_components|neal-react)/,
loader: "babel-loader",
},
{
test: /\.scss$/,
loader: "style!css!sass"
}
]
},
resolve: {
alias: {
querystring: 'querystring-browser'
}
},
plugins: [
new webpack.DefinePlugin({
"process.env": dotenv.parsed
})
]
};
Two things you can check:
Do you have a libraryTarget in your webpack config? If you, could you try and remove that?
Are you using externals in your webpack configuration? If so, the package will not be bundles and the browser might not have access to it.
Hope it helps.
EDIT:
Seems like it's a source-map issue. I thought that it might be in your configuration but it isn't. Usually a source-map error is because the browser can't find the source-map I think this is an issue you can report with the repo. It's not your configuration.

Stuck with webpack HMR configuration

I'm trying to correctly setup webpacks HMR, I'm developing a small app in order to learn how to use Redux in a React application.
I ran into a problem with webpack and the HMR plugin, when implementing the module.hot.accept function everything seems to work fine, but I've noticed it that when I modify a dependency of my App component it only re-renders the view when I don't pass any dependency argument to module.hot.accept as specified in webpack's docs.
This is what the documentation says I should do:
module.hot.accept(
dependencies, // Either a string or an array of strings
callback // Function to fire when the dependencies are updated
)
This is what I'm trying to do, this doesn't work.
module.hot.accept('./components/App', () => {
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
})
module.hot.accept('./reducers', () => {
// Reconfigure the store
})
This one works
module.hot.accept(() => {
// Render function
})
So let's say my App component, the one I render as child of the <Provider> imports a Header component and just renders like so:
const App = () => (
<div>
<Header />
</div>
)
then if I edit Header the browser will only re-render the view if there's no dependency in module.hot.accept
The problem here is that if I don't pass any dependency it will try to reload my store object and that fires this warning: <Provider> does not support changing 'store' on the fly, I want to properly configure webpack so it only updates the store object when I change things on my reducers and the view when I make changes to my components or containers.
* Edit *
Little bit of extra info, webpack seems to be aware of updates bc it logs in console the updated modules, however doesn't rerenders anything.
This is my webpack.config.js
const path = require('path')
const webpack = require('webpack')
const namedModules = new webpack.NamedModulesPlugin();
const hotModuleReplacement = new webpack.HotModuleReplacementPlugin();
const config = {
context: path.resolve(__dirname, 'src'),
entry: './index.jsx',
devtool: 'eval-source-map',
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(js|jsx)$/,
include: path.resolve(__dirname, 'src'),
use: [{
loader: 'babel-loader',
options: {
presets: [
['env', {'es2015': {'modules': false}}],
'react'
],
plugins: [
'transform-object-rest-spread',
]
}
}]
}]
},
resolve: {
extensions: ['.js', '.jsx', '.json', '*'],
modules: [
'node_modules'
]
},
plugins: [
namedModules,
hotModuleReplacement
],
devServer: {
port: 9000,
host: 'localhost',
inline: true,
hot: true
}
}
module.exports = config
Thanks in advance, fine developers.
So it was the babel configuration as I thought, you need the option modules: false in the babel configuration so it lets webpack handle the modules, it is a noob mistake but man, it drove me crazy for days.
Turned out I was doing something wrong in this line of the babel presets:
['env', {'es2015': {'modules': false}}]
the correct configuration is:
['env', {modules: false}]

Deploying ReactJS app Production

I have finished my ReactJS app and I want to put it in production. I run next command: webpack --progress -p but in chrome F12 I get next error: index.js:1 Warning: It looks like you're using a minified copy of the development build of React. When deploying React apps to production, make sure to use the production build which skips development warnings and is faster. See WebSiteFbReactJs for more details..
It is my webpack.config.js:
'use strict';
const WEBPACK = require('webpack');
const PATH = require('path');
const CopyFiles = require('copy-webpack-plugin');
const BaseName = "/upct";
module.exports = {
resolve: {
extensions: ['', '.js', '.jsx']
},
context: __dirname,
entry: {
app: ['./src/index.jsx']
},
output: {
path: PATH.join(__dirname, '/public'),
/*path: './public',*/
publicPath: BaseName+'/',
filename: 'index.js'
},
devServer: {
host: 'localhost',
port: 3000,
contentBase: PATH.join(__dirname, '/public'),
inline: true,
historyApiFallback: true,
headers: { "Access-Control-Allow-Origin": "*" }
},
module: {
loaders: [
{
test: /(\.js|.jsx)$/,
loader: 'babel',
query: {
"presets": [
"es2015",
"react",
"stage-0"
],
"plugins": [
"react-html-attrs",
"transform-decorators-legacy",
"transform-class-properties"
]
}
}
]
},
plugins: [
new WEBPACK.DefinePlugin({
BASENAME: JSON.stringify(BaseName)
})
]
}
What could this error be?. It is all OK, right? How could I solve this? Thank you.
EDIT: I am getting next error too: DevTools failed to parse SourceMap: http://MYSERVER.com/upct/src/css/bootstrap.css.map
Please add NODE_ENV = 'production' environmental variable to your Webpack build in order to disable debug information and warnings, most of the property type checks and other developer-friendly tools. It will make the app faster but harder to debug. Use this only when deploying to the production.
In your case, in the plugins section just add:
new WEBPACK.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
Please see documentation about optimizing the production build with React, especially Webpack section.
As for the error with the source maps, it seems that the link is broken and returns 404 Not Found error so Chrome can't fetch the original source code mapping for Bootstrap's CSS. That's not a big issue as you probably won't be looking at it's source but that might be a signal that your Webpack build doesn't deploy source maps when building the app. Please add devtool: 'source-map' to your config file in order to produce source maps which will improve the debugging experience on production by translating bundled code to original source files.
UglifyJs will minimize the code size by renaming variables, function names and by other optimization tricks. You can add it to your plugins section of the config file the same way:
new WEBPACK.optimize.UglifyJsPlugin({
compress: {
// suppresses warnings, usually from module minification
warnings: false,
},
}),
There are many possible optimizations, for more information please see this optimization guide.

Why is my Webpack ReactJS App so large?

I have followed as many tips as I can find in packaging my Webpack ReactJS app for production. Unfortunately, the file size is still 3MB. What am I doing wrong?
Here is my Webpack Config file:
var path = require('path')
var webpack = require('webpack')
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
'./index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle-webpack.js',
publicPath: './'
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
screw_ie8: true,
warnings: false
}
})
],
module: {
loaders: [
{
test: /\.js$/,
loaders: [ 'babel' ],
exclude: /node_modules/,
include: __dirname
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{test: /node_modules\/react-chatview/, loader: 'babel' }
]
}
}
Any help would be greatly appreciated!
I use the following command to package it:
> NODE_ENV=production webpack -p
I get the following output:
bundle-webpack.js 3.1 MB 0 [emitted] main
Best,
Aaron
Looks like you've still got a fair amount of dev stuff there, e.g. hot module replacement.
Take a look at webpack.config.prod.js at React Transform Boilerplate as a guide.
You may also be able to optimise your imports by including only the parts of the packages you need and leaving out the rest. See: Reduce Your bundle.js File Size By Doing This One Thing .
So, it turns out that David L. Walsh was correct that I had too much development stuff in my app. However, the answer provided did not resolve the issue.
I resolved the issue using 3 steps.
Remove all the "hot-reloading" plugins from my webpack configuration, as David instructed.
Remove the hot reloading "react-transform" plugin from my .babelrc file.
Change the "devtool" parameter to "source-map" from "cheap-module-eval-source-map"
After following those steps, the final bundle file was 340kb while the source map was still 3MB. Fortunately, I don't have to include the source map in my application, so it can be downloaded at 340kb, which is still fairly large, but reasonable for modern browsers running on modern internet connections.
I would up-vote David's answer, but I don't have enough reputation points yet to do so.

Resources