React-hot-loader with SSR - reactjs

I'm trying to figure out how to correctly implement react-hot-loader in my new SSR app, I've been able to do it fine in previous projects but I'm new to SSR so can't figure it out.
Here is my webpack.config.client:
const path = require("path");
const merge = require("webpack-merge");
const baseConfig = require("./webpack.config.base.js");
const client_path = path.resolve(__dirname, "public");
const config = {
name: "client",
target: "web",
entry: ["react-hot-loader/patch", "./src/client/client.js"],
output: {
path: client_path,
filename: "bundle.js"
},
resolve: {
extensions: [".js", ".jsx"]
}
};
module.exports = merge(baseConfig, config);
Here is my webpack.config.server:
const path = require("path");
const merge = require("webpack-merge");
const baseConfig = require("./webpack.config.base.js");
const webpackNodeExternals = require("webpack-node-externals");
const server_path = path.resolve(__dirname, "build");
const config = {
target: "node",
name: "server",
entry: ["react-hot-loader/patch", "./src/index.js"],
output: {
filename: "bundle.js",
path: server_path
},
resolve: {
extensions: [".js", ".jsx"]
},
externals: [webpackNodeExternals()]
};
module.exports = merge(baseConfig, config);
and webpack.config.base;
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
enforce: "pre",
loader: "babel-loader"
exclude: /node_modules/,
options: {
presets: [
"es2015",
"react",
"stage-0",
[
"env",
{ targets: { browsers: ["last 2 versions"] } }
]
],
plugins: [
"react-hot-loader/babel",
["transform-class-properties", { spec: true }]
]
}
}]
}
};
and package.json scripts:
"scripts": {
"dev": "npm-run-all --parallel dev:*",
"dev:server": "nodemon --w build --exec \"node build/bundle.js\"",
"dev:build-server": "webpack --config webpack.config.server.js --w",
"dev:build-client": "webpack --config webpack.config.client.js --w"
},
and if helpful link to github - https://github.com/dmartss/health2

Related

WEBPACK with React router gives 404 while serving the build

Recently i am learning webpack with react and i build a app that runs wells in Dev enviroment but when i build the app and tries to change the route it throws 404 error.
Here are my webpack Config.
webpack.common.js
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
entry: path.resolve(__dirname, "..", "./src/index.tsx"),
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js"],
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
},
],
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test:/\.(?:ico|gif|png|jpg|jpeg)$/i,
type:'asset/resource'
},
{
test:/\.(woff(2)?|eot|ttf|otf|svg)$/i,
type:'asset/inline'
}
],
},
output: {
path: path.resolve(__dirname, "..", "./build"),
filename: "bundle.js",
},
plugins: [
new HTMLWebpackPlugin({
template: path.resolve(__dirname, "..", "./public/index.html"),
filename:'index.html'
}),
// new CopyWebpackPlugin({
// patterns:[{from:"src",to:'dest'}]
// })
],
};
webpack.dev.js
const ReactRefreshWebpackPlugin = require('#pmmmwh/react-refresh-webpack-plugin');
const path=require('path')
module.exports={
mode:"development",
devServer:{
hot:true,
open:true,
historyApiFallback: { index: "/", disableDotRule: true },
port:3001
},
devtool:'cheap-module-source-map',
plugins:[
new ReactRefreshWebpackPlugin()
]
}
webpack.prod.js
module.exports={
mode:"production" ,
}
i changed lots of configuration like public path and other, but it didn't help.

ReactJs Image Not found on production mode

