webpack pit record

Recently, I am learning some configuration of webback. The expectation of learning is to add version number to the resources referenced in html files such as css, js and img files through webback, so as to avoid that the online requested resources are still the old version due to the browser's cache.

First, create a new project of webpack (by default, you have installed node's)

npm init 

Install webpack in the project

npm webpack --save-dev
npm webpack-cli --save-dev

And then you can write code happily

First of all, the packaging configuration of a single file is explained

In the root directory of the project, create a new webpack.config.js file,

npm install --save-dev html-webpack-plugin mini-css-extract-plugin 
clean-webpack-plugin
Now I will explain the functions of each plugin one by one:
  • html-webpack-plugin

When using the web pack, create an html file, and insert the static file after the web pack into the html file automatically. You can also use the custom template, such as html, pug, ejs, and configure the hash value.
There are many specific configurable parameters, such as title, meta and so on. Please refer to webpack official website

  • mini-css-extract-plugin

After webpack 4.0, the css style is extracted from js file to a separate css file;
In the project, the use scenario is to import the css file into the js file. When packing, the plug-in will recognize the css file and generate a packed css file through the configured path parameters.

  • clean-webpack-plugin

It is used to clear the files packed before the next packing. Please refer to webpack official website

loader used in the project
  • babel-loader

Babel compiles JavaScript code written in the latest standards down to a version that can be used everywhere today

  • html-loader

By default, it processes the < img SRC = "image. PNG" > in html as require("./image.png"). At the same time, you need to specify the loader of image file in your configuration, such as URL loader or file loader

  • url-loader file-loader

It is used to solve the problem of image packaging in a project. When the image resource is packaged into a packaging file, the corresponding file name and path can be modified. URL loader has a configurable limit attribute more than file loader. With this parameter, if the image size is larger than this parameter, the file resource can be used. If it is smaller than this parameter, the image can be displayed in base64 format;

  • style-loader css-loader

Package css file and insert it into html file;

Configuration of single page packaging webpack.config.js

const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const {
    CleanWebpackPlugin
} = require('clean-webpack-plugin');

const path = require("path");

module.exports = {
    mode: "development",
    entry: path.resolve(__dirname, './src/index.js'),

    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, 'build'),
        // libraryTarget: 'umd'
    },
    module: {
        rules: [{
                test: /\.html$/,
                use: [{
                    loader: "html-loader",
                    options: {
                        attrs: ['img:src', 'link:href']
                    }
                }]
            },
            {
                test: /\.js$/,
                use: {
                    loader: "babel-loader"
                },
                include: path.resolve(__dirname, '/src'),
                exclude: /node_modules/,
            },
            {
                test: /\.(jpg|png|gif|bmp|jpeg)$/,
                use: [{
                    // loader: 'file-loader',
                    loader: 'url-loader',
                    options: {
                        limit: 8192,
                        // name: '[name].[ext]',
                        name: '[name]-[hash:8].[ext]',
                        outputPath: 'images/',

                    }
                }]
            },
            {
                test: /\.pug$/,
                use: {
                    loader: 'pug-loader'
                }
            },
            {
                test: /\.css$/,
                use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader']
            },

        ],
    },
    plugins: [
        new CleanWebpackPlugin(),


        new HtmlWebpackPlugin({
            hash: true,
            template: "src/index.html",
            // template: "src/index.pug",
            filename: "bundle.html",
        }),

        new MiniCssExtractPlugin({
            filename: "bundle.css",
            chunkFilename: "index.css"
        }),

    ],
}

Multi page

In plugin, there are multiple html webback plugin plug-ins, which can generate corresponding multiple html files after packaging

Configuration of multi page packaging webpack.config.js

const getPath = require('./getPath')

const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const {
    CleanWebpackPlugin
} = require('clean-webpack-plugin');

const path = require("path");


module.exports = {
    mode: "development",
    entry: {
        main: './src/main/main.js',
        side: './src/side/side.js',
        // ...getPath.jsPathList,

    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'js/[name].js',
        publicPath: '../',
    },
    module: {
        rules: [{
                test: /\.html$/,
                use: [{
                    loader: "html-loader",
                    options: {
                        attrs: ['img:src', 'link:href']
                    }
                }, ]
            },
            {
                test: /\.js$/,
                use: [{
                    loader: "babel-loader",
                    options: {
                        presets: ['es2015']
                    }
                }],
                include: path.resolve(__dirname, '/src'),
                exclude: /node_modules/,
            },
            {
                test: /\.(jpg|png|gif|bmp|jpeg)$/,
                use: [{
                    // loader: 'file-loader',
                    loader: 'url-loader',
                    options: {
                        limit: 8192,
                        name: '[name]-[hash:8].[ext]',
                        outputPath: './images', //Specify the file system path to place the target file
                        publicPath: '../images',//Specify a custom public path for the target file
                    }
                }]
            },

            {
                test: /\.pug$/,
                use: {
                    loader: 'pug-loader'
                }
            },
            {
                test: /\.css$/,
                use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader']
            },
        ]
    },
    plugins: [
        new CleanWebpackPlugin(),
        //Output html file 1
        new HtmlWebpackPlugin({
            hash: true,
            template: "./src/main/main.html", //Address of the local html file template
            filename: "html/main.html",
            chunks: ['main'],
        }),

        new HtmlWebpackPlugin({
            hash: true,
            template: "./src/side/side.html",
            filename: "html/side.html",
            chunks: ['side'],
        }),
        // ...getPath.htmlPathList,

        new MiniCssExtractPlugin({
            filename: "css/[name].css",
            chunkFilename: "./src/[name]/[name].css"
        }),

    ]
}

Of course, you can also obtain the path of all the files to be packaged through the function, and insert them into the configuration file of webpack dynamically

const glob = require("glob");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
/**
 *
 * @param {string}  globPath  Path to file
 * @returns entries
 */

function getPath(globPath) {
    let files = glob.sync(globPath);

    let entries = {},
        entry, dirname, basename, extname;

    files.forEach(item => {
        entry = item;
        dirname = path.dirname(entry); //current directory
        extname = path.extname(entry); //Suffix
        basename = path.basename(entry, extname); //file name
        //File path
        if (extname === '.html') {
            entries[basename] = entry;
        } else if (extname === '.js') {
            entries[basename] = entry;
        }
    });

    return entries;
}

const jsPath = getPath('./src/*/*.js');
const htmlPath = getPath('./src/*/*.html');
const jsPathList = {};
const htmlPathList = [];

console.log("jsPath", jsPath)

Object.keys(jsPath).forEach((item) => {
    jsPathList[item] = path.resolve(__dirname, jsPath[item])
})

Object.keys(htmlPath).forEach((item) => {
    htmlPathList.push(new HtmlWebpackPlugin({
        hash: true,
        template: htmlPath[item],
        filename: `html/${item}.html`,
        chunks: [item],
        // chunks: [item, 'jquery'],
    }))
})

// console.log("htmlPathList", htmlPathList)


module.exports = {
    jsPathList,
    htmlPathList
}

After packing, the html, css and jpg files under a folder will be packed into the html folder, css folder and images folder under the build folder respectively, and the other resource files referenced in the html file will also be added with the hash value as the version number.

Pit:

At the beginning, both URL loader and file loader are installed with the latest version, resulting in the path of the packed image becoming < img SRC = "[object module]" / >
So this project uses "URL loader": "^ 2.1.0", "file loader": "^ 4.2.0"

click Open project github address

Tags: Javascript Webpack npm Attribute

Posted on Wed, 04 Dec 2019 01:15:00 -0800 by j.smith1981