Webpack 101: An introduction to Webpack
--
Hootsuite is using Webpack as a solution for our Static Asset Pipeline, which compiles, concatenates, minifies, and compresses static assets for the Hootsuite website. We chose Webpack because it is a powerful build tool for single-page applications (SPAs). Webpack is good for figuring out module dependencies, making it easier for developers to organize code structure and reuse modules/components among multiple entry points.
In this blog post, I’ll show how you can use Webpack in a project by providing some sample webpack configurations and a git repository as a demo to try out. When you finish reading this blog post, you should be able to configure your web project:
- to reuse modules and components for single/multiple entry point(s)
- to build unique bundles for each entry point
- to build a common bundle for the entry points
[caption id=”attachment_3400" align=”aligncenter” width=”500"]
Image from http://webpack.github.io/[/caption]
Why Webpack?
A good single-page application should be maintainable, reliable, and efficient. Webpack is a powerful tool to build an SPA, because:
- It manages modules and their dependencies and transforms static assets to build bundles
- It creates the same build bundles in development and production for consistency
- It controls multiple application entry points or sections, and provides common bundles among them. Other unique bundles for each section can be loaded on-demand.
- It can version assets per file — for example, appending a unique hash to the file name (i.e. bundle.sd2fdds34.js). This makes it easy to cache the assets. It also supports live updates (hot module replacement) during development.
For more information, please read Alexandrine Boissière’s presentation on “An Efficient Static Assets Pipeline With Webpack”, which describes why Webpack is a good choice for a static assets pipeline.
Now, let’s see how we can use the Webpack in our project.
Webpack CLI
Webpack can be run in the console with following command:
> webpack
This will try to load the file “webpack.config.js” in the current directory.
To specify a different config file, we can run webpack with an option:
> webpack --config ./example.config.js
For more CLI options, take a look at the documentation.
Webpack Config 101: Entry Point & Output
Tell me where to start, then I will give you the bundles.
Basically, we give Webpack a starting point, then Webpack figures out its own dependency tree, gathers all these dependencies, and builds a bundle.
The dependency diagram pictured above could be handled by a very basic config file:
With this config, Webpack will start from entry.js, figure out its dependencies and build a bundle, named bundle.js in the /dist folder. The “context” is a base directory to resolve the “entry” option. It must be an absolute path.
Webpack Config 101: Multiple Entry Points & Outputs
Webpack also supports building multiple bundles for multiple HTML pages (entry points).
With this config, Webpack will build three bundles with the name as the “key” value of each entry. So the outputs will be:
/dist/a.js, /dist/b.js, /dist/name_c.js
Webpack Config 101: Loaders
Now, does Webpack only work for javascript assets? What if the files have dependencies on css, less, jpg, svg, and so on?
Not to worry: Webpack supports other asset types by using loaders!
Sample config:
With this config, if Webpack encounters any html, js, css, images, or less file dependencies, it will preprocess the files using the loaders, which are specified in the JSON object, and put them in the bundles. Chaining Loaders Webpack can also chain loaders with “!” character, which runs from right-side loader to left-side loader. In the example above, “*.less” files will be transformed first by the less-loader, and then its output is transformed by css-loader, then its output goes through style-loader. Embedded Stylesheets One interesting behavior from the above configuration has to do with embedded stylesheets. The “style-loader!css-loader” will preprocess the stylesheets and embed them into the output javascript file(s) by default. At runtime, this embedded style will be included as a “style” tag in HTML. We can separate the style bundle by using “extract-text-webpack-plugin,” which will be introduced in next section.
Webpack Config 101: Plugins
Webpack has many useful plugins. Below are a few plugins that I have found useful.
With this config, Webpack will generate commons.js, a.js, b.js, and c.js javascript bundles, as well as a.html, b.html, and c.html files in the dist directory.
CommonsChunkPlugin is used to build a common bundle and split code. As the comments say in the config file, we can control which module is included in the commons bundle by specifying options of how many times and in which entry the module is shared.
HtmlWebpackPlugin is a third-party plugin that creates HTML files to serve the webpack bundles.
ExtractTextPlugin separates the css styles from javascript bundles. As I mentioned in the “Embedded Stylesheets”, the stylesheets are embedded into the output javascript file(s) by default. But using the ExtractTextPlugin allow us to have separate css output file(s) along with javascript file(s). It means we have an option for client to download css and javascript files in parallel, instead of loading big size of javascript file(s).
Further information on plugins is available online, and other plugins can be found here.
Demo Repository
Based on the topics we covered above, I created a repository that demonstrates:
- how to build multiple entry points
- how to use/share components in each entry point
- how to build different resources (js, jsx, less, png) using loaders
- how to build a common bundle for the entry points, using a plugin
- how to build unique bundles for each entry point
In the repo, “src” directory has two entry point files and seven React components: green, red and blue box components, green, red, and blue circle components and a shared image component. The “dist” directory has common.js, entry1.js and entry2.js bundles, built by Webpack.
The entry point 1 serves common.js and entry1.js bundles. The common.js contains the shared image component and the entry1.js contains every box components.
The entry point 2 serves common.js and entry2.js bundles. The common.js contains the shared image component and the entry2.js contains every circle components.
[caption id=”attachment_3406" align=”aligncenter” width=”400"]
Diagram of entry point 1[/caption]
[caption id=”attachment_3407" align=”aligncenter” width=”401"]
Diagram of entry point 2[/caption]
To see its config file or to play around with real code, please go to the repository and start by reading its README file.
Conclusion
Hope you found this introduction to Webpack helpful. Please leave a comment if you have any further questions; I’d be happy to answer them.
References
- Webpack
- An Efficient Static Assets Pipeline with Webpack by Alexandrine Boissière
About the Author
Martin Jung is a software engineer on the Mobile Web team. Recently he is having fun with React and Webpack. When not working, he likes to learn about other cultures and history. Follow Martin on Twitter @martinjung03.