I will try to be as basic as possible and as cohesive as possible. You can get the final code and use it in different projects directly. I will explain about the Webpack 4 fundamental concepts from scratch in few steps and code related to each step will be in a separate commit so that you can easily cross-check by running on your pc. This beginners guide to Webpack 4 help you with everything you need to know about the Webpack production environment setup.
Let us get started with Webpack 4,
Starting with Webpack 4, I created a file named webpack.config.js with a simple config dealing with what the input file and what the output file should be and expose it out with module.exports, just what we do in a node file.
Folder app will contain our source data and build will contain our final output bundle. Assuming that webpack and webpack-cli are installed as dependencies, we can add a script to the package and build the application.
You can check out the code for the commit #1 to find the code.
After installing the application, we begin with Webpack 4 production setup and explore their components.
Webpack implicitly considers the build is for a production every time we run the code. We can specify the mode to be production explicitly by setting the attribute -p or --mode=production. And, we would want to use a different configuration in case of production or development.
Let us segregate the configs for development and production into 2 different files naming them as webpack.[ENV].config.js. Similarly, we shall add 2 different entries in our package.json.
Dev build will not be minified, so the size of the build is around 4 to 5 times the production build. In the production environment, the build will be delivered by a web server, but we do not have one in the development environment. This can be handled by webpack dev server. Check commit #3 to find the code related to this section.
Webpack Dev Server is a simple web server written over ExpressJS and will help in rebuilding the source upon any modification.
We can use it by linking to npm start script
We can configure this server by showing it how content can be loaded and from where should it be loaded by adding the following to the development config.
To show what it can do we will create a simple HTML page using our bundle file which is generated. And this file will be our application so we will place it in a folder called dist.
When I run the webpack dev server with npm start it will take assume the given port 9500. You can view our application accessing
http://localhost:9500. You checkout to Commit #4 to check find this code.
Loaders are transformations that are applied to the source files. Web builds by reading the entry file and as and when a require or import statement is found to load a file Webpack will try to apply the relevant transformations mentioned in the loaders.
A loader is consisting of 2 main properties, test and use. The test will hold the pattern/regex which is verified by the name of a file and if satisfied the respective loader will load the file.
Say, we imported a CSS file in our entry file or any other js file, so that CSS file will be used only when the respective js file is included.
So to load the CSS files into our build, we will install respective loaders.
Let the contents of CSS file be the following.
Now add the loaders to webpack configuration. Remember to set modules option to true to enable CSS Modules. CSS Modules helps us to scope the CSS to an HTML element to avoid the conflicting styles when available in a common global context.
On running the build or dev server we can see the output HTML in the localhost with red in color which is given in the CSS. Checkout to Commit #5 to see all the changes done here.
To get a better understanding of loaders let us look at another example. Current all the new libraries or frameworks use ES 6/7 syntax but not all web browsers support them. So as part of the build setup, we will need to convert the ES 6/7 syntax to ES5. We will need babel to transpile to ES5. And when being used in webpack we have a webpack loader. Let us install following development dependencies.
Now, to test this we will add some ES6 features to our index.js file. I am using the following snippet which uses arrow functions and let operator.
Add some minor configuration changes to the webpack config to transpile this code to ES5. Babel can restrict to different environments when transpiling, so we need to set the presets to env to generate ES5 output.
On running the webpack now we will see the output in the ES5 format as
You can check the code in Commit #6 for complete changes.
Plugins, as the name suggests, will plugin to the build process to extend the power of webpack and can do what loaders cannot do. Webpack has a set of built-in plugins and there are a lot more open source plugins from the community.
Say, I want all my CSS files to be merged into a single separate CSS file. This requirement is above the limits of what a loader can do. So, we will use an external plugin called mini-css-extract-plugin. When you try to find the right way of extracting a resource from the build to a separate file you will come across a plugin called extract-text-webpack-plugin. Apparently, this plugin is not upgraded to Webpack 4. So you will run into some errors.
I created a new CSS file and included in our file2 and named it as file2.css with some simple contents
When we build the source we will get a single output file with complete js and CSS including every file used in the repository. So, we will install the plugin with npm i -D mini-css-extract-plugin and configure our webpack config as follows.
This will merge all the CSS files and extract them separately as a file called main.css. But the index.html we created is not referencing to this file. So, we can update the index.html to include main.css. Check the code in commit #7
Now, we are having only 2 files to be included. Plus, our index.html is completely defined with no scope for dynamism.
To fix this, we will use webpack-html-plugin which can inject the build files directly into an HTML template and puts the final HTML file into the dist folder.
Let’s remove the HTML from the dist folder and you can delete the folder from git as we no longer need the HTML file to be in the dist folder. When we run build dist folder gets created with all the dependencies whose contents are usually deployed to a web server. Create a file called index.ejs in the app folder. This use EJS templating language which helps us to create an HTML template. To see its usage let us try to get the title dynamically during the build instead of hard-coding.
You can see that I haven’t included any CSS or js file paths and even the HTML title.
Now, We will configure the webpack loader by installing the plugin and configuring our plugin section.
Now, build the application with npm run dev-build as we haven't added any updates so far to the production config. You will see that an index.html file is created in dist folder with following contents.
You can check this in Commit #8. Using a single config file or make them more modular will make the configs easy to maintain. So, I am re-organizing the functions into different files. Also giving them names will make it even more readable. So, in the final version of the code, you will find the code more organized.
This Webpack 4 basic tutorial gives you a very good understanding of webpack. And you can access the repo here. I want all of you to spend enough time to create a base webpack repository and reuse it in all your front end projects.