Configure webpack from scratch (based on babel 7 version)

  Front end, javascript, node.js, Programmer, webpack

Webpack core concepts:

  • Entry: entrance
  • Module: module, everything in the webpack is a module.
  • Chunk: code base, a chunk is composed of more than ten modules, used for code merging and splitting.
  • Loader: module converter, which is used to convert the original content of the module into new content according to requirements
  • Plugin: extension plug-in, injecting extension logic at a specific time in the webpack construction process to change the construction result or do what you want to do.
  • Output: output results

Webpack process:

After the webpack is started, all Modules that the Entry depends on will be recursively analyzed from the Modules configured in the Entry. every time a Module is found, the corresponding conversion rules will be found according to the configured Loader. after the module is converted, the modules that the current module depends on will be analyzed. these modules will be grouped by the unit of Entry, and an Entry and all its dependent modules will be assigned to a group, that is, a Chunk. It is best that the Webpack will convert all Chunk to file output. During the whole process, the Webpack will execute the logic defined in Plugin at the right time.

Next, we will start from scratch to configure a webpack configuration that supports packaging pictures, CSS,LESS,SASS, ES6/ES7 and JSX syntax, and compresses the code.

1. simplest webpack configuration

First initialize npm and install webpack dependencies:

npm init -y
npm install --save-dev webpack webpack-cli

Webpack.config.js file is as follows:

const path = require('path');

module.exports = {
    entry: path.resolve(__dirname, 'src/index.js'),
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        publicPath: '/'
    }
}

Note: The address of cdn is configured when publicPath goes online.

Use the command to package:

webpack --mode production

You can also configure it into the scripts field in package.json.

The entry file is src/index.js, which is packaged and output to dist/bundle.js

2. Use template html

Html-webpack-plugin can specify template template file. html file will be generated under the output directory and js after packaging will be introduced.

Installation dependency:

npm install --save-dev html-webpack-plugin

Webpack.config.js add plugins configuration:

const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    //...other code
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, 'src/index.html')
        })
    ]
}

HtmlWebpackPlugin has some other parameters, such as title (title(html), minify (whether to compress), filename (file name of html generated in dist), etc.

3. configure webpack-dev-server

Webpack-dev-server provides a simple web server and real-time hot update capability

Installation dependency:

npm install --save-dev webpack-dev-server

Webpack.config.js add devServer configuration:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    //...other code
    devServer: {
        contentBase: './dist',
        port: '8080',
        host: 'localhost'
    }
}

Add to the scripts field of package.json:

webpack-dev-server --mode development

After that, we can start the service through npmrundv.

For more information on webpack-dev-server, please visit:https://webpack.js.org/config …

4. Support to load css files

Css files can be converted to JS file types by using different style-loader and css-loader.

Installation dependency:

npm install --save-dev style-loader css-loader

Config.js.

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.css/,
                use: ['style-loader', 'css-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            }
        ]
    }
}

Loader can configure the following parameters:

  • Test: A regular expression that matches the extension of the processing file
  • Use: loader name
  • Include/exclude: manually specify folders that must be processed or mask folders that do not need to be processed
  • Query: Provides additional setup options for loader

If you need to pass parameters to loader, you can use the method of use+loader, such as:

module.exports = {
    //other code
    module: {
        rules: [
            {
            use: [{
                        loader: 'style-loader',
                        options: {
                            insertAt: 'top'
                        }
                    },
                    'css-loader'
                ],
                //....
            }
        ]
    }
} 

5. Support loading pictures

  • File-loader: Solving the Problem of Introducing Picture Paths in CSS and Other Files
  • Url-loader: Base64 will be encoded when the picture is less than limit, and file-loader will be used to copy when the picture is greater than limit parameter.

If you want the pictures to be stored in a separate directory, you need to specify outputPath.

Installation dependency:

npm install --save-dev url-loader file-loader

Webpack.config.js (in the array of module.rules).

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192,
                            outputPath: 'images'
                        }
                    }
                ]
            }
        ]
    }
} 

6. Support compilation of less and sass

Some front-end colleagues may be accustomed to using less or sass to write css, so they also need to configure it in the webpack.

Install the corresponding dependencies:

npm install --save-dev less less-loader
npm install --save-dev node-sass sass-loader

Webpack.config.js to add the loader configuration (in the module.rules array).

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.less/,
                use: ['style-loader', 'css-loader', 'less-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.scss/,
                use: ['style-loader', 'css-loader', 'sass-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            }
        ]
    }
}        

7. Supports escaping ES6/ES7/JSX

