Why and when should I Use Webpack?
What is the advantage of CompressionPlugin?
Do loaders work in a synchronous or an asynchronous way?
What is the main difference between Webpack and other build tools like Gulp or Grunt?
How would you remove unused selectors from css using webpack?
What is a dependency graph and how does webpack build it?
Which modules design patterns webpack supports out of the box?
Name some benefits of using webpack
Name some plugins you think are very important and helpful
What are some advantages of using webpack-dev-server over simple "http" server or "nginx"?
Why is OccurenceOrderPlugin the part of webpack optimization?
What is difference between "hash" and "chunkhash"?
Webpack gives us a dependency graph. What does that mean?
Explain me the difference between NPM vs. Bower vs. Browserify vs. Gulp vs. Grunt vs. Webpack?
What's the difference between webpack loaders and plugins?
Briefly describe long-term caching and how to achieve it using webpack?
How to move some data (e.g css code) from a bundle to a separate file in webpack?
Describe the webpack runtime and manifest
What is Hot-Modules-Replacement?
What is parallel-webpack and how does it affect webpack's build process?
Is it possible to use other languages (except javascript) for the webpack config file?
Describe tree shaking mechanism in webpack
Webpack is a build tool that puts all of your assets, including Javascript, images, fonts, and CSS, in a dependency graph. Webpack lets you use require()
in your source code to point to local files, like images, and decide how they're processed in your final Javascript bundle, like replacing the path with a URL pointing to a CDN.
If you're building a complex Front End application with many non-code static assets such as CSS, images, fonts, etc, then yes, Webpack will give you great benefits.
If your application is fairly small, and you don't have many static assets and you only need to build one Javascript file to serve to the client, then Webpack might be more overhead than you need.
Bundle is the output file generated by webpack. It contains all of the modules which are used in application. Bundles generation process is regulated by webpack config file.
CompressionPlugin builds gzip-ed version of bundles. Its possible to simply add server side compression e.g using nginx or expres compression plugin. Server-side compression is not recommended because it addes load on CPU and increases response time.
Plugins used to customize webpack’s build process in a variety of ways. A webpack plugin is a JavaScript object that has an apply property. This apply property is called by the webpack compiler, giving access to the entire compilation lifecycle. Webpack comes with a multiple built-in plugins available under webpack.[plugin-name]
.
webpack enables use of loaders to preprocess files. This allows you to bundle any static resource way beyond JavaScript. Loaders can work synchronous or asynchronous.
Webpack is a module bundler, though it is quite often used instead of Gulp or Grunt task runners. This advanced tool provides developers with control of spliting the modules, allowing them to adjust builds to particular situations and workaround solutions that don’t function properly out of the box.
Comparing Webpack vs Grunt, the first of those offers more flexibility and advanced functionality for modern front-end projects. It comes with a functional core and can be extended using particular loaders and plugins. Essentially it is used for bundling JavaScript modules with dependencies into files, but for complex JavaScript applications with lots of non-code assets (images, fonts, CSS, etc.) it can provide great benefits.
Talking about Webpack vs Gulp vs Grunt performance, the two latter look into a defined path for files that match your configuration, while the Webpack analyzes the whole project. It looks through all the dependencies, processes them with loaders and produces a bundled JS file.
Using purifycss-webpack plugin
The entry object is where webpack looks to start building the bundle, at this point the application starts executing.
Any time one file depends on another, webpack treats this as a dependency. Starting from entry point(s), webpack recursively builds a dependency graph that includes every module your application needs, using import
and require
statements, then packages all of those modules into bundle(s).
Loaders are transformations that are applied on the source code of a module. Webpack supports modules written in a variety of languages and preprocessors, via loaders. Loaders describe to webpack how to process non-JavaScript modules and include these dependencies into your bundles.
- common.js,
- amd
- es6 (since webpack 2)
- Loaders can be chained.
- Loaders can be synchronous or asynchronous.
- Loaders run in Node.js and can do everything that’s possible there.
- Loaders can be configured with an options object
- Plugins can give loaders more features.
- Loaders can emit additional arbitrary files.
Webpack and static assets in a dependency graph offers many benefits. Here's a few:
- Dead asset elimination. This is killer, especially for CSS rules. You only build the images and CSS into your
dist/
folder that your application actually needs. - Easier code splitting. For example, because you know that your file
Homepage.js
only requires specific CSS files, Webpack could easily build ahomepage.css
file to greatly reduce initial file size. - You control how assets are processed. If an image is below a certain size, you could base64 encode it directly into your Javascript for fewer HTTP requests. If a JSON file is too big, you can load it from a URL. You can
require('./style.less')
and it's automaticaly parsed by Less into vanilla CSS. - Stable production deploys. You can't accidentally deploy code with images missing, or outdated styles.
- Webpack will slow you down at the start, but give you great speed benefits when used correctly. You get hot page reloading. True CSS management. CDN cache busting because Webpack automatically changes file names to hashes of the file contents, etc.
Webpack is the main build tool adopted by the React community.
- CommonsChunkPlugin - creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points.
- DefinePlugin - allows you to create global constants which can be configured at compile time.
- HtmlWebpackPlugin - simplifies creation of HTML files to serve your webpack bundles.
- ExtractTextWebpackPlugin - Extract text from a bundle, or bundles, into a separate file.
- CompressionWebpackPlugin - Prepare compressed versions of assets to serve them with Content-Encoding.
The webpack-dev-server is a little Node.js Express server, which uses the webpack-dev-middleware to serve a webpack bundle.
webpack-dev-server simplifies development process due to integrated fast in-memory access to the webpack assets and hot-modules-replacement features.
This code is intended to transform and load sass files as webpack modules.
This config tells to webpack to search for all files which have .scss
extension, then applies the following loaders on them, from right to left order:
postcss-loader
- transforms postcss to sass code.sass-loader
- transforms sass to plain css.css-loader
- reads css file, resolvesimport
andurl(...)
statements.style-loader
- creates<style>
tags in the page's<head>
element containing css returned bycss-loader
.
Due to ?sourceMap
at the end of css-loader and sass-loader, source maps for all .scss files will be created.
OccurenceOrderPlugin order the modules and chunks by occurrence. More module occurs - smaller id it has, this technique helps to reduce bundle size, because a module is used many times will be referenced many times with webpack_require(moduleId)
.
hash
will generate unique hash for each build and use it for all chunks. Replace hash
with chunkhash
to generate unique hashes for each chunk. This is useful when you dont want to re-download vendors (dependencies) file but you have changes in your application code and want to update it.
Any time one file depends on another, webpack treats this as a dependency. This allows webpack to take non-code assets, such as images or web fonts, and also provide them as dependencies for your application.
Webpack lets you use require() on local "static assets":
<img src={ require('../../assets/logo.png') } />
When webpack processes your application, it starts from a list of modules defined on the command line or in its config file. Starting from these entry points, webpack recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into a small number of bundles - often, just one - to be loaded by the browser.
The require('logo.png')
source code never actually gets executed in the browser (nor in Node.js). Webpack builds a new Javascript file, replacing require()
calls with valid Javascript code, such as URLs. The bundled file is what's executed by Node or the browser.
Webpack isn't perfect and has some pitfalls.
- The documentation is awful. The language is often confusing, such as "webpack takes modules with dependencies and generates static assets representing those modules." What? Even the page layout is problematic, with random sidebar entries you can't click on, and animated logos while you're trying to read.
- The source code is similarly painful.
- Configuring Webpack is a minefield for newcomers. The configuration file syntax is confusing. It helps to look at established examples from boilerplate projects.
- Webpack is maintained mostly by one person. The rapid community adoption and the thrust into the spotlight means the ecosystem lags far behind the maturity of React. This has side effects, such as the poor quality of the documentation.
- Webpack introduces a nasty mini language in a string:
require("!style!css!less!bootstrap/less/bootstrap.less");
This syntax is almost never used, and barely explained, but it's all over the documentation. This string language is one of of Webpack's biggest design flaws in my opinion.
npm
&bower
are package managers. They just download the dependencies and don't know how to build projects on their own. What they know is to callwebpack
/gulp
/grunt
after fetching all the dependencies.bower
is likenpm
, but builds flattened dependencies trees (unlikenpm
which do it recursively). Meaningnpm
fetches the dependencies for each dependency (may fetch the same a few times), whilebower
expects you to manually include sub-dependencies. Sometimesbower
andnpm
are used together for front-end and back-end respectively (since each megabyte might matter on front-end).grunt
andgulp
are task runners to automate everything that can be automated (i.e. compile CSS/Sass, optimize images, make a bundle and minify/transpile it).grunt
vs.gulp
(is likemaven
vs.gradle
or configuration vs. code). Grunt is based on configuring separate independent tasks, each task opens/handles/closes file. Gulp requires less amount of code and is based on Node streams, which allows it to build pipe chains (w/o reopening the same file) and makes it faster.webpack
(webpack-dev-server
) - Webpack is a build tool that puts all of your assets, including Javascript, images, fonts, and CSS, in a dependency graph.npm
/bower
+ plugins may replace task runners. Their abilities often intersect so there are different implications if you need to usegulp
/grunt
overnpm
+ plugins. But task runners are definitely better for complex tasks (e.g. "on each build create bundle, transpile from ES6 to ES5, run it at all browsers emulators, make screenshots and deploy to dropbox through ftp").browserify
allows packaging node modules for browsers.browserify
vsnode
'srequire
is actually AMD vs CommonJS.
- Loaders work at the individual file level during or before the bundle is generated.
- Plugins work at bundle or chunk level and usually work at the end of the bundle generation process. Plugins can also modify how the bundles themselves are created. Plugins have more powerful control than loaders.
Browsers should cache static assets to save traffic and users time. But after each change or bugfix, browser have to download newer version of files. The most easy way to achieve this is changing file name. It could be buildId or unique hash in the end of file's name like
app.js?build=1
app.js?build=2
or
app.js.2a6c1fee4b5b0d2c9285.js
app.js.70b594fe8b07bcedaa98.js
To achieve this using webpack simple configuration should be done
module.exports = {
...
output: {
filename: "[name].[hash].js"
}
...
}
Using ExtractTextWebpackPlugin
. It moves all the required *.css modules in entry chunks into a separate CSS file. So your styles are no longer inlined into the JS bundle, but in a separate CSS file (styles.css). If your total stylesheet volume is big, it will be faster because the CSS bundle is loaded in parallel to the JS bundle.
The CommonsChunkPlugin is built-in feature that creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points. By separating common modules from bundles, the resulting chunked file can be loaded once initially, and stored in cache for later use. This results in pagespeed optimizations as the browser can quickly serve the shared code from cache, rather than being forced to load a larger bundle whenever a new page is visited.
This code creates separate file: common.js
which contains common modules from home and dashboard chunks.
This code tells to webpack to include only those files which names match to /(en-gb|en-us)\.js/
pattern from /moment[\/\\]locale/
path. It used to optimize final bundle excluding unused locales. So if you need to use e.g french language's locale as well then you should add it to second regex like this: /(en-gb|en-us|fr)\.js/
.
- The runtime is basically all the code webpack needs to connect your modularized application while it's running in the browser. It contains the loading and resolving logic needed to connect your modules as they interact. This includes connecting modules that have already been loaded into the browser as well as logic to lazy-load the ones that haven't.
- As the compiler enters, resolves, and maps out your application, it keeps detailed notes on all your modules. This collection of data is called the Manifest and it's what the runtime will use to resolve and load modules once they've been bundled and shipped to the browser.
Hot-Modules-Replacement (HMR) is webpack feature which allows to update modules in application without page reload. HMR can be used as an advanced replacement for livereload.
parallel-webpack useful for webpack configurations with multiple entry points. It allows to run multiple webpack builds in parallel, spreading the work across your processors and thus helping to significantly speed up build.
Yes, webpack accepts configuration files written in multiple programming and data languages, such as typescript, coffeescript, babel and jsx.
Tree shaking is a term commonly used in the JavaScript context for dead-code elimination. It relies on the static structure of ES2015 module syntax, i.e. import and export.
You can imagine your application as a tree. The source code and libraries you actually use represent the green, living leaves of the tree. Dead code represents the brown, dead leaves of the tree that are consumed by autumn. In order to get rid of the dead leaves, you have to shake the tree, causing them to fall.
If your code did have some side effects (code that performs a special behavior when imported) though, use sideEffects
property:
{
"name": "your-project",
"sideEffects": [
"./src/some-side-effectful-file.js"
]
}