variable config file based on environment - reactjs, webpack - reactjs

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!

Related

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']
}
}

React + webpack dev environment setup - wrong filepath

I'm trying to set up a developer environment for React but I'm getting some issues with webpack pathing. Usually, a quick google solves issues like these but I haven't seen anyone with the same problem, which probably means I'm an idiot and is messing something up.
So, I followed a tutorial and I have a dev-folder and a output-folder. In output I have output.js, where I want webpack to output all my stuff. So, according to the guide, I should run ./node_modules/.bin/webpack and it should work with the config I have, but it's showing the wrong filepath. I want it to go to react-test/output/output.js but it's throwing in a /dev, making it react-test/dev/output/output.js. My webpack.config.js looks like this:
var webpack = require("webpack");
var path = require("path");
var DEV = path.resolve(__dirname, "dev");
var OUTPUT = path.resolve(__dirname, "output");
var config = {
entry: DEV + "/index.jsx",
output: {
path: OUTPUT,
filename: "output.js"
},
module: {
loaders: [{
include: DEV,
loader: "babel-loader"
}]
}
};
module.exports = config;
I can't see where dev is getting added.
I would modify the file to the following:
var path = require('path');
module.exports = {
entry: path.join(__dirname, '/dev/index.js'),
output: {
path: path.join(__dirname, '/output'),
filename: 'output.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015']
}
}
]
}
};
You don't need to require webpack in this file, but you do need to tell the module loader what to test. The presets I included are assuming you are using ReactJS and ES6, you may need to change them as appropriate.
webpack.config
var path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: './dev/index.js',
output: {
path: path.resolve(__dirname, 'output'),
filename: 'output.js',
publicPath: '/'
},
module: {
rules: [
{ test: /\.(js)$/, use: 'babel-loader' },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
]
},
devServer: {
historyApiFallback: true
},
plugins: [
new HtmlWebpackPlugin({
template: 'app/Index.html' // Copy Index.html with script tag refrencing output.js in Output folder
})
]
}
Try to set context option to react-test directory.
And set DEV and OUTPUT paths realtive to it:
var DEV = path.resolve(__dirname, "./dev");
var OUTPUT = path.resolve(__dirname, "./output");
var config = {
context: path.resolve(__dirname, './'),
entry: DEV + "/index.jsx",
output: {
path: OUTPUT,
filename: "output.js"
},
...

webpack.DefinePlugin is not recognized and devtool: 'cheap-module-source-map does not work

I am trying to reduce the size of react project for production by following this article http://moduscreate.com/optimizing-react-es6-webpack-production-build/. Unfortunately, some of the steps do not work. One of them is webpack.DefinePlugin, in webpack outputs the error that webpack.DefinePlugin cannot be defined. Maybe, it is because I build the project as in develoment and now i want to move it to production. Maybe, I had to create the project in production initially? Or anyone knows the better way to reduce the size of the project?
webpack.config.js
var path = require("path");
var webpack = require('webpack');
var DIST_DIR = path.resolve(__dirname, "dist");
var SRC_DIR = path.resolve(__dirname, "src");
var config = {
devtool: 'cheap-module-source-map',
entry: SRC_DIR + "/app/index.js",
output: {
path: DIST_DIR + "/app",
filename: "bundle.js",
publicPath: "/app/"
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
],
module: {
loaders: [
{
test: /\.js?/,
include: SRC_DIR,
loader: "babel-loader",
query: {
presets: ["react", "es2015", "stage-2"]
}
}
]
}
};
module.exports = config;
also, devtool: 'cheap-module-source-map' is not working, it did not reduce the size of the project at all.
Try
...
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
...
instead.
Also, devtool: 'cheap-module-source-map' is not for reducing the size of your bundle, it is for generating source maps.

React error even after using DefinePlugin

I am using React 15.4.2 and Redux 3.6.0 with Webpack and this is my webpack.config.js file contents: (some of the code is omitted for brevity)
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const pkg = require('./package.json');
const TARGET = process.env.npm_lifecycle_event;
const PATHS = {
src: path.join(__dirname, 'src/js'),
dist: path.join(__dirname, 'dist')
};
process.env.BABEL_ENV = TARGET;
const common = {
resolve: {
extensions: ['', '.js', '.jsx']
},
entry: {
app: PATHS.src
},
output: {
path: PATHS.dist,
publicPath: '/',
filename: '[name].[hash].js'
},
module: {
loaders: [
{ test: /\.jsx?$/, loaders: ['babel?cacheDirectory'], include: PATHS.src },
{ test: /\.scss$/, exclude: /node_modules/, loaders: ['style', 'css', 'sass'] },
{ test: /(\.ttf|\.woff2?|\.eot|\.svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, exclude: /node_modules/, loader: 'url' },
{ test: /\.(jpe?g|png|gif|svg)$/i, exclude: /node_modules/, loader: 'url?limit=10000!img?progressive=true' },
{ test: /\.json/, loaders: ['json']}
]
},
plugins: [
new HTMLWebpackPlugin({
template: 'src/index.html',
inject: 'body'
})
]
};
if (TARGET === 'build') {
module.exports = merge(common, {
entry: {
vendor: Object.keys(pkg.dependencies)
},
output: {
path: PATHS.dist,
filename: '[name].[chunkhash].js',
chunkFilename: '[chunkhash].js'
},
module: {
loaders: [
{ test: /\.css$/, loader: ExtractTextWebpackPlugin.extract('style', 'css'), include: PATHS.src }
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new CleanWebpackPlugin([PATHS.dist]),
new ExtractTextWebpackPlugin('[name].[chunkhash].css'),
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
})
]
});
}
Running npm run build gives the minified code. But it still gives the error
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 https://facebook.github.io/react/docs/optimizing-performance.html#use-the-production-build for more details.
I have also tried reordering the plugins in build TARGET, but its giving the same error.
What am I missing here?
P.S. Redux gives the same minification error too.
EDIT
This is my package.json build script:
"scripts": {
...
"build": "NODE_ENV=production webpack --progress"
...
}
EDIT #2
This is the output to a console.log statement from within the application.
You could use this syntax for the DefinePlugin.
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('production')
}
}),
I enabled source maps to see that its a package I have been using that was minified using non-standard ways. So, setting NODE_ENV to 'production' had no effect on the said package. Nevertheless, my Webpack config and my build scripts have been working perfectly fine. Thank you for your help guys!

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

Resources