I have pushed my app on my repo.
The images are imported to the path:
react-blog-app/blob/gh-pages/static/media/_resized_300.353f8ae3.jpg
However on the page the images are not found.
The URL is pointing to
react-blog-app/static/media/_resized_300.353f8ae3.jpg
I have added 'contentBane' on config.json
{
"apiEndpoint": "https://jsonplaceholder.typicode.com/posts" ,
"devServer": {
"contentBase": "./build"
}
}
Do you have any suggestion to fix this issue?
Thanks in advance.
I think you didn't add file-loader to module.rules. the code below is minimal webpack configuration for react app.
webpack.config.js
require("dotenv").config();
const path = require("path");
const webpack = require("webpack");
// Plugins
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
mode: process.env.NODE_ENV || "production",
entry: "./src/index.jsx",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
resolve: { extensions: ["*", ".js", ".jsx"] },
// externals: {
// "react-js": "React",
// "react-dom": "ReactDOM"
// },
module: {
rules: [
{
test: /\.(js|jsx|es6|es|mjs)$/,
include: path.resolve(__dirname, "src"),
exclude: /node_modules/,
use: ["babel-loader"]
},
{
test: /\.html$/,
use: ["html-loader"]
},
{
test: /\.css$/,
use: [
"style-loader",
"css-loader",
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ["file-loader"]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ["file-loader"]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: "./src/index.ejs",
filename: "index.html",
title: "My React App",
inject: "body",
scriptLoading: "defer",
cache: true
}),
new webpack.ProgressPlugin()
],
devtool: "source-map",
devServer: {
hot: true,
port: 8000,
open: true
}
};
.babelrc
{
"presets": ["#babel/preset-react"],
"env": {
"development": {
"presets": [["#babel/preset-react", { "development": true }]]
}
}
}
package.json
"scripts": {
"start:dev": "cross-env NODE_ENV=development \"webpack-dev-server\"",
"build": "webpack"
}

What's best way to config React components library with Webpack, typescript, css modules and SASS

I'm config a React components library for reuses in other our projects. I want to use these:
Typescript for components
Css modules
Sass
Webpack for bundle
So this is my webpack config:
const childProcess = require('child_process');
const path = require('path');
const url = require('url');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const loadersConf = require('./webpack.loaders');
const NPM_TARGET = process.env.npm_lifecycle_event; //eslint-disable-line no-process-env
const targetIsRun = NPM_TARGET === 'run';
const targetIsTest = NPM_TARGET === 'test';
const targetIsStats = NPM_TARGET === 'stats';
const targetIsDevServer = NPM_TARGET === 'dev-server';
const DEV = targetIsRun || targetIsStats || targetIsDevServer;
const STANDARD_EXCLUDE = [
path.join(__dirname, 'node_modules'),
];
// These files will be imported in every sass file
const sassResourcesPaths = [
path.resolve(__dirname, 'src/styles/abstracts/_variables.sass'),
path.resolve(__dirname, 'src/styles/abstracts/_mixins.sass'),
];
const config = {
module: {
rules: loadersConf,
},
resolve: {
modules: [
'node_modules',
path.resolve(__dirname),
],
extensions: ['.js', '.jsx', '.ts', '.tsx', '.css', '.scss'],
},
performance: {
hints: 'warning',
},
target: 'web',
plugins: [
new webpack.DefinePlugin({
COMMIT_HASH: JSON.stringify(childProcess.execSync('git rev-parse HEAD || echo dev').toString()),
}),
new MiniCssExtractPlugin({
filename: '[name].[contentHash].css',
chunkFilename: '[name].[contentHash].css',
}),
],
};
if (DEV) {
config.mode = 'development';
config.devtool = 'source-map';
}
const env = {};
if (DEV) {
} else {
env.NODE_ENV = JSON.stringify('production');
}
config.plugins.push(new webpack.DefinePlugin({
'process.env': env,
}));
module.exports = config;
And this is loaders for webpack:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const STANDARD_EXCLUDE = [
path.join(__dirname, 'node_modules'),
];
const NPM_TARGET = process.env.npm_lifecycle_event; //eslint-disable-line no-process-env
const targetIsRun = NPM_TARGET === 'run';
const targetIsTest = NPM_TARGET === 'test';
const targetIsStats = NPM_TARGET === 'stats';
const targetIsDevServer = NPM_TARGET === 'dev-server';
const DEV = targetIsRun || targetIsStats || targetIsDevServer;
// noinspection WebpackConfigHighlighting
module.exports = [
{
test: /\.(js|jsx|ts|tsx)?$/,
exclude: STANDARD_EXCLUDE,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
// Babel configuration is in .babelrc because jest requires it to be there.
},
},
},
{
type: 'javascript/auto',
test: /\.json$/,
include: [
path.resolve(__dirname, 'i18n'),
],
exclude: [/en\.json$/],
use: [
{
loader: 'file-loader?name=i18n/[name].[hash].[ext]',
},
],
},
// ==========
// = Styles =
// ==========
// Global CSS (from node_modules)
// ==============================
{
test: /\.css/,
include: path.resolve(__dirname, "node_modules"),
use: [
MiniCssExtractPlugin.loader,
{
loader: "style-loader"
},
{
loader: 'css-loader'
}
]
},
{
test: /\.(sc|sa|c)ss$/,
exclude: /\.st.css$/, //This must appear before the "oneOf" property
use: [
MiniCssExtractPlugin.loader,
'style-loader',
'css-modules-typescript-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true,
camelCase: "dashes",
localIdentName: DEV
? '[name]__[local]___[hash:base64:5]'
: '_[hash:base64:5]',
},
},
{
loader: "postcss-loader",
options: {
sourceMap: "inline",
extract: true,
}
},
"sass-loader",
],
},
{
test: /\.(png|eot|tiff|svg|woff2|woff|ttf|gif|mp3|jpg)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'files/[hash].[ext]',
},
},
{
loader: 'image-webpack-loader',
options: {},
},
],
},
];
Babel config:
const config = {
presets: [
['#babel/preset-env', {
targets: {
chrome: 66,
firefox: 60,
edge: 42,
safari: 12,
},
modules: false,
corejs: 3,
useBuiltIns: 'usage',
shippedProposals: true,
}],
['#babel/preset-react', {
useBuiltIns: true,
}],
['#babel/typescript', {
allExtensions: true,
isTSX: true,
}],
],
plugins: [
'#babel/plugin-transform-runtime',
'#babel/plugin-syntax-dynamic-import',
'#babel/proposal-class-properties',
'#babel/proposal-object-rest-spread',
'#babel/plugin-proposal-optional-chaining',
['module-resolver', {
root: ['./src', './test'],
}],
],
};
// Jest needs module transformation
config.env = {
test: {
presets: config.presets,
plugins: config.plugins,
},
};
config.env.test.presets[0][1].modules = 'auto';
module.exports = config;
This is a demo component of this library:
import React from 'react';
const styles = require('./style.scss');
type Props = {
children?: React.ReactNode;
openLeft?: boolean;
openUp?: boolean;
id?: string;
ariaLabel: string;
customStyles?: object;
}
export default class Button extends React.PureComponent<Props> {
public render() {
return (
<button className={styles.test}>
{this.props.children}
</button>
);
}
}
So, this is develop build command:
"build": "cross-env NODE_ENV=production webpack --display-error-details --verbose",
"run": "webpack --progress --watch",
when I using this library:
import ExampleComponent from 'mylibrary';
When I run BUILD or RUN command, the javascript is built, but not SCSS. So in my other project, the build throw an error:
can not find module './style.scss'
This error occur in ExampleComponent
Please tell me how to resolve it. Thanks you very much!
This is my webpack config for the styles part:
{
test: /\.s?css$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: 'css-loader'
},
{
loader: 'postcss-loader',
options: {
config: {
path: 'postcss.config.js'
}
}
},
{
loader: 'sass-loader'
},
]
}
and in my postcss.config.js:
module.exports = {
plugins: [
require('autoprefixer')
]
}

