Hot Loader not working - reactjs

I am trying to use Hot Loader. I have installed Hot Loader and followed all the steps from the documentation http://gaearon.github.io/react-hot-loader/getstarted/. I then give "npm start" command to the terminal. But terminal throws an error. I am not able to see the changes I make in the component getting reflected in browser.
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
devServer: {
inline: true,
contentBase: './src',
port: 3000
},
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-dev-server/client?http://localhost:3000', // WebpackDevServer host and port
'webpack/hot/only-dev-server', // "only" prevents reload on syntax errors
'./dev/js/index.js' // Your appʼs entry point
],
module: {
loaders: [
{
test: /\.js$/,
loaders: ['react-hot','babel'],
exclude: /node_modules/
},
{
test: /\.scss/,
loader: 'style-loader!css-loader!sass-loader'
}
]
},
output: {
path: 'src',
filename: 'js/bundle.min.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.optimize.OccurrenceOrderPlugin()
]
};
Script part of Package.json
"scripts": {
"dev": "webpack",
"start": "node server.js"
},
server.js
var webpack = require('webpack');
var webpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
var port = 3000;
var compiler = webpack(config);
new webpackDevServer(compiler, {
publicPath: config.output.publicPath,
hot:true,
stats:{colors:true}
}).listen(port, 'localhost', function (err, result) {
if(err){
console.log(err);
}
console.log('listening at localhost' + port);
});
Few quetions
1. Is my server.js file is fine.
2. Have I included everything correctly in scripts in package.json.
3. Is "npm start" a command to launch hot loader.
4. Even after getting error after "npm start", I can launch my application
in the browser by clicking the chrome icon. What is the reason.
5. What should I change in these files to get a working hot loader.

Related

why process.env doesn't work in app.js file but works in webpack.config.js?

why process.env doesn't work in app.js file but works in webpack.config.js? I have my own webpack that I created myself. It was not created with CRA
the version so it is correct to deduce? Or is there any way to get it out? Or is it better not to drive at all? since it seems to me that this is also not correct, since the env file should be in the exception and on the server, when loading, probably nothing will be known about the version ...
I want to output the version to the console so I can see the webpack version. But I can't do it even though I made the necessary settings. if I output data in webpack, then everything works correctly if I output data in a simple js file, erroneous errors. in general, I want to make the version visible on the server after the build, and I want to do it in this way, you can simply output console.log, but this seems like the wrong solution console.log('ver 1.74.2')
import React from "react";
import styles from "./styles.scss";
const onClickEvent = (e) => {
e.preventDefault();
alert("You Clicked Me!");
};
const App = () => {
console.log(process.env.TERM_PROGRAM_VERSION);
return (
<div className={styles.content}>
<div className={styles.label}>OWN WEBPACK</div>
<button className={styles.btn} onClick={onClickEvent}>
Click Me 😎
</button>
</div>
);
};
export default App;
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const production = process.env.NODE_ENV === "production";
const Dotenv = require("dotenv-webpack");
console.log(process.env.TERM_PROGRAM_VERSION);
module.exports = {
entry: { myAppName: path.resolve(__dirname, "./src/index.js") },
output: {
path: path.resolve(__dirname, "./dist"),
filename: production ? "[name].[contenthash].js" : "[name].js",
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.s(a|c)ss$/,
exclude: /node_modules/,
use: [
production ? MiniCssExtractPlugin.loader : "style-loader",
{
loader: "css-loader",
options: {
modules: true,
sourceMap: !production,
},
},
{
loader: "sass-loader",
options: {
sourceMap: !production,
},
},
],
},
],
},
resolve: {
extensions: ["*", ".js", ".jsx", ".scss"],
},
plugins: [
new CleanWebpackPlugin(),
new Dotenv(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
title: "Webpack & React",
template: "./src/index.html",
favicon: "./public/favicon.ico",
}),
new MiniCssExtractPlugin({
filename: production ? "[name].[contenthash].css" : "[name].css",
}),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
"process.env.MY_ENV": JSON.stringify(process.env.MY_ENV),
}),
],
devServer: {
port: 3001,
hot: true,
},
mode: production ? "production" : "development",
};
"scripts": {
"start": "npm run build && node server/index.js",
"dev": "NODE_ENV=development test=$TERM_PROGRAM_VERSION webpack serve --config webpack.config.js",
"build": "NODE_ENV=production webpack --config webpack.config.js",
"build:dev": "NODE_ENV=development webpack --config webpack.config.js",
"build:watch": "NODE_ENV=development node ./node_modules/webpack/bin/webpack.js --config webpack.config.js --watch"
},
//server/index.js
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
if (process.env.NODE_ENV === 'development') {
console.log('in development.');
} else {
console.log('in production.');
}
/* App Config */
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, '../dist')));
/* Server Initialization */
app.get('/', (req, res) => res.sendFile('index.html'));
var port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Server initialized on: http://localhost:${port} // ${new Date()}`));
Change your env variable to REACT_APP_TERM_PROGRAM_VERSION then reload your app.
React env variables must start with REACT_APP_ prefix. See https://create-react-app.dev/docs/adding-custom-environment-variables/

