Skip to content

自定义文件列表插件(多输出一个文件,记录打包后所有文件的大小)

本节实现一个打包后记录各个打包文件大小的插件。

准备工作

安装插件

shell
yarn add html-webpack-plugin@^3.2.0 -D

新建index.html

html
<!-- webpack\webpack-plugin\src\index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>

</html>

自定义插件 FileListPlugin

修改配置文件

js
// webpack\webpack-plugin\webpack.config.js
let path = require('path')
let DonePlugin = require('./plugins/DonePlugin.js')
let AsyncPlugin = require('./plugins/AsyncPlugin.js')
let HtmlWebpackPlugin = require('html-webpack-plugin')
let FileListPlugin = require('./plugins/FileListPlugin.js')

module.exports = {
    mode: 'development',

    entry: './src/index.js',

    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },

    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),

        // 在文件要发射,还没发射的时候,添加一个文件
        // list.md
        // 记录一下 各个打包文件的大小
        new FileListPlugin({
            filename: 'list.md'
        })
    ]
}

代码

js
// webpack\webpack-plugin\plugins\FileListPlugin.js
class FileListPlugin {
    constructor({ filename }) {
        this.filename = filename // 把传过来的参数 挂载到实例上
    }
    apply(compiler) {
        // 文件已经准备好了 要进行发射
        // emit
        compiler.hooks.emit.tap('FileListPlugin', (compliation) => {
            // compliation 上面带了很多 webpack 当前处理过程中 带的内容
            // console.log(Object.keys(compliation));

            /* compliation.assets
                {
                    'bundle.js': CachedSource {
                        _source: ConcatSource { children: [Array] },
                        _cachedSource: undefined,
                        _cachedSize: 3937,
                        _cachedMaps: {},
                        node: [Function (anonymous)],
                        listMap: [Function (anonymous)]
                    },
                    'index.html': { source: [Function: source], size: [Function: size] }
                }
            */
            // console.log(compliation.assets);

            // 只需要在发射之前 在增加一个list.md 到 compliation.assets 上,就会别打包出来
            // 遵照上面的格式增加一下

            let assets = compliation.assets
            let content = `## 文件名    资源大小\r\n`

            // [['bundle.js',{}], ['index.js',{}] ]
            Object.entries(assets).forEach(([filename, statObj]) => {
                content += `- ${filename}    ${statObj.size()}\r\n`
            })

            // 把list.md 增加到要发射的缓存上
            assets[this.filename] = {
                source() {
                    return content
                },

                size() {
                    return content.length
                }
            }
        })
    }
}

module.exports = FileListPlugin
/* 
Object.keys(compliation)
[
  '_pluginCompat',
  'hooks',
  'name',
  'compiler',
  'resolverFactory',       
  'inputFileSystem',       
  'requestShortener',      
  'options',
  'outputOptions',
  'bail',
  'profile',
  'performance',
  'mainTemplate',
  'chunkTemplate',
  'hotUpdateChunkTemplate',
  'runtimeTemplate',       
  'moduleTemplates',       
  'semaphore',
  'entries',
  '_preparedEntrypoints',  
  'entrypoints',
  'chunks',
  'chunkGroups',
  'namedChunkGroups',
  'namedChunks',
  'modules',
  '_modules',
  'cache',
  'records',
  'additionalChunkAssets',
  'assets', // 当前要打包的文件资源列表,我们要用的就是这个
  'assetsInfo',
  'errors',
  'warnings',
  'children',
  'logging',
  'dependencyFactories',
  'dependencyTemplates',
  'childrenCounters',
  'usedChunkIds',
  'usedModuleIds',
  'fileTimestamps',
  'contextTimestamps',
  'compilationDependencies',
  '_buildingModules',
  '_rebuildingModules',
  'emittedAssets',
  'fullHash',
  'hash',
  'fileDependencies',
  'contextDependencies',
  'missingDependencies'
]
*/

打包一下 看看结果 npx webpack

image-20220207213530402

## 文件名    资源大小
- bundle.js    3937
- index.html    380

插件引入成功~

总结

本节自定义了一个自创的插件,文件列表插件

插件的功能是让webpack多打包一个list.md文件,统计打包文件的大小

插件代码需注意一下几点

  1. 在emit钩子可以获取到所有等待打包的文件缓存,该阶段还尚未发射文件

  2. 发布任务回调的参数上有很多webpack当前阶段的属性,所有打包的文件缓存都在assets上,想多生成一个文件就在这个属性上照着规范增加一个属性。

  3. 代码

    js
    // webpack\webpack-plugin\plugins\FileListPlugin.js
    class FileListPlugin {
        constructor({ filename }) {
            this.filename = filename // 把传过来的参数 挂载到实例上
        }
        apply(compiler) {
            // 文件已经准备好了 要进行发射
            // emit
            compiler.hooks.emit.tap('FileListPlugin', (compliation) => {
                // compliation 上面带了很多 webpack 当前处理过程中 带的内容
                // console.log(Object.keys(compliation));
    
                /* compliation.assets
                    {
                        'bundle.js': CachedSource {
                            _source: ConcatSource { children: [Array] },
                            _cachedSource: undefined,
                            _cachedSize: 3937,
                            _cachedMaps: {},
                            node: [Function (anonymous)],
                            listMap: [Function (anonymous)]
                        },
                        'index.html': { source: [Function: source], size: [Function: size] }
                    }
                */
                // console.log(compliation.assets);
    
                // 只需要在发射之前 在增加一个list.md 到 compliation.assets 上,就会别打包出来
                // 遵照上面的格式增加一下
    
                let assets = compliation.assets
                let content = `## 文件名    资源大小\r\n`
    
                // [['bundle.js',{}], ['index.js',{}] ]
                Object.entries(assets).forEach(([filename, statObj]) => {
                    content += `- ${filename}    ${statObj.size()}\r\n`
                })
    
                // 把list.md 增加到要发射的缓存上
                assets[this.filename] = {
                    source() {
                        return content
                    },
    
                    size() {
                        return content.length
                    }
                }
            })
        }
    }
    
    module.exports = FileListPlugin

参考

https://www.bilibili.com/video/BV1a4411e7Bz?p=48&spm_id_from=pageDriver