Window is not defined after a build with Webpack

I am developing a reactJS application and also I am using WebPack 4.29.6 the problem that I face here it is that locally it works everything perfect when I run the npm run dev command while when I want to deploy in server I don't know how to do it I am building the app with the build:production command then it generates /dist folder inside with all files now here I try to run bundle.js it gives me this error: ReferenceError: window is not defined.
these are command's that i use to start my app:
"scripts": {
"dev": "cross-env webpack-dev-server --config ./webpack.config.dev.js --mode development",
"build:production": "cross-env webpack --config webpack.config.production.js --mode production"
}
this is my webpack.config.common.js
const path = require('path');
const webpack = require('webpack');
const outputPath = path.join(__dirname, '/dist');
const port = process.env.PORT || 4000;
module.exports = {
context: __dirname,
entry: './src/index.jsx',
resolve: {
extensions: ['*', '.js', '.jsx'],
},
output: {
path: outputPath,
publicPath: '/',
filename: 'bundle.js',
sourceMapFilename: 'bundle.map',
},
devServer: {
port,
historyApiFallback: true,
compress: true,
contentBase: './dist',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader', 'eslint-loader'],
},
{
test: /\.less$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
},
],
},
{
test: /\.css$/,
use: ['css-loader'],
},
{
test: /\.svg$/,
loader: 'svg-inline-loader',
},
{
test: /\.(png|jpg|gif|woff(2)?|ttf|eot|svg)$/,
exclude: [
/\.(js|jsx|mjs)$/,
/\.html$/,
/\.json$/,
/\.(less|config|variables|overrides)$/,
],
use: [
{
loader: 'file-loader',
},
],
},
],
},
plugins: [
new webpack.ProvidePlugin({
Promise: 'es6-promise-promise',
}),
],
};
this is my webpack.config.dev.js
const webpack = require('webpack');
const merge = require('webpack-merge');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpackCommonConfig = require('./webpack.config.common');
module.exports = merge(webpackCommonConfig, {
mode: 'development',
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, '/index.html'),
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.EnvironmentPlugin({ NODE_ENV: 'development' }),
],
devtool: 'inline-source-map',
devServer: {
hot: true,
open: true,
},
externals: {
// global app config object
config: JSON.stringify({
apiUrl: 'http://localhost:3000',
}),
},
});
this is my webpack.config.production.js
const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const webpackCommonConfig = require('./webpack.config.common');
module.exports = merge(webpackCommonConfig, {
mode: 'production',
plugins: [new webpack.EnvironmentPlugin({ NODE_ENV: 'production' })],
optimization: {
minimizer: [
// we specify a custom UglifyJsPlugin here to get source maps in production
new UglifyJsPlugin({
cache: true,
parallel: true,
uglifyOptions: {
compress: false,
ecma: 6,
mangle: true,
},
sourceMap: true,
}),
],
},
devtool: 'source-map',
devServer: {
compress: true,
},
});
It may be late to answer but it may help someone else. I also had the ReferenceError: window is not defined. issue with Webpack 4, and found that adding globalObject: 'this' line to the output section in webpack config file fixed my problem:
output: {
globalObject: "this",
filename: "[name].js",
path: path.join(__dirname, "build/package"),
publicPath: "/resources/",
}
You can see the issue was discussed here
and the Webpack documentation about the globalObject setting here.
Using global worked for me.
const window = global.window
if (window && window.localStorage) {
const storageLogLevel = window.localStorage.getItem(LOG_LEVEL_KEY)
switch (storageLogLevel) {
case LogLevel.DEBUG:
logLevel = 0
break
case LogLevel.INFO:
logLevel = 1
break
case LogLevel.WARNING:
logLevel = 2
break
case LogLevel.CRITICAL:
logLevel = 3
break
default:
logLevel = 1
}
}

