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.