Webpack Dev Server with React Hot Loader - reactjs

I have a webpack configuration that works perfect in itself. I'm trying to install React Hot Loader together with HMR as suggested, which require webpack-dev-server. Here I cannot get it to work. I can not find where my bundle is located. I want it to be just at localhost:3000.
My webpack.config.js:
var webpack = require('webpack');
var path = require('path');
module.exports = {
watch: true,
devtool: 'eval',
// entry: './src/main.js', This runs just for webpack bundling
entry:[
'webpack-dev-server/client?http:localhost:9000', // WebpackDevServer host and port
'webpack/hot/only-dev-server', // "only" prevents reload on syntax errors
'./src/main.js' // Your appʼs entry point
],
output: {
path: path.resolve(__dirname, 'public', 'dist'),
filename: 'main.js'/*,
publicPath: '/dist/'*/
},
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel-loader?cacheDirectory=true,presets[]=react,presets[]=es2015'],
exclude: function(path) {
var isModule = path.indexOf('node_modules') > -1;
var isJsaudio = path.indexOf('jsaudio') > -1;
if (isModule && !isJsaudio) {
return true;
}
}
}, {
test: /\.json$/,
loader: "json-loader"
}]
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
resolve: {
extensions: ['', '.js', '.json', 'index.js'],
root: [
path.resolve(__dirname, 'src'),
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, 'node_modules', 'jsaudio', 'src')
]
},
target: 'web',
node: {
fs: 'empty',
net: 'empty',
tls: 'empty'
}
};
And the webpack-server.js:
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
new WebpackDevServer(webpack(config), {
publicPath: '/dist/',
hot: true,
historyApiFallback: true
}).listen(9000, 'localhost', function (err, result) {
if (err) {
return console.log(err);
}
console.log('Listening at http://localhost:9000/');
});
Update: The linked question does not help, especially since it does not even have a confirmed answer.

I would suggest trying out react-hot-loader v3 as the updates to get hot-reloading working have been simplified (in my opinion!).
in webpack then try point now only needs:
entry: {
app: [
'react-hot-loader/patch',
'webpack-hot-middleware/client',
`${SRC}/client-entry.js`
]
}
here is a link to an example app, react-lego that i've created to help people add react-hot-loader v3 to their apps. hope it helps

Related

webpack dev server not allowing POST fetch request - react app

I am developing my first webapack-react app using webpack-dev-server, however I am running into issues sending POST requests to my flask backend api as I keep getting a 400 bad request error. Here is my post request:
fetch('/api/login', {
method: 'post',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({"first_name": "name"})
});
If I tweak the above to a GET request (and remove body), the request goes through fine and I the api returns data.
Digging a little deeper, it seems as though webpack-dev-server doesn't permit POST requests - have I understood that correctly and is there a workaround?
Here is my webpack dev configuration:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
host:'0.0.0.0',
hot: true,
historyApiFallback: true,
proxy: {
'/api': {
target: 'http://flaskapp:5090',
pathRewrite: {'^/api': ''},
secure: false,
}
},
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
});
This is by no means the accepted answer. I'm just sharing my Webpack file to how I got it to work.
Here is my webpack.config file. I had the same issue the other day with making fetch requests with POST. However, I looked online to see if I could remove the /api from my fetch requests so I tried the rewrite module and it didn't work for me so I just removed it. In my fetch requests if I wanted to fetch something for example it would be /api/signup for example and my fetch worked. I also set up my proxy in webpack not in package.json
const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const HtmlWebPackPlugin = require('html-webpack-plugin');
var browserConfig = {
devServer: {
historyApiFallback: true,
proxy: {
"/api": "http://localhost:3012"
}
},
entry: ['babel-polyfill', __dirname + '/src/index.js'],
output: {
path: path.resolve(__dirname + '/public'),
filename: 'bundle.js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
query: {
presets: ['react', 'env', 'stage-0']
}
}
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './public/index.html',
})
]
}
var serverConfig = {
target: 'node',
externals: [nodeExternals()],
entry: __dirname + '/server/main.js',
output: {
path: path.resolve(__dirname + '/public'),
filename: 'server.js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
query: {
presets: ['react', 'env', 'stage-0']
}
}
}
]
}
}
module.exports = [browserConfig, serverConfig]

