Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The effect of HtmlWebpackPlugin on webpack dev server

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?

like image 316
d512 Avatar asked Apr 23 '18 14:04

d512


People also ask

What is the purpose of HtmlWebpackPlugin?

The HtmlWebpackPlugin simplifies creation of HTML files to serve your webpack bundles. This is especially useful for webpack bundles that include a hash in the filename which changes every compilation.

What is HtmlWebpackPlugin template?

template: './src/index. html' – this option specifies which file to use as template for the index. html being created. title: 'My Awesome application' – this is a custom property we added to the config object, the value of this property would be used to embed in the placeholder element <%= htmlWebpackPlugin. options.

What html5 Tech does webpack-dev-server use?

Run the Webpack dev server Because we are using html-weback-plugin , it will create an index. html file and include the bundled file main. js into the script tags.

How can we make the webpack to watch for changes?

Using Watch Mode You can instruct webpack to "watch" all files within your dependency graph for changes. If one of these files is updated, the code will be recompiled so you don't have to run the full build manually. Now run npm run watch from the command line and see how webpack compiles your code.


2 Answers

Okay, I think I figured this out.

TL;DR

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.

The Tedious Details:

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.

like image 72
d512 Avatar answered Sep 22 '22 21:09

d512


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).

like image 32
Prajwal Avatar answered Sep 19 '22 21:09

Prajwal