Tutorial for webpack 4 - part 13 - live code replacement

Although automatic watching for changes and rebuilding bundles is a great webpack feature that improves development, there is some more manual work that needs to be done before you see the result in the browser. I would like to show you how webpack-dev-server can help you.

Table of contents

If you want to jump to other parts of the tutorial, use table of contents.

 

Live code replacement

When you make a series of changes on the frontend side for example styles or modify texts, there are many attempts. You make a single change, wait for webpack to notice the change and rebuild it (if you have watching for changes enabled), then you rebuild the WAR file (or the exploaded WAR file), redeploy it and refresh the page in the browser. Even if you use advanced features of your IDE, these steps are at least semi manual. Moreover, you have to repeat them multiple times because the new color you set is too dark or the text is slightly too long so you need to make another attempt.

It would be so wonderful if there was a way to make a code change and all these steps performed automatically and you could just observe the effect on the page in the browser. Oh, wait, there is such way. It is called webpack-dev-server.

 

webpack-dev-server configuration

In the first step, install webpack-dev-server and webpack and make sure that versions of both are compatible. To do that, run the below command from the directory where package.json exists.

npm install webpack-dev-server webpack --save-dev

After that, you should see proper entries with webpack-dev-server and webpack in package.json file.

 

In the second step, make necessary configuration in webpack.config.js (if this file is new to you, check other articles in webpack tutorial especially the one where I create webpack.config.js). For me it was enough to add the following devServer section:

module.exports = {
   
...     watch: true,
   
devServer: {
       
contentBase: __dirname + "/main/webapp/dist/",
       
compress: true,
       
port: 9000,
proxy: {
   
'/api': 'http://localhost:8080'
}
   
}
};
contentBase
defines where are the files that should be served to the browser. It usually points to the output files produced by webpack.
compress
enabled compression for the served files because of performance reasons.
port
defines the port numer where the content will be accessible for the browser. It should be set to a different port than the one used by the backend side of your application (if you have one).
proxy
redirects all requests for '/api' to a new address. Normally, the frontend sends API requests to the same port to the backend. In our case, frontend is managed by webpack-dev-server on port 9000 but the backend listens on port 8080 so we should use proxy to connect one to the other. It is needed only if you have the backend part. My sample application does not so I actually do not needed it.

That should be enough configuration to make webpack-dev-server work.

 

CORS mapping

My sample application do not have any backend part but if yours does you will need one more element. An important aspect of using webpack-dev-server is a fact that the frontend is published on the defined port. It is 9000 in my case. At the same time, the backend part exposes APIs on a different one, e.g. 8080. They are considered as two different origins and such requests are normally prohibited unless the backend explicitely allows that. Otherwise you will see Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource ... error. This mechanism is called Cross-Origin Resource Sharing (CORS).

If you want to use webpack-dev-server to manage the frontend and use the backend at the same time, you need to accept connections from port 9000 to the backend. If your application is based on Spring you can add the following method to Spring configuration:

 @Configuration
@EnableConfigurationProperties
(ApplicationConfig.class)
public class WebConfiguration implements ServletContextInitializer {
...
   
@Bean
    @Profile
("dev")
   
public WebMvcConfigurer corsConfigurer() {
       
return new WebMvcConfigurerAdapter() {
           
@Override
           
public void addCorsMappings(CorsRegistry registry) {
         registry.addMapping(
"/**").allowedOrigins("http://localhost:9000");
            }
        };
    }

}

It will activate only for dev profile. 

 

Running webpack-dev-server

Once it is configured, you can start it by running the following command from the directory where package.json is:

npx webpack-dev-server --mode=development

Then, open http://localhost:9000 in the browser. When you make a change in the code, webpack will notice it, rebuild it and webpack-dev-server will reload the page in the browser.

 

Summary

I showed you how to configure webpack-dev-server to reduce amount of repeatable work during development, especially, rebuilding frontend, redeployment and web page refreshing.

Source code created in this part is on tutorial/part13-webpack-dev-server branch on GitHub.

 

Next part

Look here for the next part of the tutorial.