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"
}
}
};
Actually it is not a matter of
webpack
orwebpack-dev-server
but of you php.I had the same problem, and similar setup. I ended up with php variable that will contain
/dist/bundle.js
on production andhttp://localhost:3000/bundle.js
on development.The conditional was if the site is served from the production domain or not.
Then with that variable you can concat the location of your js file on your main template php file.
Hope that helps