I am currently trying to get a better understanding of webpack and webpack-dev-server.
I have the following setup: A php site serves a react app and I want hot module replacement (HMR) for development purposes, while being on this site. Because I don't want my webpack-dev-server to serve my whole page, I tried to have it serve my bundle.js, which I then include in my php file manually at the moment:
<script src="https://localhost:8877/dist/elements.bundle.js"></script>
The problem is that for production I have to change this url by hand to something like /dist/elements.bundle.js
, because the bundle will not be served by the dev-server on the server.
I read a lot about webpack-dev-server/client?https://localhost:8877
and
webpack/hot/only-dev-server
and if I understood it corretly, those entries will redirect to the webpack-dev-server url?
If I run my npm start
-script with webpack-dev-server --config webpack.dev.js
, this will not build my elements.bundle.js in the filesystem, but only serve it from the dev-server's memory. In this case, I cannot include the local bundle.js but have to use the one from localhost:8877
. But how can I have webpack compile the entry point and webpack-dev-server do it's job at the same time with one command?
If I run webpack --config webpack.dev.js
and webpack-dev-server --config webpack.dev.js
in two terminals, then I can include /dist/elements.bundle.js
in my php file, but HMR is not working anymore, as it tells me it has to reload the whole page.
I am really trying to understand the concepts and I would be very glad, if someone could give me some advice and help me setting up my project correctly.
How can I switch between development and production without changing the script tag in my php file and with support of HMR and react-hot-loader?
This is my webpack.dev.js:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const development = process.env.NODE_ENV !== "production";
module.exports = merge(common, {
devtool: 'inline-source-map',
watch: development
});
This is my webpack.common.js:
const path = require('path');
const webpack = require('webpack');
require("babel-polyfill");
const development = process.env.NODE_ENV !== "production";
module.exports = {
context: path.resolve(__dirname, "webroot"),
devtool: 'cheap-eval-source-map',
entry: {
elements: [
'babel-polyfill',
'react-hot-loader/patch',
'webpack-dev-server/client?https://localhost:8877',
'webpack/hot/only-dev-server',
'./js/elements.client.js'
]
},
output: {
path: path.resolve(__dirname, "webroot", "js", "dist"),
filename: "[name].bundle.js",
publicPath: "https://localhost:8877/dist/"
},
plugins: [
new webpack.DefinePlugin({
DEVELOPMENT: JSON.stringify(development)
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin()
],
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['react-hot-loader/babel','react-html-attrs', 'transform-decorators-legacy', 'transform-class-properties'],
}
}
]
},
devServer: {
hot: true,
https: true,
inline: true,
host: 'localhost',
port: 8877,
contentBase: path.resolve(__dirname, "webroot"),
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
}
}
};