material-ui.dropzone: You may need an appropriate loader to handle this file type

Integrating material-ui-dropzone in my React app, I got this error:
./~/material-ui-dropzone/src/index.jsx Module parse failed:
...\client\node_modules\material-ui-dropzone\src\index.jsx Unexpected
token (123:26) You may need an appropriate loader to handle this file
type. SyntaxError: Unexpected token (123:26)
Here is my webpack configuration:
const Path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const Webpack = require('webpack'); const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = (options) => { const ExtractSASS = new ExtractTextPlugin(`/styles/${options.cssFileName}`);
const webpackConfig = {
devtool: options.devtool,
entry: [
`webpack-dev-server/client?http://localhost:${+ options.port}`,
'webpack/hot/dev-server',
Path.join(__dirname, '../src/app/index'),
],
output: {
path: Path.join(__dirname, '../dist'),
filename: `/scripts/${options.jsFileName}`,
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
module: {
loaders: [{
test: /.jsx?$/,
include: Path.join(__dirname, '../src/app'),
loader: 'babel',
}],
},
plugins: [
new Webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(options.isProduction ? 'production' : 'development'),
},
"global.GENTLY": false
}),
new HtmlWebpackPlugin({
template: Path.join(__dirname, '../src/index.html'),
}),
],
node: {
__dirname: true,
},
};
if (options.isProduction) {
webpackConfig.entry = [Path.join(__dirname, '../src/app/index')];
webpackConfig.plugins.push(
new Webpack.optimize.OccurenceOrderPlugin(),
new Webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false,
},
}),
ExtractSASS
);
webpackConfig.module.loaders.push({
test: /\.scss$/,
loader: ExtractSASS.extract(['css', 'sass']),
}); } else {
webpackConfig.plugins.push(
new Webpack.HotModuleReplacementPlugin()
);
webpackConfig.module.loaders.push({
test: /\.scss$/,
loaders: ['style', 'css', 'sass'],
});
webpackConfig.devServer = {
contentBase: Path.join(__dirname, '../'),
hot: true,
port: options.port,
inline: true,
progress: true,
historyApiFallback: true,
stats: 'errors-only',
}; }
return webpackConfig;
};
Babel config file is:
{
"presets": ["react", "es2015", "stage-1"]
}
It is the only library I had problems with. Any idea where might be the problem?
if you are using webapck#3.x
Try to modify your babel loader to
module: {
rules: [
{
test: /\.jsx?$/,
include: Path.join(__dirname, '../src/app'),
use: {
loader: 'babel-loader',
options: {
presets: ["react", "es2015", "stage-1"],
}
}
}
]
}
You can reference here https://webpack.js.org/loaders/babel-loader/
Noted that in your loader config, write babel-loader instead of just babel. Also make sure if you have npm install the right babel npm packages to the devDependencies, which depends on your webpack version.
If it does not solve your problem, paste your package.json file so i can get to know your webpack version.
Cheers.

ReactJS App on PHP backend - how to hot reload on local machine?

