This article uses Webpack to build a scaffolding configuration for a development environment from scratch, and makes a note here for future use.
preface
Starting with WebPack V4.0.0, you don’t have to import a configuration file. Packaging is done directly using the webpack command. However, more flexible configuration capabilities are generally required, so in this article I will also create a WebPack configuration file to configure some of the webPack properties.
Demo address
Environment set up
The project structure
First we create a directory, initialize NPM, then install Webpack locally, then install WebPack-CLI (this tool is used to run Webpack on the command line) :
$ mkdir webpack-dev-demo && cd webpack-dev-demo
$ npm init -y
$ npm install webpack webpack-cli --save-dev
Copy the code
project
webpack-dev-demo
|- package.json
|- /public
|- index.html
|- /src
|- index.js
Copy the code
src/index.js
function component() {
var element = document.createElement('div');
element.innerHTML = 'Hello World';
return element;
}
document.body.appendChild(component());
Copy the code
public/index.js
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Webpack development environment configuration</title>
</head>
<body>
</body>
</html>
Copy the code
package.json
{
"name": "webpack-dev-demo"."version": "1.0.0"."description": ""."private": true."scripts": {
"test": "echo \"Error: no test specified\" && exit 1"."build": "webpack --config webpack.config.js"
},
"keywords": []."author": ""."license": "ISC"."devDependencies": {
"webpack": "^ 4.29.0"."webpack-cli": "^ 3.2.1." "}}Copy the code
Creating a Configuration File
Create the webpack.config.js configuration file in the project root directory
project
webpack-dev-demo
|- package.json
|- /public
|- index.html
|- /src
|- index.js
+ |- webpack.config.js
Copy the code
Configure the inlet and output
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js'.output: {
filename: '[name]-[hash:8].js'.path: path.resolve(__dirname, 'dist')}}Copy the code
Run webpack
$ npm run build
Copy the code
Console print result
You can see the print log, the package is successful, but when you open our index.html file in the browser, nothing is displayed in the interface, which is understandable because index.html has not introduced any JS files at this point. In the dist folder, the js file name has a lot of hash values, and it may be different each time you compile it. This is where the HTML-webpack-plugin comes in
Use of the HTML-webpack-plugin plugin
Install plug-in:
$ npm install html-webpack-plugin --save-dev
Copy the code
Using plug-ins:
webpack.config.js
. const HTMLWebpackPlugin =require('html-webpack-plugin');
module.exports = {
...
plugins: [
new HTMLWebpackPlugin({
// The title of the HTML document to be generated
title: 'Webpack Development Environment Configuration '.// Webpack generates the template path
template: './public/index.html'}})]Copy the code
For more information on the configuration of the HTML-webpack-plugin, please refer to the plugin documentation.
Run Webpack again
$ npm run build
Copy the code
You can see that the dist folder generates an index. HTML file. When you open the index. HTML file in your browser, you can see that ‘Hello World’ now displays normally
At this point, the project is packaged normally, but not enough. You can see that there are two JS files in the dist folder, but there is only one package. It was because of another package that we typed out in the last operation and did not delete it. So, to avoid cluttered files in the Dist folder, we also need to introduce the clean-webpack-plugin to help us clean up the Dist folder
Use of the clean-webpack-plugin plugin
Install plug-in:
$ npm install clean-webpack-plugin --save-dev
Copy the code
New CleanWebpackPlugin(Paths [, {options}])
webpack.config.js
. const CleanWebpackPlugin =require('clean-webpack-plugin');
module.exports = {
...
plugins: [
...,
New CleanWebpackPlugin(Paths [, {options}])
new CleanWebpackPlugin(['dist'])]}Copy the code
Run Webpack again
$ npm run build
Copy the code
Now there is only one JS and HTML file in the dist folder. The plug-in configuration is successful. For more information about the clean-Webpack-plugin configuration, please refer to the plug-in documentation.
Configure the Http service and preview the data in real time
Install the webpack-dev-server package:
$ npm install --save-dev webpack-dev-server
Copy the code
Use:
webpack.config.js
. const webpack =require('webpack');
module.exports = {
...
devServer: {
// Must be configured, the service start directory, default is the following directory
contentBase: './dist'.// Set to true for hot loading
hot: true./** ** The following is optional */
// Specify the use of a host. The default is localhost
host: 'localhost'./ / the port number
port: 8000.// When using the HTML5 History API, any 404 response may need to be replaced with index.html. Enable by setting it to true
historyApiFallback: {
disableDotRule: true
},
// Whether a mask layer prompt appears on the browser when an error occurs
overlay: true./** * Switches between two different modes of dev-server * by default, the application enables inline mode inline * set to false and uses iframe mode, which uses the
inline: true./** * statistics, enumeration type, optional: * "errors-only": outputs only when errors occur * "minimal": outputs only when errors occur or new compilations * "None ": outputs none * "normal": Standard output * "verbose": all output */
stats: "errors-only"./ / Settings interface request broker, more proxy configuration please refer to https://github.com/chimurai/http-proxy-middleware#options
proxy: {
'/api/': {
changeOrigin: true.// Destination address
target: 'http://localhost:3000'.// Rewrite the path
pathRewrite: {
'^/api/': '/'}}}},plugins: [...// Add the NamedModulesPlugin to make it easier to view the dependencies to be patched. This plugin can be omitted because mode: 'development' is set
// new webpack.NamedModulesPlugin(),
// Perform module hot replacement
new webpack.HotModuleReplacementPlugin()
]
}
Copy the code
1, Add hot to devServer configuration: True attribute. 2, in the plugins to add new webpack NamedModulesPlugin () and new webpack HotModuleReplacementPlugin ()
Add an execution command to package.json
package.json
. "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --config webpack.config.js", + "start": "webpack-dev-server" } ...Copy the code
Starting the Http Service
Execute command:
$ npm run start
Copy the code
You can see the console print:
Open the browser and enter http://localhost:8000/. Hello World is displayed normally.
Pattern configuration
Webpack configuration has a mode property configuration with three optional properties:
-
Production sets the value of process.env.node_env to production. Enable FlagDependencyUsagePlugin FlagIncludedChunksPlugin, ModuleConcatenationPlugin NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin and UglifyJsPlugin.
-
Development sets the value of process.env.node_env to development. Enable NamedChunksPlugin and NamedModulesPlugin.
-
None does not use any default optimization options
Here we are configuring the development environment, so we need to set mode to Development
webpack.config.js
. module.exports = { + mode:'development'. }Copy the code
Enable the debug tool Source Map
At this point, the project is working, so there is no problem, but now we have to change the return element in index.js to the wrong return ele. We opened the development tool F12 and could see the error message on the console. When we clicked it, we found that it was inconsistent with the code we wrote and it was difficult to debug the wrong code. At this time, Source Map came in handy.
Add the devTool property in webpack.config.js
webpack.config.js
. module.exports = {mode: 'development',
+ devtool: inline-source-map
...
}
Copy the code
Differences between multiple attributes of Devtool
devtool | Build speed | Rebuild speed | The production environment | Quality (quality) |
---|---|---|---|---|
(none) | +++ | +++ | yes | Packaged code |
eval | +++ | +++ | no | Generated code |
cheap-eval-source-map | + | ++ | no | Converted code (line only) |
cheap-module-eval-source-map | o | ++ | no | Original source code (line only) |
eval-source-map | — | + | no | Original source code |
cheap-source-map | + | o | yes | Converted code (line only) |
cheap-module-source-map | o | – | yes | Original source code (line only) |
inline-cheap-source-map | + | o | no | Converted code (line only) |
inline-cheap-module-source-map | o | – | no | Original source code (line only) |
source-map | — | — | yes | Original source code |
inline-source-map | — | — | no | Original source code |
hidden-source-map | — | — | yes | Original source code |
nosources-source-map | — | — | yes | No source code content |
Run the project again:
$ npm run start
Copy the code
You can see that the error is still reported, but in the development tool console, check the error message, you can clearly find the location of the code we wrote.
After testing, change the wrong return ele to the correct return Element
Add a module resolution rule to the project
At this point, the development environment is almost configured, but NOW I want to add a style for div, want to make the text programming blue, center display, then need to use loader, because webPack default can not parse CSS, so we need to configure our own
Configure CSS module resolution
Install the required plug-ins:
$ npm install css-loader style-loader --save-dev
Copy the code
Css-loader is used to parse CSS files, while style-loader is used to inject parsed CSS content into JavaScript. Since loader is executed from bottom to top, write CSS-Loader below.
Use:
webpack.config.js
. module.exports = { ... plugins: [...] .module: {
rules: [{test: /\.css$/.use: [
'style-loader'.// You can also add some configuration to the loader
{
loader: 'css-loader'.options: {
/ / open sourceMop
sourceMap: true}}]}}Copy the code
Create a new CSS file in the SRC directory
SRC/index. CSS:
div {
color: blue;
text-align: center;
}
Copy the code
src/index.js
require('./index.css'); .Copy the code
Rerun the project:
$ npm run start
Copy the code
You can see that the text has turned blue and is centered on the browser.
Configure other module resolution
In addition to CSS, other files are considered as modules in Webpack and need to be parsed by the corresponding Loader. The following is not a demonstration, first put the code posted to have a look.
Download all required plug-ins:
$ npm install file-loader csv-loader xml-loader html-loader markdown-loader --save-dev
Copy the code
webpack.config.js
. module.exports = { ... plugins: [...] .module: {
rules: [...// Parse image resources
{
test: /\.(png|svg|jpg|gif)$/.use: [
'file-loader']},// Parse the font
{
test: /\.(woff|woff2|eot|ttf|otf)$/.use: [
'file-loader']},// Parse data resources
{
test: /\.(csv|tsv)$/.use: [
'csv-loader']},// Parse data resources
{
test: /\.xml$/.use: [
'xml-loader']},// Parse the MakeDown file
{
test: /\.md$/.use: [
"html-loader"."markdown-loader"}]}}Copy the code
These configurations can basically meet the various module resources used in conventional development, but in the development process may also need to use CSS precompiled languages such as LESS, SCSS, and need to use less-Loader, sas-loader for configuration. More configuration usage here can not be detailed one by one, and so we use the time to refer to the corresponding documentation.
Use Babel for configuration
At present, the project can run normally, but now ES6 and 7 grammars have come out, but the browser cannot fully recognize them, so we need Babel to convert JS files into ES5 grammars that can be recognized by the browser.
Install the babel-loader plug-in
$ npm install babel-core babel-loader --save-dev
Copy the code
Babel can also be configured, either directly in the Loader as above, or by creating a.babelrc file in the root directory from which the project is automatically read
Use the Babel – loader:
webpack.config.js
. module.exports = { ... plugins: [...] .module: {
rules: [{test: /\.js/.include: path.resolve(__dirname, 'src'),
loader: 'babel-loader? cacheDirectory',},]}}Copy the code
CacheDirectory property for Babel
The default value is false. If set, the specified directory will be used to cache loader execution results. Subsequent WebPack builds will attempt to read the cache to avoid the potentially high-performance Babel recompilation process that can occur each time it is executed. If a null value is set (loader: ‘babel-loader? CacheDirectory ‘) or true (loader: babel-loader? CacheDirectory =true), loader will use the default cache directory node_modules/. Cache /babel-loader, if the node_modules directory is not found in any root directory, It will degrade back to the default temporary file directory of the operating system.
Speed up babel-loader by at least twice with the cacheDirectory option.
Presets configuration for Babel
The presets attribute tells Babel which new syntax features are being used in the source code being converted. A single preset supports a set of new syntax features, and multiple presets can be stacked. Presets are collections of Plugins, each of which performs the task of converting a new syntax. Presets are organized according to ECMAScript drafts and can generally be grouped into three broad categories:
-
Features already written into the ECMAScript standard are subdivided as new features are added to the standard each year:
- Es2015 includes new features added in 2015;
- Es2016 includes new features added in 2016;
- Es2017 includes new features added in 2017;
- Env contains all the latest features in the current ECMAScript standard.
-
Features proposed by the community but not yet written into the ECMAScript standard fall into the following four categories:
- Stage0 is just a nice radical idea, there is a Babel plugin that supports these features, but it is not certain that they will be made standard;
- Stage1 features worthy of inclusion in the standard;
- Stage2 This feature specification has been drafted and will be included in the standard;
- Stage3 This feature specification has been finalized and major browser vendors and the Node.js community have started implementing it.
- Stage4 will be added to the standard over the next year.
-
For example, babel-preset-react is used to support JSX syntax in react development.
Plugins configuration for Babel
The plugins attribute tells Babel which plug-ins to use, and plug-ins control how the code is transformed.
Install the Presets plug-in that you need to use in your project
$ npm install babel-preset-env babel-preset-stage-0 --save-dev
Copy the code
Install the Babel Plugin required in the project
$ npm install babel-plugin-transform-class-properties babel-plugin-transform-runtime babel-runtime --save-dev
Copy the code
-
Babel-plugin-transform-class-properties allows you to use the new class attribute usage in your project
-
Since babel-plugin-transform-Runtime converts files with auxiliary code in each file, you can use the code in Babel-Runtime directly to convert files, avoiding code redundancy. So babel-plugin-transform-Runtime and babel-Runtime are used in pairs
.babelrc
{
"presets": ["env"."stage-0"]."plugins": [
"transform-runtime"."transform-class-properties"]}Copy the code
When the configuration is complete, you can use ES6 and other new JS syntax freely in your project.
Use the friendly – errors – webpack – the plugin
Sometimes the project will have an error, maybe a compilation error, maybe an ESLint error, etc. We want the error to be friendly and we can use this plugin
Plug-in installation:
npm install friendly-errors-webpack-plugin --save-dev
Copy the code
Use:
webpack.config.js
. const FriendlyErrorsWebpackPlugin =require('friendly-errors-webpack-plugin');
module.exports = { ... .plugins: [
...
new FriendlyErrorsWebpackPlugin()
]
}
Copy the code
Refer to the plug-in documentation for more configurations
How does the config module resolve
Configure resolve to alias some common paths. If you need to configure resolve to alias some common paths, you can configure resolve to alias some common paths
Configuration:
webpack.config.js
. module.exports = { ... plugins: [...] .modules: {... },resolve: {
alias: {
src: path.resolve(__dirname, 'src')}}}Copy the code
Use: When importing index.css files from the SRC directory in any file, the path can be written as follows
index.js
- require('./index.css');
+ import 'src/index.css';
Copy the code
Rerun the project and find that the project starts normally and the styles in index.css work properly
At this point, the Webpack scaffolding for a simple development environment is complete.
Final project structure and file code
project
webpack-dev-demo
|- package.json
|- /public
|- index.html
|- /src
|- index.js
|- index.css
Copy the code
public/index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Webpack development environment configuration</title>
</head>
<body>
</body>
</html>
Copy the code
src/index.js
import 'src/index.css';
function component() {
var element = document.createElement('div');
element.innerHTML = 'Hello World';
return element;
}
document.body.appendChild(component());
Copy the code
src/index.css
div {
color: blue;
text-align: center;
}
Copy the code
.babelrc
{
"presets": ["env"."stage-0"]."plugins": [
"transform-runtime"."transform-class-properties"]}Copy the code
webpack.config.js
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode: 'development'.devtool: 'inline-source-map'.entry: './src/index.js'.output: {
filename: '[name]-[hash:8].js'.path: path.resolve(__dirname, 'dist')},devServer: {
// Must be configured, the service start directory, default is the following directory
contentBase: './dist'.// Set to true for hot loading
hot: true./** ** The following is optional */
// Specify the use of a host. The default is localhost
host: 'localhost'./ / the port number
port: 8000.// When using the HTML5 History API, any 404 response may need to be replaced with index.html. Enable by setting it to true
historyApiFallback: {
disableDotRule: true
},
// Whether a mask layer prompt appears on the browser when an error occurs
overlay: true./** * Switches between two different modes of dev-server * by default, the application enables inline mode inline * set to false and uses iframe mode, which uses the
inline: true./** * statistics, enumeration type, optional: * "errors-only": outputs only when errors occur * "minimal": outputs only when errors occur or new compilations * "None ": outputs none * "normal": Standard output * "verbose": all output */
stats: "errors-only"./ / Settings interface request broker, more proxy configuration please refer to https://github.com/chimurai/http-proxy-middleware#options
proxy: {
'/api/': {
changeOrigin: true.// Destination address
target: 'http://localhost:3000'.// Rewrite the path
pathRewrite: {
'^/api/': '/'}}}},plugins: [
new HTMLWebpackPlugin({
// The title of the HTML document to be generated
title: 'Webpack Development Environment Configuration '.// Webpack generates the template path
template: './public/index.html'
}),
New CleanWebpackPlugin(Paths [, {options}])
new CleanWebpackPlugin(['dist']),
// Add the NamedModulesPlugin to make it easier to view the dependencies to be patched. This plugin can be omitted because mode: 'development' is set
// new webpack.NamedModulesPlugin(),
// Perform module hot replacement
new webpack.HotModuleReplacementPlugin()
],
module: {
rules: [{test: /\.js/.include: path.resolve(__dirname, 'src'),
loader: 'babel-loader? cacheDirectory'
},
/ / CSS
{
test: /\.css$/.include: path.resolve(__dirname, 'src'),
use: [
'style-loader'.// You can also add some configuration to the loader
{
loader: 'css-loader'.options: {
/ / open sourceMop
sourceMap: true}}},// Parse image resources
{
test: /\.(png|svg|jpg|gif)$/.use: [
'file-loader']},// Parse the font
{
test: /\.(woff|woff2|eot|ttf|otf)$/.use: [
'file-loader']},// Parse data resources
{
test: /\.(csv|tsv)$/.use: [
'csv-loader']},// Parse data resources
{
test: /\.xml$/.use: [
'xml-loader']},// Parse the MakeDown file
{
test: /\.md$/.use: [
"html-loader"."markdown-loader"]]}},resolve: {
alias: {
src: path.resolve(__dirname, 'src')}}}Copy the code
package.json
{
"name": "webpack-dev-demo"."version": "1.0.0"."description": ""."private": true."scripts": {
"test": "echo \"Error: no test specified\" && exit 1"."build": "webpack --config webpack.config.js"."start": "webpack-dev-server"
},
"keywords": []."author": ""."license": "ISC"."devDependencies": {
"babel-core": "^ 6.26.3"."babel-loader": "^ 7.1.5." "."babel-plugin-transform-class-properties": "^ 6.24.1"."babel-plugin-transform-runtime": "^ 6.23.0"."babel-preset-env": "^ 1.7.0"."babel-preset-stage-0": "^ 6.24.1"."babel-runtime": "^ 6.26.0"."clean-webpack-plugin": "^" 1.0.1."css-loader": "^ 2.1.0." "."html-webpack-plugin": "^ 3.2.0"."style-loader": "^ 0.23.1"."webpack": "^ 4.29.0"."webpack-cli": "^ 3.2.1." "."webpack-dev-server": "^ 3.1.14"}}Copy the code
The source address
Demo address
conclusion
This article is a long one. Thank you for your patience. This article mainly from the entry, output, Plugins, Module processing, loader, resolve and other six configuration items to configure a basic Webpack development environment scaffolding. The main contents of this paper are as follows:
-
What does loader do and how to configure it
-
The role of Babel and configuration items
-
Functions and application scenarios of each plug-in
-
Parsing can bring efficiencies to development
This article may be a bit superficial for those of you who are already familiar with Webpack, but it focuses on the functionality of each configuration item and the effect it has on the project. For the preparation of entry webpack friends should have certain help.