Key Content of This Lesson#
- Understand the concept, tools, and goals of "engineering" in frontend development
- A team should have a few members familiar with Webpack, which can become a core competitive advantage for individuals
- A necessary path for advanced frontend development
Course Objectives:
- Understand the basic usage of Webpack
- Establish a knowledge system by introducing Webpack's features, Loader, and Plugin component design
- Not cover every detail, but introduce all aspects of Webpack
- Not delve into the source code, but explain the underlying implementation principles
What is Webpack#
What constitutes a frontend project? — Resources
In the old days, these resources were managed manually, but there were several significant drawbacks that greatly affected development efficiency:
- Manual dependencies, for example, if there are 50 JS files... The operation process is cumbersome
- When there are dependencies between code files, they must be written strictly in dependency order
- Consistency between development and production environments makes it difficult to integrate new TS or JS features
- It is relatively difficult to integrate tools like Less, Sass, etc.
- Inconsistent resource management models for JS, images, and CSS
Later, many frontend engineering tools emerged, especially Webpack.
The essence of the web is a frontend resource compilation and packaging tool.
- Multiple resource files are packaged into a single Bundle
- Supports
- Babel, Eslint, TS, CoffeeScript, Less, Sass
- Supports modular processing of CSS, images, and other resource files
- Supports HMR + development server
- Supports continuous listening and continuous building
- Supports code splitting
- Supports Tree-shaking
- Supports Sourcemap
- ...
Core Process of Webpack Packaging#
Example#
-
Install (make sure to open the command line with administrator privileges)
npm i -D webpack webpack-cli
-
Edit the configuration file webpack.config.js
module.exports = { entry: 'main.js', // Define the entry file for the current project output: { // Define the output file for the current project filename: "[name].js", path: path.join(__dirname, "./dist"), }, module: {// Define some loader-related content, as will be seen below rules: [{ test: /\.less$/i, use: ['style-loader', 'css-loader', 'less-loader'] }] } }
-
Execute the compile command
npx webpack
Steps#
Entry => Dependencies Lookup => Transform => Bundle => Output
A highly simplified version:
- Start the compilation from the entry file in entry
- Dependency resolution: Find the required resources based on
require
orimport
statements - According to the
module
configuration, call resource transformers to compile non-JS resources into JS content until all resources are processed - Resource merging and packaging: Merge the transpiled resource content into a JS file that can be run directly in the browser
Modularity + Consistency
- Multiple file resources are merged into one, reducing the number of HTTP requests
- Supports modular development
- Supports advanced JS features
- Supports TypeScript, CoffeeScript dialects
- Unifies the processing model for images, CSS, fonts, and other resources
- Etc...
Key Configuration Items (How to Use?)#
The usage of Webpack is primarily centered around configuration, which can be roughly divided into two categories:
- Process-related: Configuration items that affect certain or several stages of the process and directly influence the packaging effect
- Tool-related: Configuration items that provide more engineering capabilities outside the main process
ps: The official documentation is indeed hard to understand ()
Configuration overview:
Based on usage frequency, the main configuration items are as follows:
-
entry/output — program input and output, necessary
-
module/plugins
-
For example, if my project needs to load less files, I need to import the following loaders, etc.
-
-
mode
-
watch/devServer/devtool
Official Webpack Configuration Documentation
Using Webpack to Handle CSS/Less, etc.#
-
Install Loaders
npm add -D css-loader style-loader
-
Add module to handle CSS files
Thought Questions#
- What is the role of Loaders? Why do we need to use css-loader and style-loader here?
- Compared to the old days of maintaining CSS in HTML files, what are the advantages and disadvantages of this method?
- Have you encountered CSS pre-compilation frameworks like Less, Sass, or Stylus? How to integrate these tools into Webpack?
- Answer: I have encountered Less.
Reference Materials:
Using Webpack with Babel#
-
Install dependencies
npm -D @babel/core @babel/preset-env babel-loader
-
Declare entry
entry
& outputoutput
-
Add module to handle JS files
module:{ rules:[ { test:/\.js?$/, use:[{ loader: 'babel-loader', options: { presets: [ [ '@babel/preset-env' ] ] } }] } ] }
-
Execute
npx webpack
Thought Questions#
- What specific functions does Babel provide?
- What problems do Babel and Webpack solve respectively? How do they work together?
Reference Materials:
Using Webpack to Generate HTML#
-
Install dependencies
npm i -D html-webpack-plugin
-
Configuration
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: "./src/index",
output: {
filename: "[name].js",
path: path.join(__dirname, "./dist"),
},
plugins: [new HtmlWebpackPlugin()]
};
- Execute
npx webpack
Thought Questions#
- Compared to manually maintaining HTML content, what are the advantages and disadvantages of this automated generation method?
Reference Materials:
Using Webpack — HMR#
Hot Module Replacement — modules are hot-replaced (the code written will be updated immediately in the browser~)
-
Enable HMR
module.exports={ // ... devServer: { hot:true; // Required } };
-
Start webpack
The principle can be referenced: Webpack Principles Series Ten: Full Analysis of HMR Principles (qq.com)
Using Webpack — Tree-Shaking#
Tree-Shaking - used to remove Dead Code
Dead Code
- Code that is not used and unreachable
- The execution result of the code will not be used
- Code that is read-only and not writable
Tree-Shaking
- Modules are exported but not used by other modules
Steps to enable?
- mode: "production"
- optimization: {usedExports: true}
module.exports = {
entry: "./src/index",
mode: "production",
devtool: false,
optimization: {
usedExports: true,
},
};
ps: This is particularly effective for utility libraries like Lodash, which can greatly reduce the size of the output.
Other Tools#
- Caching
- Sourcemap (mentioned in previous courses)
- Performance monitoring
- Logging
- Code compression
- Code splitting
- ...
Thought Questions#
- Besides the above-mentioned content, what other configurations can be classified as "process-related"?
- What are the specific functions of tool-related configurations? Including devtool/cache/stat, etc.
Understanding Loaders#
The core function of Loaders: Convert non-JS resources into JS resources
-
Install Loaders
npm add -D css-loader style-loader less-loader
-
Add module to handle Less files
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use:[
"style-loader",
"css-loader",
"less-loader",
],
},
],
},
};
Understanding Loaders: Chaining#
- less-loader: Implements the conversion from less => css
- css-loader: Implements the conversion from css => js, wrapping CSS into content like module.exports = "${css}", which conforms to JavaScript syntax
- style-loader: Wraps the CSS module in a require statement and calls functions like injectStyle at runtime to inject the content into the page's style tag
Understanding Loaders: Other Features#
Characteristics
- Chained execution
- Supports asynchronous execution
- Divided into normal and pitch modes
- Reference: Webpack Principles Series Seven: How to Write a Loader (qq.com)
module.exports = function(source, sourceMap?, data?) {
// source is the input for the loader
// It could be file content or the result of the previous loader
return source;
};
Common Loaders#
From a usage perspective, it is recommended to master the functions and configuration methods of these common Loaders.
Thought Questions#
- What is the input for a Loader? What is the expected output?
- What does the chaining of Loaders mean? How to chain multiple Loaders together?
- How to handle asynchronous scenarios in Loaders? How to throw an exception?
Understanding Plugins#
What is a Plugin#
- Many well-known tools, such as:
- VS Code, Web Storm, Chrome, Firefox
- Babel, Webpack, Rollup, Eslint
- Vue, Redux, Quill, Axios
- And so on, have designed a so-called "plugin" architecture. Why?
Plugins can enhance the extensibility of the entire application.
Assuming an application has no plugins, the entire process becomes particularly complex, then:
- Newcomers need to understand the details of the entire process, high onboarding cost
- The cost of feature iteration is high, one change affects everything
- Functionality becomes rigid, lacking growth potential as an open-source project
High mental cost => Low maintainability => Weak vitality
The essence of the plugin architecture: Open for extension, closed for modification, which is essentially the Open/Closed Principle.
In fact, many of Webpack's functionalities are also implemented based on plugins.
How to Write a Plugin#
First: Plugins revolve around hooks.
class SomePlugin {
apply(compiler) {
compiler.hooks.thisCompilation.tap('SomePlugin', (compilation) => {
})
}
}
Hooks#
-
Timing: Specific nodes in the compilation process where Webpack will notify plugins about what is happening at that moment;
-
Context: The context information is passed as parameters through the callback mechanism provided by tapable;
-
Interaction: The context parameter object contains many interfaces with side effects, and plugins can use these interfaces to change things.
Timing: compiler.hooks.compilation
Parameters: compilation, etc.
Interaction: dependencyFactories.set
Thought Questions#
- What are the differences between Loaders and Plugins?
- What is the role of "hooks"? How to listen to hook functions?
Reference Materials:
How to Learn Webpack#
Beginner Level: Learn to Apply Flexibly#
- Understand the packaging process
- Master the usage of common configuration items, Loaders, and Plugins, and be able to flexibly build a Webpack environment that integrates Vue, React, Babel, Eslint, Less, Sass, image processing, and other tools
- Master the usage of common scaffolding tools, such as: Vue-cli, create-react-app, @angular/cli
Advanced Level: Learn to Extend Webpack#
- Understand the Loader and Plugin mechanisms, and be able to develop Webpack components independently
- Understand common performance optimization techniques and be able to apply them to solve practical problems
- Understand the concepts of frontend engineering and the current ecosystem
Master Level: Source-level Understanding of Webpack Packaging and Compilation Principles#
- Read the source code, understand the principles of Webpack compilation and packaging, and even be able to participate in co-construction.
Summary and Reflections#
This lesson detailed the role of Webpack, its configuration structure, and key configuration items. It also discussed the chaining of loaders, the implementation principles of plugins, and some other features. It is evident that the teacher's research on Webpack is very thorough and detailed, with direct debugging into the loader internals during the class to help us understand. The teacher also summarized the Webpack knowledge system: Webpack 5 Knowledge System - GitMind.
Q&A#
Q: What level of understanding is required for interviews?
A: There are many online interviews primarily focused on three themes:
- What is the role of Loaders? How to write a loader? What are common loaders?
- Common loaders: css-loader, style-loader, vue-loader, file-loader, eslint-loader, babel-loader, etc.
- What is the use of plugins? How to write plugins? What are the compilation principles?
- What do Bundle, chunk, and module mean?
Some resources: In-depth Understanding of Webpack
Most of the content referenced in this article comes from Teacher Fan Wenjie’s class. Feel free to follow the teacher's public account: Tecvan.