Dockerizing react app with webpack, connection issues

I'm lately trying to dockerize my react app to learn docker.
I'm using weback for managing this project.
Now here is the thing, after I run dev script npm run dev, server gets on, but I'm not able to connect to it either on host (posting container on 3000:3000) and inside container for any-given ports that came up to my mind (like 8000, 8080, 3000, 5000). It just seems to me like the port connection is not set up properly.
Reading some webpack docs did not give me any clue.
The questions are: best way to define server scripts to run ?
My way of doing it is:
"scripts": {
"dev": "webpack --mode development --watch",
"build": "webpack --mode production"
},
Is there any default-like port that webpack sets its connection to (maybe a way to change it)?
What I did establish, is that for 90% it's my webpack config. After dockerizing react app with create-react-app I did have successfull start.
My webpack.config.js :
const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: { index: path.resolve(__dirname, "src", "index.js") }, //"./src/index.js",
output: {
path: path.resolve(__dirname, "./static/frontend"),
filename: "[name].js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
],
},
optimization: {
minimize: true,
},
plugins: [
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify("production"),
},
}),
],
};

Webpack and Lighthouse performance test

Hy,
I'm new to webpack and after hard learning I know that I know nothing :-).
I'm using React and I have 2 questions:
How can I run my build version in the browser, for the lighthouse test. At the moment I'm using npm run dist (below package.json). Which is working but I have the feeling it is not the correct way and my dist folder gets deleted. If I use npx create-react-app I can use serve -s build therefor.
If I make my Lighthouse performance test I get "Enable text compression". So I installed the compression-webpack-plugin and brotli-webpack-plugin. I have now in the dist folder the br and gz files but in the HTTP response header I don't get Content-Encoding: br or gzip and lighthouse still blames me for this.
package.jsong
"scripts": {
"start": "webpack-dev-server --config webpack.dev.js --open --progress --colors --hot",
"dist": "webpack-dev-server --config webpack.prod.js --open --mode production",
"build": "webpack --config webpack.prod.js"
}
webpack.common.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: {
main: "./src/index.js"
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: {
attributes: true
}
}
]
},
{
test: /\.(svg|png|jpg|gif|webp|jpeg)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[hash].[ext]",
outputPath: "imgs"
}
}
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
webpack.dev.js
var path = require("path");
const { merge } = require("webpack-merge");
const common = require("./webpack.common");
module.exports = merge(common, {
mode: "development",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].bundle.js",
publicPath: "/"
},
devServer: {
historyApiFallback: true,
contentBase: "./dist"
}
});
webpack.prod.js
var path = require("path");
const { merge } = require("webpack-merge");
const common = require("./webpack.common");
const CompressionPlugin = require("compression-webpack-plugin");
const BrotliPlugin = require("brotli-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = merge(common, {
mode: "production",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].[hash].bundle.js"
},
devtool: "source-map",
performance: {
hints: false
},
optimization: {
splitChunks: {
chunks: "all"
},
minimizer: [
new TerserPlugin({
parallel: true,
cache: true,
sourceMap: true
})
]
},
plugins: [
new CompressionPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
test: /\.(js|html|svg)$/,
threshold: 8192,
minRatio: 0.8
}),
new BrotliPlugin({
asset: "[path].br[query]",
test: /\.(js|html|svg)$/,
threshold: 10240,
minRatio: 0.8
})
]
});
.babelrc
{
"presets": ["#babel/preset-env", "#babel/preset-react"],
"plugins": [["#babel/transform-runtime"]]
}
THX for any help.
If you run the build script you will get the optimized code that you can deploy on a webserver. Running npx serve build would be an easy way to simulate a webserver with the bulid files. I guess the dist script does the same using the webpack dev server.
Text compression is something you would normally configure on the webserver or proxy that hosts your website. I guess these webpack plugins do the same thing but it's normally a one liner in a webserver or proxy and you don't have to interfere with the create-react-app standard config.
Text compression examples:
Express.js
Nginx
Here the solution:
I added server.js
const express = require("express");
const path = require("path");
const port = 8080;
const app = express();
app.get("*.js", (req, res, next) => {
req.url = req.url + ".br";
res.set("Content-Encoding", "br");
res.set("Content-Type", "application/javascript; charset=UTF-8");
next();
});
app.use(express.static("./dist"));
app.get("*", (req, res) => {
res.sendFile(path.resolve("./dist", "index.html"));
});
app.listen(port);
console.log("Server started");
Also changed my package.json
"scripts": {
"stard": "webpack-dev-server --config webpack.dev.js --open --progress --colors --hot",
"build": "webpack --config webpack.prod.js",
"prod": "node server.js"
},
had to add to my webpack.prod.js publicPath: "/"
...
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].[hash].bundle.js",
publicPath: "/"
},
...

