Reputation: 34113
I'm using Webpack on a React project and it seems like HtmlWebpackPlugin
affects the webpack dev server in a weird way that I don't understand.
It seems to allow me to browse to index.html
no matter where that file is in the code base, something that is not possible using the dev server alone.
Let's say that I have the following directory structure:
myproj/
|- package.json
|- webpack.config.js
|- src/
|- index.html
|- index.jsx
and a webpack.config.js
file that looks like this:
const path = require('path');
module.exports = {
entry: './src/index.jsx',
devServer: {
contentBase: __dirname
}
};
Then I run webpack-dev-server --mode=development
. Since I have devServer.contentBase
set to the current directory (myproj
) and the index.html
file is inside myproj/src
, I must browse to http://localhost:8080/src/index.html
to see my web app. If I try browsing http://localhost:8080/index.html
then I get a 404. That makes sense to me.
Then I add the HtmlWebpackPlugin
, changing nothing else inside webpack.config.js
:
const HtmlWebpackPlugin = require('html-webpack-plugin');
....
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
Now all of a sudden I can browse to http://localhost:8080/index.html just fine. In fact, I can hit either http://localhost:8080/index.html
or http://localhost:8080/src/index.html
.
What's up with that? What did HtmlWebpackPlugin
do to make this possible?
Upvotes: 8
Views: 11321
Reputation: 34113
Okay, I think I figured this out.
Once you add HtmlWebpackPlugin
you should remove this line from index.html
:
<script type="text/javascript" src="main.bundle.js"></script>
and only browse to http://localhost:8080/index.html
.
Once you add in HtmlWebpackPlugin
, it takes your index.html
file and merges in a <script>
tag that points to your webpack bundle. It serves this merged html file from http://localhost:8080
. It does this even if index.html
already contains a reference to the bundle.
The plugin doesn't actually overwrite index.html
with the merged version. So browsing to http://localhost:8080/src/index.html
just shows you that file as it is on disk.
So if your src/index.html
file looks like this before you add HtmlWebpackPlugin
:
<body>
<div id="app">it worked</div>
<script type="text/javascript" src="main.bundle.js"></script>
</body>
then after you add HtmlWebpackPlugin
, browsing to http://localhost:8080
gives you this merged version:
<body>
<div id="app">it worked</div>
<script type="text/javascript" src="main.bundle.js"></script>
<script type="text/javascript" src="main.bundle.js"></script>
</body>
So now you will have two references to the bundle, the one you added in the file and the one HtmlWebpackPlugin
added.
Browsing to http://localhost:8080/src
gives you what's on disk at src/index.html
:
<body>
<div id="app">it worked</div>
<script type="text/javascript" src="main.bundle.js"></script>
</body>
However, since he whole point of using HtmlWebpackPlugin
is to let it insert the bundle reference for you, that means you should remove that <script>
tag from src/index.html
. That in turn means that browsing to src/index.html
won't work anymore because you no longer have a reference to your bundle!
You are now reliant on letting HtmlWepbackPlugin
insert the <script>
tag for you, which means that you must now browser to http://localhost:8080/index.html
to get the version it generated.
Webpack. Be. Crazy.
Upvotes: 7
Reputation: 1012
you do have access to both http://localhost:8080/index.html and http://localhost:8080/src/index.html. But the are served differently.
For http://localhost:8080/src/index.html, it is served by webpack-dev-server just like when HtmlWebpackPlugin is not included. If you check the response content of this url, you will find that is is identical with the content of src/index.html on your disk.
For http://localhost:8080/index.html, it is served by HtmlWebpackPlugin from memory. If you check the response content of this url, you will find that all your bundle file are added to the HTML(that's why we use it). For the filename, you can config it to anything you like with the 'filename' field(you can specify a subdirectory too). check https://github.com/jantimon/html-webpack-plugin#options for more detail.
Upvotes: 3
Reputation: 4000
As you have observed, when you are running webpack-dev-server
, all the webpack output files (including styles, scripts, and service workers), will be loaded from memory only. This will not write any files to configured output directory.
From Webpack-dev-server docs,
This modified bundle is served from memory at the relative path specified in publicPath (see API). It will not be written to your configured output directory. Where a bundle already exists at the same URL path, the bundle in memory takes precedence (by default).
Upvotes: 3