React production shows blank page - reactjs

i have a problem with a webpack build, the command i run is
cross-env NODE_ENV=production webpack --config webpack.prod.js
and the file webpack prod is:
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var path = require('path');
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
module.exports = webpackMerge(commonConfig, {
devtool: 'source-map',
output: {
path: path.join(process.cwd(), '/public'),
publicPath: '/',
filename: '[name].[hash].js'
},
plugins: [
//new webpack.NoErrorsPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
mangle: {
keep_fnames: true,
except: ['$super']
}
}),
new ExtractTextPlugin('[name].[hash].css'),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
]
});
webpack.common.js is
var webpack = require('webpack');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var path = require('path');
var pkgBower = require('./package.json');
module.exports = {
entry: {
'app': './main.js'
},
resolve: {
root: path.join(__dirname, ''),
modulesDirectories: ['node_modules', 'bower_components'],
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [...]
},
devServer: {
outputPath: path.join(__dirname, 'public')
},
plugins: [
new HtmlWebpackPlugin({
template: process.env.NODE_ENV == 'development' ? 'index.html' : 'index.prod.html',
baseUrl: process.env.NODE_ENV == 'development' ? '/' : '/'
})
]
};
i can run the build but unfortunatelly when i open index.html it shows a blank page to me, i want to include this SPA in a spring boot project but I do not know how ;)
Thanks!

Solved! was a problem of "browserHistory"
If you use the "browserHistory" as history manager your webpack needs a node.js server to run, using a "hashHistory" you can use it as a normal web page!
See
Why is React Webpack production build showing Blank page?

First things first, which version of webpack are you using Lorenzo? Probably due to syntax, it's 1.X.
First, check in your package.json file which version is. Then, if it's really 1.x you can build in debug mode.
export default {
entry: [
'./src/Client.js'
],
debug: true
}
Inside your webpack.common.js
Check the error, paste here.
I hope it helps, welcome to StackOverflow, here are a few notes that can improve our community =)

Try to put "main":"index.js" in package.json file
That solved my problem.
"main": "index.js",
"scripts": {
...
},
Happy to help.

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/

How to set environment variables on React with custom webpack

My React app isn't run by create-react-app, but a custom Webpack config.
I"ve installed dotenv / dotenv-expand / and also dotenv-webpack.
I have .env / .env.development files with API_URL variable in it.
On my url file,
const { API_URL } = process.env
and use this API_URL to fetch data.
But on this file, when I console.log(process.env), it is empty.
I also have tried to update webpack.config.js file with
const Dotenv = require('dotenv-webpack');
and
new Dotenv()
in plugins array.
But still doesn't work.
I also tried having variable name REACT_APP_API_URL but was same result.
Could anyone help me to set the env vars?
Thank you.
webpack.config.js
const webpack = require('webpack')
const Dotenv = require('dotenv-webpack');
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpackMerge = require('webpack-merge')
const modeConfig = env => require(`./build-utils/webpack.${env}`)(env)
const presetConfig = require('./build-utils/loadPresets')
module.exports = ({ mode, presets } = { mode: 'production', presets: [] }) => {
console.log('mode', mode, 'presets', presets)
return webpackMerge(
{
mode,
module: {
rules: [
{
test: /\.(png|jpe?g|svg)$/,
use: {
loader: 'file-loader',
options: {
name: 'assets/[name].[ext]',
}
},
},
],
},
node: {
fs: 'empty'
},
resolve: {
extensions: ['.js', '.json'],
},
output: {
filename: 'bundle.js',
chunkFilename: '[name].lazy-chunk.js',
path: path.resolve(__dirname, 'build'),
publicPath: mode === 'development' ? '/' : './'
},
devServer: {
historyApiFallback: true
},
plugins: [
new HtmlWebpackPlugin({
template: './build-utils/template.html'
}),
new webpack.ProgressPlugin(),
new Dotenv()
]
},
modeConfig(mode),
presetConfig({ mode, presets })
)
}
If you're trying to access the env values in your JS files, you typically need to have the dotenv plugin.
const webpack = require('webpack')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpackMerge = require('webpack-merge')
require('dotenv').config() // may need to set path to your .env file if it isn't at the root at the project
const modeConfig = env => require(`./build-utils/webpack.${env}`)(env)
const presetConfig = require('./build-utils/loadPresets')
module.exports = ({ mode, presets } = { mode: 'production', presets: [] }) => {
return webpackMerge(
...
plugins: [
new HtmlWebpackPlugin({
template: './build-utils/template.html'
}),
new webpack.ProgressPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
SOME_VALUE: JSON.stringify(process.env.SOME_VALUE),
...
}
})
]
},
...
)
}
NOTE: With this implementation you won't be able to do
const { API_URL } = process.env because DefinePlugin does a search and replace of the JavaScript where it will look up any references to process.env.API_URL and replace it with whatever that value is. Therefore API_URL won't exist on porcess.env, so to use it just do process.env.API_URL
You could also use dotenv-webpack, I think you were close to getting it to work.
const webpack = require('webpack')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpackMerge = require('webpack-merge')
const Dotenv = require('dotenv-webpack');
const modeConfig = env => require(`./build-utils/webpack.${env}`)(env)
const presetConfig = require('./build-utils/loadPresets')
module.exports = ({ mode, presets } = { mode: 'production', presets: [] }) => {
return webpackMerge(
...
plugins: [
new HtmlWebpackPlugin({
template: './build-utils/template.html'
}),
new webpack.ProgressPlugin(),
new Dotenv({
path: envPath
})
]
},
...
)
}
If you need more help please share more details in by creating a Minimal, Reproducible Example.

