Preface
We often see structures like the following when using webpack
:
build
├── webpack.common.js
└── webpack.dev.js
└── webpack.prod.js
Often times, webpack
configurations we basically copy and paste without thinking about why we're breaking the config file down into so many. As a result, when we learn to configure webpack
on our own, we often have problems such as the following:
- Slow builds in development environments
- Blank pages after packaging
- Resources not found
In fact, these problems, all stem from us:
- Not understanding
webpack
to build the development environment, production environment, the two environment configuration of the difference in thinking - We don't have a clear understanding of the file directories of the two environments.
So this article is the same as before, will not just copy the configuration over, but hope that summarize the relevant methods, so that we can better learn to configure.
Learning Outline
This article focuses on:
- The core idea of
webpack
development environment configuration. - Completing a development environment configuration based on the core concepts
- Explain some confusing points in the
devServer
configuration. - Summarize the core ideas of
webpack
development environment configuration.
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 along with the article and write the code yourself - It's not easy to create, if you think it's helpful, welcome to
star
🌟!
Development Environment Core Ideas
We mentioned above that we often see directories like the following when using webpack
:
build
├── webpack.common.js
└── webpack.dev.js
└── webpack.prod.js
Why do we need to break the configuration file into so many, so cumbersome?
Let's first review, in our actual development, in order to project can be stable and safe on-line, we will generally be divided into several environments:
- Development environment: local development, debugging environment
- Test environment: we complete the local development, the code will be deployed to our test server, for testing
- Production environment: the test passed, the code will be deployed to the official server, the official on-line
Some of the more rigorous tests will have pre-production environments, etc.
Our configuration should be specific to the environment, so of course our configuration should not be the same for different environments.
Purpose
We need to be clear about what the fundamental purpose of the development environment is.
The fundamental purpose of the development environment is to quickly locate problems during the development process, to see the effect of debugging faster, and to improve development efficiency.
Especially as a front-end, inseparable from the visual dealings. We can't wait to Ctrl+S
, immediately after the effect, so that we can quickly debug. Imagine if every time we write an effect, we have to wait for a few seconds before we can see it, will this drive us crazy?
Ideas
Therefore, in order for us to see the effect debugging as soon as possible, reducing the webpack
compilation process, development environment, the configuration should be everything from simple:
- For styles, we don't need to separate them and insert them directly into the
<head />
with thestyle-loader
. - For
js
,img
,media
,font
and other front-end resource files, we don't need to separate them. - Enable
source map
to locate the problem. - Use the
devServer
configuration provided bywebpack
for local development. - Don't compress code.
- Don't use unnecessary
loader
andplugins
. - ...
Development environment configuration is also different from person to person, this is what I do. But we should remember that development environment, configuration should be kept simple, in order to let us see the results faster, improve development efficiency!
Development environment configuration
First experience
Through the previous explanation, I believe you are familiar with the basic configuration of webpack
:
- Handling
css, less
, front-end resources and other files - Compiling
es6+
syntax andapi
. - Processing
html
files
have mastered the relevant configuration methods, and we also summarized a basic configuration, not too clear students can look at the first, this basic configuration is still quite important.
ok, then we first use learn-08 this case to experience how to do local development debugging. In order to be as close as possible to our real-life development projects, the case will:
- refer to the image in
html
. - use
less
to reference an image - use
es6+
injs
to load images dynamically. -
Use the
devServer
configuration item.
For ease of reading, I'm not going to put the source code in the article, you can go to github to see it.
Then perform the following steps:
- for semantic purposes, we name the
webpack
configuration filewebpack.dev.js
- Start
webpack
on the command line -npm start
.
"scripts": {
"start": "webpack server --config ./webpack.dev.js"
}
Run the results:
We will find:
- After the file compilation and processing is complete, no file is outputted
- At this point, an internal server (
http://192.168.0.196:8080/
) is turned on. If we are on the same network as our computer, we can access this link from our phone and see the results. This is very efficient for debuggingH5
development (this is mainly due to thedeveServer
configuration item, which will be explained later on) - The page is updated in real time after we change the code
The above is pretty much what we want for efficient development.
Analyzing
After the initial experience, let's take a look at how to configure the development environment based on the development environment configuration ideas summarized above:
- Parsing styles does not require separating out the
css
file; we insert the parsed styles directly into the<header />
:
module: {
rules: [
{
test: /.(css|less)$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
},
]
},
- For
js
,img
,media
,font
and other front-end resource files, there is no need to subpackage:
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name]-[chunkhash:5].js',
},
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 1024 * 3 // When the image size is < 3kb 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'
}
}
]
},
- Enable
source map
to make it easier to locate the problem; and not compress the code:
{
mode: 'development',
devtool: 'inline-cheap-module-source-map'
}
- Use the
devServer
provided withwebpack
for local development:
devServer: {
static: {
directory: path.join(__dirname, 'static'),
},
},
- No other extra
plugins
were installed, only theplugin
that parseshtml
was installed because it parseshtml
:
plugins: [
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, './dist/[name].html'),
template: path.resolve(__dirname, './src/index.html'),
title: 'webpack.dev.config',
})
],
If we compare the base configuration, we will find that the development environment configuration is almost the same as the base configuration, except that the devServer
configuration item is used more to enable local server debugging:
// webpack.dev.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
+ mode: 'development',
+ devtool: 'inline-cheap-module-source-map',
entry: {
index: './src/index.js'
},
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name]-[chunkhash:5].js',
},
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 * 3 // When the image size is < 3kb it will be converted to base64
}
},
generator: {
filename: '[name]-[contenthash:5][ext][query]' // 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.dev.config',
})
],
+ devServer: {
+ static: {
+ directory: path.join(__dirname, 'static'),
+ },
+ }
}
devServer
Remember our previous case, how we ran our code? We ran it with our own editor (vscode
) to see the results after we had packaged it. If we were that inefficient, we wouldn't be able to go live with our project.
That's why webpack
provides a very user-friendly configuration item called devServer
.
To use it, we need to install the
webpack-dev-server
dependencynpm i webpack-dev-server -D
.
From such a semantic name, we know that it must be a configuration that provides some kind of service in the development environment.
The service is that this will enable a local service that will compile our configured webpack
, in real time, and save it in memory, so that we can easily debug our code, which serves the purpose of our local development needs to be efficient very well.
So this configuration item, only used for our development environment configuration.
devServer.static
Documentation Explanation: tells the server where to serve content from. This is only necessary if you wish to serve static files
Misinterpretation
The devServe
configuration item is actually written in quite a bit of detail in the documentation, so here's a potentially confusing one - devServe.static
.
A lot of people use webpack
and copy and paste, so it's common to see configurations like the following:
output: {
path: path.resolve(__dirname, '. /dist'), .
}
devServer: {
static: {
directory: path.join(__dirname, 'dist'), }
}
}
Because the folder we set up for output after packaging is generally dist
, the devServe.static
configuration item specifies that the directory of static files to be served is also dist
. So, we would naturally assume that the contents of the local server access opened by webpack
at this point would be the contents inside the dist
folder.
Therefore, we would incorrectly conclude that devServe.static
serves to set the directory that is accessed by the local server when webpack
is turned on.
However, we can look at dev.config.js above, where we set the name of the folder we output after packaging to dist
, and the directory set by devServe.static
is static
. If we follow our misinterpretation above, we should have a 404
or a blank page on our server at this point due to the difference in the two folder settings, but we can still run our service.
This means that devServe.static
is not setting the directory where the packaged output folder is accessed when webpack
is turned on for the local server.
Correctly understood
Analysis
Let's move on to the learn-08 case (the static
folder holds the logo.png
image inside).
We previously wanted to reference the image in question inside js
, which we typically do:
// index.js
const img = new Image();
img.src = require('Your image path');
We normally require
the image according to the relative path, which is equivalent to a module, so the image will be compiled by webpack
(adding hash
or converting it to base64
), and then written to the final directory (output.path
) that we have set up.
But when we set up:
devServer: {
static: {
directory: path.join(__dirname, 'static'),
}
}
After opening the local server, this line prompts:
Content not from webpack is served from 'your path/static' directory
First of all, this means that the static
directory we set up will not be processed and packaged by webpack
, so the resources in this folder will not be parsed and compiled by webpack
, and therefore it will not be hashed
or converted to base64
.
Let's take a look at how index.js
from learn-08 uses the resources in static
:
// index.js
loadImage('./logo.png').then(img => {
console.log('I am from index.js');
img.width = 120;
document.querySelector('#js_content .img_content').append(img);
});
We will see that we are introducing the image directly using the ./
way to bring in the image, indicating that webpack
has a local server turned on that will map the contents of the static
directory we set up to the root directory.
If you've used
vue-cli
before, you'll appreciate that this is what thepublic
folder invue-cli
does.
We can access the contents of the set devServer.static.directory
folder in the following way:
- Normally
devServer.static.directory
is mapped to the root directory, so we access it usinghttp://[devServer.host]:[devServer.port]/[devServer.static.directory]
- If you want to change the access path, you can add
devServer.static.publicPath
configuration. In this case, you can usehttp://[devServer.host]:[devServer.port]/[devServer.static.publicPath]/[devServer.static.directory]
for accessing
Summary
After analyzing the explanation above, we can conclude that the correct understanding of devServer.static
should be:
- It is a directory for static resources that are not compiled by
webpack
(e.g., images, third-party resources, etc.), so it won't behashed
orbase64
; it is a directory. - When opening a
webpack
local server, it is usually mapped to the root directory of our project (you can change the access directory viadevServe.static.publicPath
) - Since it's not compiled and packaged by
webpack
, we usually end up copyingdevServer.static.directory
to the root ofoutput.path
withcopy-webpack-plugin
- It functions much like the
public
folder insidevue-cli
, which we can use when we develop via./
or../
to access that resource (depending on the directory relationship).
Core
Okay, so we know from the above explanation of the development environment configuration and devServer
:
- The development environment configuration is kept simple, so resources such as
img
,js
, etc. are mapped directly to the root directory (css
is inserted into<head />
). - The development environment
webpack
also mapsdevServer.static.directory
to the root directory when the local server is enabled.
So after running the development environment configuration, our structure directory is roughly as follows:
dist
├── ecj-cli-b6fa8.png
├── index-c466b.js
├── index.html
└── logo.png
Configuration varies from person to person, the most important thing is that after we configure the development environment, production environment, the compilation and packaging of output content, directory, a good understanding of the structure of the mind, which is very important.
It is very important that we have a good understanding of the directory structure of the compiled and packaged output, which is very important.
We can see the structure of the development environment by the following method:
devServer.devMiddleware.writeToDisk: true
http://[devServer.host]:[devServer.port]/webpack-dev-server
- Chrome
F12 -> Sources
Finally
- This article learned how to configure the development environment, the next article will explain the configuration of the production environment before some of the preparations, so that we can better learn the production environment configuration
- The cases covered in the article have been uploaded to github, and you are really welcome to
star
orfork
them. - 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 (1)
I hope this article is helpful for you to learn
webpack
, if there are differences and similarities, welcome to discuss with me in the comments section!