ES6/ES7/JSX escape requires Babel’s dependency and supports decorators.

npm install --save-dev @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/plugin-proposal-decorators @babel/plugin-proposal-object-rest-spread

Webpack.config.js to add the loader configuration (in the module.rules array).

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env', '@babel/react'],
                            plugins: [
                                [require("@babel/plugin-proposal-decorators"), { "legacy": true }]
                            ]
                        }
                    }
                ],
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/
            },
        ]
    }
}

8. Compress JS files

Installation dependency:

npm install --save-dev uglifyjs-webpack-plugin
npm install --save-dev optimize-css-assets-webpack-plugin

Webpack.config.js to add the configuration of optimization

const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
    //other code
    optimization: {
        minimizer: [
            new UglifyWebpackPlugin({
                parallel: 4
            })
        ]
    }
}

9. Separate CSS (if CSS file is large)

Because CSS can be downloaded in parallel with JS, when an HTML file is large, CSS can be extracted and loaded separately.

npm install --save-dev mini-css-extract-plugin

Webpack.config.js, and modify style-loader’ to {loader: minicssextratplugin.loader}.

CSS is packaged in a separate directory, then filename is configured.

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    //other code
    module: {
        rules: [
            {
                test: /\.css/,
                use: [{ loader: MiniCssExtractPlugin.loader}, 'css-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.less/,
                use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'less-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.scss/,
                use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'sass-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        })
    ]
}

10. Compress CSS files

Installation dependency:

npm install --save-dev optimize-css-assets-webpack-plugin

Add configuration to optimization in webpack.config.js

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
    //other code
    optimization: {
        minimizer: [
            new OptimizeCssAssetsWebpackPlugin()
        ]
    }
}

11. Empty the output directory before packing

npm install --save-dev clean-webpack-plugin

Config.js add plugins configuration to webpack.config.js

const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
    //other code
    plugins: [
        new CleanWebpackPlugin()
    ]
}

At this point, the webpack configuration has basically met the requirements.

Webpack.config.js and package.json files

Config.js file:

const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');
const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
    entry: path.resolve(__dirname, 'src/index.js'),
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        publicPath: '/'
    },
    devServer: {
        contentBase: './dist',
        port: '8080',
        host: 'localhost'
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env', '@babel/react'],
                            plugins: [
                                [require("@babel/plugin-proposal-decorators"), { "legacy": true }]
                            ]
                        }
                    }
                ],
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/
            },
            {
                test: /\.css/,
                use: [{ loader: MiniCssExtractPlugin.loader}, 'css-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.less/,
                use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'less-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.scss/,
                use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'sass-loader'],
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024,
                            outputPath: 'images'
                        }
                    }
                ]
            }
        ]
    },
    optimization: {
        minimizer: [
            new UglifyWebpackPlugin({
                parallel: 4
            }),
            new OptimizeCssAssetsWebpackPlugin()
        ]
    },
    plugins: [
        new htmlWebpackPlugin({
            template: path.resolve(__dirname, 'src/index.html'),
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        }),
        new CleanWebpackPlugin()
    ]
}

Json file:

{
  "name": "webpk",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode production",
    "dev": "webpack-dev-server --mode development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.4.0",
    "@babel/plugin-proposal-decorators": "^7.4.0",
    "@babel/plugin-proposal-object-rest-spread": "^7.4.0",
    "@babel/preset-env": "^7.4.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "clean-webpack-plugin": "^2.0.1",
    "css-loader": "^2.1.1",
    "file-loader": "^3.0.1",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.9.0",
    "less-loader": "^4.1.0",
    "mini-css-extract-plugin": "^0.5.0",
    "node-sass": "^4.11.0",
    "optimize-css-assets-webpack-plugin": "^5.0.1",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "uglifyjs-webpack-plugin": "^2.1.2",
    "url-loader": "^1.1.2",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.2.1"
  },
  "dependencies": {
    "react": "^16.8.4",
    "react-dom": "^16.8.4",
    "react-redux": "^6.0.1",
    "redux": "^4.0.1"
  }
}

For more parameters of loader and plugin, please refer to:
https://www.webpackjs.com/loa …
https://www.webpackjs.com/plu …

Thank you for taking the precious time to read this article. If this article gives you some help or inspiration, then don’t be stingy with your praise and Star Ha. Your affirmation is my greatest motivation to move forward.https://github.com/YvetteLau/ …

If you have other webpack configuration requirements, please leave a message ~

Recommend to pay attention to my public number:

clipboard.png