Webpack stopped transpiling React

I've been using WebPack v2.6.1 to transpile and bundle my react jsx code. I did not change anything. All of a sudden, WebPack stopped transpiling and bundling my React code for production.
Below is a part of the error messages I'm getting:
When I use webpack dev server, everything works perfectly fine. This is happening when I try to go to production. WebPack seems to be producing the bundled output files but when I try to pull up the page, they don't come up. I'm issuing the same webpack --env.process command I've always used. In the browser, this is the error I'm getting which is preventing my React component from displaying.
My webpack.config.js file is below. Any idea what's happening here?
var IS_DEV = false; // change to false if building production files
var webpack = require('webpack');
var path = require("path");
// Define plugins needed for production and dev cases
var _pluginsDev = [
new webpack.ProvidePlugin({
'fetch': 'imports-loader?this=>global!exports-loader?global.fetch!whatwg-fetch',
moment: 'moment',
ps: 'perfect-scrollbar'
}),
];
var _pluginsProd = [
new webpack.ProvidePlugin({
'fetch': 'imports-loader?this=>global!exports-loader?global.fetch!whatwg-fetch',
moment: 'moment',
ps: 'perfect-scrollbar'
}),
new webpack.DefinePlugin({ // Minimizer, removing multiple occurances of imports et.c
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
minimize: true,
compress: true,
output: { comments: false }
})
];
var _devtool = IS_DEV ? 'eval' : 'cheap-module-source-map';
var _plugins = IS_DEV ? _pluginsDev : _pluginsProd;
var _fileName = IS_DEV ? "./build/[name]-bundle.js" : "./dist/[name]-bundle.js";
var _bundles = {
home: './UI/components/home/home.jsx',
accounts: './UI/components/accounts/accounts.jsx',
contacts: './UI/components/contacts/contacts.jsx',
projectsList: './UI/components/projects/projects_list/projectsList.jsx'
};
module.exports = {
entry: _bundles,
output: {
path: path.resolve(__dirname, "wwwroot"),
publicPath: "/",
filename: _fileName
},
devtool: _devtool,
plugins: _plugins,
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ['es2015', 'stage-2', 'stage-0', 'react']
}
}
}
]
},
resolve: {
extensions: ['.js', '.jsx']
}
}

webpack DefinePlugin use external config.js