React App ignores NODE_ENV of the production mode

I'm fairly new to React and I've built a client side react app using webpack as module bundler and npm. It works smoothly in development with Webpack devServer. While in production, I've used express as a server. When running at localhost:8080, it displays fine but I get these warnings. I set up the NODE_ENV='production', but still same warnings.
Here is my production configuration file
production.config.js
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const webpack = require('webpack')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const config ={
devtool: 'cheap-module-source-map',
entry: [
'react-hot-loader/patch',
'./client/main.js'
],
output: {
path: path.resolve(__dirname, 'build'),
filename: 'app.bundle.js',
publicPath:'/'
},
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
//query: { sourceMap: false },
options: {
importLoaders: 1,
}
},
{
loader: 'postcss-loader'
}
]
})
},
{
test: /\.jsx?$/,
use: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpe?g|gif|svg|ico|\.woff$|\.ttf$|\.wav$|\.mp3$)$/i,
use: ['file-loader?name=img/[name].[ext]',
'image-webpack-loader']
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file-loader?name=fonts/[name].[ext]'
}
]
},
plugins: [
//index.html custom template
new HtmlWebpackPlugin({
title: 'Index',
template: './index.html'
}),
new webpack.EnvironmentPlugin(
{
'process.env':
{
NODE_ENV: JSON.stringify('production') }
}
),
//extract css files
new ExtractTextPlugin({filename:"styles.css",disable:false,allChunks:true}),
new UglifyJsPlugin({
sourceMap: false,
mangle: true,
beautify:false,
compress: {
warnings: false, // Suppress uglification warnings
pure_getters: true,
unsafe: true,
unsafe_comps: true,
screw_ie8: true
},
output: {
comments: false
}
})
]
};
module.exports=config
package.json
{
"name": "react-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"webpack": "webpack",
"dev": "webpack-dev-server --colors",
"prod": "npm run build && node deploy.js",
"build": "webpack --config production.config.js --progress --colors"
}
//dependencies are omitted
}
Try using this package: https://www.npmjs.com/package/cross-env
I believe there is a problem with setting NODE_ENV=production in windows command prompts which it solves.
Usage example:
Build script:
cross-env NODE_ENV=production webpack
webpack.config.js:
const webpack = require('webpack');
const env = process.env.NODE_ENV || 'production';
//...
plugins = [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(env)
}
})
]
//...
Hope that helps.

Resources