Preface
As explained in the previous article - Take your webpack to the next level by understanding these concepts, we have a general understanding:
- Some of the concepts that arise in using
webpack
process - Combined with the concepts of the packaging process, we analyzed the
webpack
packaging process, so that we can have a general understanding of the packaging process.
We all know that in the actual development process, we use webpack
only to finally output css
, img
, js
, html
and other front-end resources that the browser can run.
So, in order to be more close to the actual situation, in this article, we will learn how to configure webpack
with the purpose of how to output css
, img
, js
, html
and other front-end resources.
Learning Outline
This article explains the following basic configuration:
- Handling
css, less
files - Handling
img
,font
,audio
and other front-end resource files. - Compiling
es6+
syntax andAPI
. - Processing
html
files
The webpack
documentation is pretty detailed, so I don't want to copy and paste it and write it all over again, so it's better to just read the documentation.
Learning can't be learned the hard way, there should be some methods and techniques. Therefore, I would like to summarize some methods in the process of explaining the configuration, so that we can better understand the configuration of webpack
. In this way, some similar configurations, we can match them by looking at the documentation.
Remarks
The article has been uploaded to github:
- For the sake of reading convenience, the article only posted the relevant code, it is recommended to
fork
it to see the complete code; or follow the article together with the side of the knock, so that the impression will be more profound! - It's not easy to create, if you think it's helpful, welcome to star๐!
Handling css, less
files
Let's start with the learn-03 case to see how webpack
handles style files.
We install the appropriate loader
to parse them:
-
less-loader
: parsesless
intocss
. -
css-loader
: parsescss
into valid modules recognized bywebpack
. -
style-loader
: parsescss
and inserts it into<header />
.
npm install less less-loader css-loader style-loader -D
Then configure it:
// webpack.config.js
module.exports = {
...,
module: {
rules: [
{
test: /.(css|less)$/,
use: [
'style-loader',
'css-loader',
'less-loader',
],
},
]
}
}
The parsing of loader
is performed in reverse order (or right-to-left), so this configuration will be performed in the following order (less-loader
โ css-loader
โ style-loader
):
- parses
less
intocss
. - pass the result to
css-loader
, which parses it into a valid module recognized bywebpack
. - passes the result to
style-loader
, which inserts the parsed styles into<header />
) in the following order.
The less
, css
, and entry file code is:
// index.less
*{
margin: 0;
padding: 0;
}
h1{
color: red;
margin-top: 20px;
}
/* index.css */
h2{
color: green;
}
// index.js
import './assets/index.less';
import './assets/index.css';
Output:
We'll see that the style we wrote was processed successfully and inserted into the <head/>
.
Summary
We previous post said:
- The resource files that we come in via
import
orrequire
, or each file in our project, can be viewed as an individual module - The role of the
Loader
is to convert these modules into valid modules thatwebpack
recognizes.
webpack
humanely exposes the module
configuration item, which is specifically designed to configure the relevant loader
to parse the corresponding module
. So if we want to parse some module used in our source code, we should:
- download the appropriate
loader
first -
Find the
module
configuration directly and configure it according to theloader
usage.
So, we can try to configure our own .scss
or .txt
files according to the above summarized methods and ideas.
OK, we successfully got the styles (css
) we need for our project, next we will see how to deal with images (img
) and other front-end resource files.
Handling front-end resource files
There are a lot of front-end resource files, here, we roughly divide them into two categories first:
- Common class:
img
,font
,video
and so on. - Special category:
.csv
,.xml
and so on.
These resources are also modules as long as they are imported
or required
into our source code. Since they are modules, we need to install the appropriate loader
to parse them, and then configure them in the module
configuration.
Prior to wepack5
, For resources of commonly used classes, we generally needed to install the following loader
to parse them:
-
raw-loader
: parses files into strings -
file-loader
: parses files coming in fromimport/require()
into a fully referencedurl
and sends the file to the output directory -
url-loader
: can convert files tobase64
.
We often use file-loader
and url-loader
. This is because common resources are often introduced into our projects as url
, or converted to base64
in order to reduce http
requests.
But after webpack5
, webpack
has built-in the functions of the above several loaders
, so we can no longer need to install the above loaders
; we can directly use webpack
's own asset module.
The resource module built in after webpack5
:
-
asset/source
: equivalent toraw-loader
. -
asset/resource
: equivalent tofile-loader
. -
asset/inline
: equivalent to aurl-loader
. -
asset
: more flexible, has bothasset/resource
andasset/inline
. If you set a file size limit, the file will be converted tobase64
if it doesn't exceed the limit; if you don't set a size limit, it works the same asfile-loader
.
This is why I love
webpack5
so much, because we don't have to install so many messyloaders
.
Let's use the case of learn-04 to see how we can use the resource module to parse our front-end resources.
Let's add the configuration from the previous chapter on parsing styles together and use the image resources in less
and js
respectively.
We have two images:
-
preview.gif
: size349kb
-
ecj-cli.png
: size4kb
.
// webpack.config.js
module.exports = {
...,
module: {
rules: [
{
test: /.(css|less)$/,
use: [
'style-loader',
'css-loader',
'less-loader',
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 1024 * 10 // // When the image size is < 10kb it will be converted to base64
}
},
generator: {
filename: '[name][ext]' // Set the name of the output file
}
}
]
}
}
Entry file:
// index.js
import './assets/index.less';
const img = new Image();
img.src = require('./assets/ecj-cli.png');
img.width = 500;
document.querySelector('#js_logo').append(img);
Style:
.bg_logo{
width: (1434/3px);
height: (1212/3px);
background-image: url('./preview.gif');
background-size: 100%;
}
Output results:
We'll see that the style and js
both process the image successfully:
-
preview.gif
is larger than10kb
, so instead of being converted tobase64
, a full reference path is returned (equivalent tofile-loader
) -
ejc-cli.png
is smaller than10kb
so it was converted tobase64
(equivalent tourl-loader
)
The gif above is a command line tool ejc-cli that I developed that is very useful in everyday projects. It can convert the
Excel
data collected by the docking staff intojson
data in a certain format which is needed by our code. It is very convenient for us to develop and maintain the data, and also to interface with other people.If you are interested, you can check out ๐๐ป learn about ejc-cli
Summary
Resources that are imported into our source code via import
or require
are also modules. So you need to download the appropriate loader
and configure it in the module
configuration.
For common resources (img
, font
, video
, audio
, etc.):
- Because they are commonly used,
webpack5
has built-in functionality to handle them, so that we don't need to install an additionalloader
, and we use theasset module
to manage them directly. -
We generally use
asset/resource
,asset/inline
,asset
modules to manage common class resources. Because the resources of our common classes are often introduced in our projects, we need to parse them to introduce the fullurl
, or convert them tobase64
in order to reduce the number ofhttp
requests.
For special classes of resources (.csv
, .xml
, etc.):
- We can understand that because they are not commonly used,
webpack
does not have their functionality built in. - Therefore, we need to install the appropriate
loader
to parse them. For example, if we want to parse a.csv
file, we need to install thecsv-loader
to parse it.
We can try to configure ourselves to handle .video
or font
as summarized above.
OK, so far, we've got css
, img
. Let's see how we can get our js
through webpack
processing.
Compiling es6+
To this day, js
is evolving rapidly, and every year some new syntax or new API
appears in order to improve development efficiency and code quality.
For example, in terms of syntax appeared:
- Arrow functions:
()=>
- class syntactic sugar:
class People {}
- Deconstructed assignment:
const [x, y] = [1, 2];
- ...
On the API
side again:
Promise
Array.prototype.includes()
Object.keys()
- ...
But these new additions are not supported on some lower browsers, so we need to use webpack
to compile our es6+
into a version that these lower browsers can support.
Let's start with the learn-05 case and see how we configure webpack
to compile es6+
.
We install the relevant dependencies:
...
"devDependencies": {
"@babel/core": "^7.22.8",
"@babel/plugin-transform-runtime": "^7.22.7",
"@babel/preset-env": "^7.22.7",
"babel-loader": "^9.1.3",
"webpack": "^5.88.1",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"core-js": "^3.31.1"
},
Entry files. Uses es6+
syntax such as class
, Promise
, ()=>{}
and API
:
// index.js
class People {
constructor(name) {
this.name = name;
}
sayHi() {
return Promise.resolve(this.name);
}
}
const Lee = new People('Lee');
Lee.sayHi().then(name => console.log(`Hi, I am ${name}.`));
Configure webpack
:
// webpack.config.js
module.exports = {
...,
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader'
}
}
]
}
}
Configure Babel
. Create a new babel.config.js
file in the project root directory:
// babel.config.js
const presets = [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {
version: require('core-js/package.json').version,
proposals: true
}
}
]
];
const plugins = [
'@babel/plugin-transform-runtime',
];
module.exports = {presets, plugins}
Set the target browser to be compatible with. Add the browserslist
field to package.json
:
"browserslist": [
"ie 11"
]
The result of running it in ie 11
:
We will find:
- The
es6+
we wrote runs successfully inie 11
. -
Promise
, thees6+
API
, has also been added toie 11
.
It means that our compilation of es6+
was successful.
About Babel
In the configuration above, you will notice that if we want to compile es6+
with webpack
, we also need to add the babel.config.js
file to the root directory, which is a much more complicated and troublesome step than dealing with other modules. This is because compiling the core of es6+
requires Babel
to work with it. Babel
is a tool for compiling es6+
.
Since this post is mainly about webpack
, we'll just give a general mention of Babel
here. Here are some common configurations for Babel
.
- If the project we are developing is an application or a large project, we can configure it like this:
const presets = [
[
'@babel/preset-env',
{
modules: false,
useBuiltIns: 'entry', // or useBuiltIns: 'usage',
corejs: {
version: '3.27.2',
proposals: true
}
}
]
];
const plugins = [
'@babel/plugin-transform-runtime'
];
module.exports = {plugins, presets};
// index.js
// If use useBuiltIns: 'entry'
import 'core-js/stable'
- If we are trying to develop a third party library, we can configure it like this:
// Babel้
็ฝฎ
const presets = [
[
'@babel/preset-env',
{
modules: false
}
]
];
const plugins = [
[
'@babel/plugin-transform-runtime',
{
corejs: {
version: 3,
proposals: true
}
}
]
];
module.exports = {plugins, presets};
Summary
- If
js
isimported
orrequired
into our source code, then it is also a module. So we have to download the correspondingloader
(babel-loader
) and configure it in themodule
configuration. - In addition, we need to configure
babel-loader
and, most importantly,Babel
(babel.config.js
).
So, if we want to "compile es6+
", we need to configure webapck
, and most importantly we need to configure babel.config.js
. If you don't want to just copy and paste the Babel
configuration, you have to learn about Babel
.
Remember what we use webpack
for? To output css
, img
, js
, html
and other front-end resources that the browser can run.
OK, so far we have processed css
, img
, js
through webpack
. Let's take a look at how we can get our html
through webpack
processing.
Processing html
files
In the above example, we want to see the effect in the browser, we need to:
- Create a new
html
file in the root directory. - In the new
html
file, we need to bring in the packaged resource files manually.
This process is too troublesome, is there a way, we just provide a html
template file, and then through the webpack
compilation, it automatically help us to pack the packaged files into the good. This way, we can run html
directly after packaging and see the effect in the browser.
webpack
is so user-friendly, of course there is.
Let's start by using the learn-06 example here to see how we can utilize webpack
to achieve the results we described above.
Install the relevant plugins:
npm i html-webpack-plugin -D
This time, the webpack
configuration is a little different:
We set the packaged js
storage directory to be the js
folder; and we add a hash
value of 5
lengths to the packaged js
name.
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
entry: {
index: './src/index.js'
},
output: {
path: path.resolve(__dirname, './dist'),
filename: './js/[name]-[chunkhash:5].js',
clean: true
},
plugins: [
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, './dist/[name].html'),
template: path.resolve(__dirname, './index.html'),
title: 'HtmlWebpackPlugin',
})
],
}
The structure of the packaged file is:
dist
โโโ index.html
โโโ js
โโโ index-efbfd.js
The packaged html
is as follows:
We will find:
- Our
html
andjs
are packaged and exported to thedist
folder, which is very convenient for us to deploy (before we createdindex.html
in the root directory, so there are onlyimg
andjs
files in thedist
folder after packaging). - The packaged
html
will automatically bring in our packagedjs
file for us.
Analyzing
As we can see from the above example, if we want webpack
to process html
files, we need to configure it in plugins
provided by webpack
. Some of you may wonder why html
is a module and why it is configured in plugins
and not in module
. Let's analyze it.
All the files of our project can be considered as a module, but whether we configure them in module
or plugins
depends on what we want to use them for. Generally, if we use the module in our own source code, we need a Loader
to parse it**.
When we explained how to deal with img
and js
above, our purpose was to parse these files in the source code:
-
img
, which we need to convert tobase64
-
js
, we need to compilees6+
stuff intoes5
and below
And, our files are introduced into our project by import
or require()
, so of course we need the appropriate Loader
to convert these modules.
But when dealing with html
files, our purpose is not to parse the html
, we just want the packaged html
to automatically reference our js
and img
, which is more like using the auto-introduction feature; moreover, we don't introduce our html
into our project, so of course we don't need the appropriate Loader
to parse it.
Remember from our previous post we explained that Loader
is used to transform the modules, and Plugin
is used to enhance the webpack
package when compiling.
In this case, we are dealing with the html
file, and our goal is to make the packaged html
automatically reference our js
and img
. So we need to configure the plugins
configuration item to enhance the webpack
packaging and compilation functionality.
Similarly, suppose we want to parse an html
file in our project (in our project, import html from '. /x.html'
), then we have to install the appropriate loader
(html-loader
) and configure it in the module
configuration item.
Summary
Whether to configure in the module
or plugins
configuration item depends on the purpose for which we are using these modules.
At this point, we have successfully configured webpack
to get the css
, img
, js
, and html
we need for a project; this is also equivalent to learning the basic configuration of webpack
.
You can use the methods summarized above to handle sass
, font
, video
and other resources on your own to deepen your impression.
Learning Summary
From the above explanation of some configuration items, we can have the following summary:
- To parse
css
, we need to install theloader
and configure it in themodule
. - To parse
img
,font
,video
, etc., we don't need to install theloader
(webpack
has built-in functionality to parse them). We usually useasset/resource
,asset/inline
,asset
inmodule
configuration to parse them. - To parse
js
, we need to install the appropriateloader
(babel-loader
), configure it in themodule
configuration, and most importantly, learn aboutBabel
. - To parse the
html
file, we need to configure thehtml-webpack-plugin
plugin in theplugins
configuration field. - Whether we configure it in the
module
orplugins
configuration depends on what we want to do with the modules.
With the above learning, let's organize and output a complete webpack
base configuration to make it more impressive:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
entry: {
index: './src/index.js'
},
output: {
path: path.resolve(__dirname, './dist'),
filename: './js/[name]-[chunkhash:5].js',
clean: true
},
module: {
rules: [
{
test: /.(css|less)$/,
use: [
'style-loader',
'css-loader',
'less-loader',
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 1024 * 10 // When the image size is < 10kb it will be converted to base64
}
},
generator: {
filename: '[name]-[hash:5][ext]' // Set the name of the output file
}
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, './dist/[name].html'),
template: path.resolve(__dirname, './src/index.html'),
title: 'Webpack Basic Configuration',
})
],
}
The full base configuration is at learn-07, and we recommend that you take a look at the full version, only webpack.config.js
is posted here.
Finally
- I hope some of the methods summarized in this article for learning purposes will help you learn how to configure
webapck
better. - Later articles will be in-depth configuration. In real projects, most of them are divided into development and production environments, so we will learn how to configure
webpack
differently for different environments of development and production, which is closer to our real projects. - You can support me by following my github!
Regarding the content of the article, if you have similarities and differences, feel free to discuss them in the comments section!
Top comments (0)