I am new in webpack
I have this code in webpack.config.js
var path = require('path');
var webpack = require('webpack');
var pkg = require('./package.json');
var myconfig = require('./webpack.myconfig.js');
// bundle dependencies in separate vendor bundle
var dependencies = Object.keys(pkg.dependencies).filter(function (el) {
//exclude font packages from vendor bundle & css-toggle-switch
if (el.indexOf('font') !== -1 || el.indexOf('css-toggle-switch') !== -1) {
return false;
}
else return true;
});
module.exports = {
entry: {
libs: dependencies,
main: './src/index'
},
output: {
path: path.join(__dirname, myconfig.buildPath),
publicPath: myconfig.uiURL,
filename: 'dist/js/[name].js',
chunkFilename: '[id].[name].js'
},
plugins: [
new webpack.DefinePlugin({
DEBUG_MODE: JSON.stringify(false),
TIMEOUT: JSON.stringify(30000),
API_URL: JSON.stringify(myconfig.apiUrl),
"process.env": {
NODE_ENV: JSON.stringify("production")
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'libs',
filename: 'dist/js/libs.js',
minChunks: Infinity
})
],
};
and this is myconfig.js
myconfig = {
uiURL: 'http://example.com/',
apiUrl: 'http://api.example.com/api/'
};
module.exports = myconfig;
and if I run this syntax
webpack -p --config webpack.config.js --progress --colors
I will get the result like
/dist/js/libs.js
/dist/js/main.js
but I want the result not like this, I want the result to be:
/dist/js/myconfig.js
/dist/js/libs.js
/dist/js/main.js
What really I want is,
I want in main.js file, it will use myconfig.apiUrl as depedencies,
so when I deployed to production or qserver, I just change myconfig.js.
Thank you
webpack.myconfig.js is used in webpack config file so you have to rebuild every time when webpack.myconfig.js is changed.
You could use myconfig.json and send http request to get it dynamically.
If you just want to get myconfig.js in /dist/js/, you can use CopyWebpackPlugin. It can copy static files from one path to another.
Add a new new line plugins section like :
plugins: [
new CopyWebpackPlugin([{ from: APP_DIR + '\\images', to: APP_DIR + '\\build\\images' }]),
new webpack.DefinePlugin({
DEBUG_MODE: JSON.stringify(false),
TIMEOUT: JSON.stringify(30000),
API_URL: JSON.stringify(myconfig.apiUrl),
"process.env": {
NODE_ENV: JSON.stringify("production")
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'libs',
filename: 'dist/js/libs.js',
minChunks: Infinity
})
],
Here CopyWebpackPlugin copies file from one path to another.
Make sure you var CopyWebpackPlugin = require('copy-webpack-plugin');at top of webpack.config.js & added same in package.json & installed via npm.

variable config file based on environment - reactjs, webpack

I need bunch of global variables in my reactjs components(example: hostnames, token, api urls, etc) based on the environment. but I don't want to add it to the js individually. I would like to create project.config file to set up prod:{hostname:example.com, api-url:prod, etc} and dev:{hostname:localhost.com, api-url:dev, etc}, I installed loose-envify, but I have to specify for each var.
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://example.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')}),
new ExtractTextPlugin("static/super.css", {
allChunks: true
})
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'src')
},
{ test: /\.scss$/,
loaders: ["style", "css", "sass"],
include: path.join(__dirname, 'src')
}
]
}
};
Did you try to stringify a config json that can have some common and overridden properties for dev or prod?
Which will be given to the new webpack.DefinePlugin({...})?
I was trying to try something similar and tried following which seems to work fine.
In your webpack config add a DefinePlugin. Following is my webconfig:-
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(process.env.environment),
}
})
],
Now while compiling use the following commands:-
environment=local webpack (for local)
environment=development webpack(for dev)
environment=production webpack(for prod)
Now if you see I have set 'NODE_ENV' with the cli input so when 'NODE_ENV' is production as value, the webpack automatically minifies your output bundle.
Now say you have API url declared in a file(I had Constants.jsx), so I added following to constants.jsx. So basically you can read the NODE_ENV set in webpack config in this Constants.jsx and import them in your components from where APIS are called by exporting it from here.
const api_url=function(){
let api_url='';
if(process.env.NODE_ENV == 'local'){
api_url= 'http://localhost:8002/api/v0';
}
else if(process.env.NODE_ENV == 'development'){
api_url = 'https://development/api/v0';
}
else if(process.env.NODE_ENV == 'production'){
api_url = 'https://production/api/v0';
}
return api_url;
}
export const url= api_url();
Hope it helped!

Resources