I am developing a ReactJS-App that gets served by a PHP backend. On my local machine I set up MAMP with a virtual host pointing to my project's root and I use webpack to bundle my React-App.
Since I really enjoy working with hot reloading I now try to use the webpack dev server to proxy MAMP and benfit from its react hot loading capabilities.
I haven't been able to get it working yet and I hope for someone to help me with the configuration. Or isn't my approach basically working? Anyway, I'll be happy if you help me out with this. Thanks in advance! Here's my webpack config so far:
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
module.exports = {
devtool: 'cheap-module-source-map',
devServer: {
port: 3000,
proxy: {
'*': {
target: 'http://my-virtual-host.dev:8888/',
}
}
},
entry: [
'./src/app.jsx'
],
output: {
path: path.join(__dirname, 'build'),
filename: 'bundle.js',
publicPath: 'http://localhost:3000/build/'
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
loaders: [
{
enforce: 'pre',
test: /\.jsx?$/,
include: [
path.resolve(__dirname, 'src'),
],
loader: 'eslint-loader',
},
{
test: /\.jsx?$/,
include: [
path.resolve(__dirname, 'src'),
],
loader: 'react-hot-loader'
},
{
test: /\.jsx?$/,
include: [
path.resolve(__dirname, 'src'),
],
loader: 'babel-loader',
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: { importLoaders: 1 },
},
'postcss-loader',
],
}),
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new ExtractTextPlugin('bundle.css'),
new StyleLintPlugin({
configFile: '.stylelintrc',
context: 'src',
files: '**/*.pcss'
})
]
};
Okay, I found the solution! My fault: I was thinking that my webpack dev server should "proxy" every request to MAMP and return its response. Putting in the other way around solved my Problem: MAMP serves my PHP Application and the webpack dev server only its assets.
When in development mode my PHP Application links assets to the webpack dev server (this discussion around a github issue helped me a lot: https://github.com/webpack/webpack-dev-server/issues/400).
Now, the main attributes I changed in my webpack config are:
module.exports = {
devServer: {
proxy: {
'*': {
target: 'http://my-virtual-host.dev:8888/',
changeOrigin: true,
}
}
},
entry: [
'webpack-dev-server/client?http://localhost:8080/',
'webpack/hot/only-dev-server', // Enable hot reloading
'./src/app.jsx'
],
output: {
path: path.join(__dirname, 'build'),
filename: 'bundle.js',
publicPath: 'http://localhost:8080/build/'
},
}
Linking assets for example to http://localhost:8080/build/app.js, the proxy settings and the output.publicPath did the trick. Hot reloading works fine.
Although it works for me now I'm still interessted in your thoughts!

Webpack server configuration + external libs

I have the following webpack configuration file:
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const LiveReloadPlugin = require('webpack-livereload-plugin');
const path = require('path');
module.exports = {
entry: [
'webpack-dev-server/client?http://0.0.0.0:2000', // WebpackDevServer host and port
'webpack/hot/only-dev-server', // "only" prevents reload on syntax errors
'./app/index.tsx'
],
output: {
path: __dirname + '/dist/',
filename: 'bundle.js'
},
devtool: 'source-map',
resolve: {
extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js']
},
module: {
loaders: [
{
test: /\.tsx?$/,
loaders: ['react-hot', 'ts'],
include: path.join(__dirname, 'app')
}
],
preLoaders: [
'source-map-loader'.
{test: /\.js$/, loader: 'source-map-loader'}
]
},
plugins: [
new CopyWebpackPlugin([
{from: './app/index.html', to: './dist/index.html'}
]),
new webpack.HotModuleReplacementPlugin()
],
builds.
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
}
};
and here is my server configuration:
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const config = require('./webpack.config');
new WebpackDevServer(webpack(config), {
contentBase: './dist',
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true,
open: 'http://localhost:2000'
}).listen(2000, 'localhost', function (err, result) {
if (err) {
return console.log(err);
}
console.log('Listening at http://localhost:2000/');
});
I want to be able to access the application from root path: http://localhost:2000 and not http://localhost:2000/dist.
One more thing, is there any way to move all the external dependancies from node_modules to dist with webpack (without the need to include the script tag in the index.html file)?
First of all for set application start point you need to set publicPath to "/" or publicPath: 'http://localhost:2000'
Your second question
Is there any way to move all the external dependancies from node_modules to dist with webpack?
Yes
You can use different file just for external modules and bundle that file. You don't need to take care of index.html file let webpack plugin HtmlWebpackPlugin take care of it.
First step set entry points for your app
entry: {
'vendors': './src/vendors.ts',//your external libraries
'app': './src/main.ts' //your app
}
and out put
output: {
publicPath: '/',
filename: '[name].js'//this will generate two different files app.js, vendor.js
}
How to add HtmlWebpackPlugin?
Add this in you plugins
new HtmlWebpackPlugin({
template: "./src/index.html",
minify:false
})
Now it will place script tags for you
on you server configuration change your public path to
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

Resources