Turn off hot reloading on webpack

I created a reactjs app with webpack. Everything works fine on local. Just by using npm start. I want to deploy a simple package for prod with webpack -p command. it gave me a bundle.js I appended it, and it works fine too. but it is still looking for my local server running as part of hot reloading config. I changed hot:false, but its still looking for it.
here is my webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://csd.local.com:3000',
'webpack/hot/only-dev-server',
'./src/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production')})
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'src')
},
{ test: /\.scss$/,
loaders: ["style", "css", "sass"],
include: path.join(__dirname, 'src')
}
]
}
};
And here is my server.js
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: false,
historyApiFallback: true
}).listen(3000, 'localhost', function (err, result) {
if (err) {
return console.log(err);
}
console.log('Listening at http://csd.local.com:3000/');
});
All I want is, turn off hot reloading in prod.
That's because you're telling webpack to bundle HMRE's client-side scripts together with your app:
'webpack-dev-server/client?http://csd.local.com:3000',
'webpack/hot/only-dev-server',**strong text**
The solution would be to detect wether you're in "development" or "production" environment. To do so you can use "yargs" to parse your cli arguments (it's a webpack dependency so you don't even have to install it), and use the result to dynamically build your config.
var production = require('yargs').argv.p;
See a complete example at http://pastie.org/10895795

Using Webpack for hot-loader and generating a physical file w/ ReactJs ES6

I have a ReactJs ES6 (ie 'import' keywords) app that uses gulp for generating a physical build file and webpack for hot-loading the changes to a virtual file. I wanted to combine the two services with npm start (which current loads webpack, not gulp).
server.js file
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true
}).listen(3000, 'localhost', function (err, result) {
if (err) {
console.log(err);
}
console.log('Listening at localhost:3000');
});
webpack.config.js file
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./src/index.js'
],
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'build'),
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
resolve: {
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [{
test: /\.jsx?$/,
loaders: ['react-hot', 'babel-loader'],
include: path.join(__dirname, 'src'),
exclude: /node_modules/
},
{ test: /\.css$/, loader: 'style-loader!css-loader' }
]
}
};
I thought based on webpack's output section, webpack would generate a physical file in my build folder while creating a virtual file in '/static/bundle.js'
Currently, the virtual file with hot-loader is working, but no physical file has been built in the 'build' path.
Am I correct that webpack can replace gulp and generate both a physical & virtual build file? If so, where is my code in err as far as creating a physical build file?
Thanks in Advance.
Solution:
My code is fine, I needed to add to my scripts in package.json:
.....
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"gulp": "gulp",
"all": "npm run build && npm run gulp"
.....
I then run "npm run all" and I can run webpack and gulp from one command

Resources