Open huruji opened 5 years ago
最近想要了解一下 webpack 的 plugin 怎么写,于是各种文章就会告诉你想要写一个 plugin 那么你首先需要了解一下 Compilation、compiler 对象,然后 plugin 插件其实是一个含有 apply 方法的 class,而 apply 方法的参数就是 compiler 对象,compiler 对象里有各种钩子,这些钩子分别会在 webpack 的运行过程中触发,而实现这些钩子的核心是 tapable ,这个 tapable 还算好理解,可以把它看做是一个更高级的 发布-订阅。然后我想实现以下 done 这个 hook 的功能,你就会发现这个 hook 的参数是 stats 对象,所以问题来了,我想要去实现 一个 plugin,那么是真的要搞清这些对象了。
我先弄了一个最简单的 webpack 配置:
const path = require('path') const myplugin = require('./myplugin') const config = { entry: path.join(__dirname, 'index.js'), output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, use: 'babel-loader' } ] }, plugins: [ new myplugin() ], mode: "development" } module.exports = config
myplugin 是实现在 compiler 的 done hook中,内容如下:
const fs = require('fs') class HelloWord { apply(compiler) { compiler.hooks.done.tap('helloword', (stat) => { fs.writeFile('stat.json', JSON.stringify(stat, null, 2), {flag: 'w+'}); console.log('hello world') }) } } module.exports = HelloWord
然后控制台会告诉你 stats 对象内有循环引用,所以 JSON.stringify 会报错,那么使用 StackOVerflow 的方法解决:
JSON.stringify
const fs = require('fs') class HelloWord { apply(compiler) { compiler.hooks.done.tap('helloword', (stat) => { const cache = [] fs.writeFile('stats.json', JSON.stringify(stat, (key, value) => { if (cache.indexOf(value) !== -1) { return; } cache.push(value); })) console.log('hello world') }) } } module.exports = HelloWord
好的,这下可以正常输出了,我们打开我们的文件,文件内容如下:
{ "compilation": { "_pluginCompat": { "_args": [ "options" ], "taps": [ { "type": "sync", "name": "Compilation" }, { "name": "Tapable camelCase", "stage": 100 }, { "name": "Tapable this.hooks", "stage": 200 } ], "interceptors": [] }, "hooks": { "buildModule": { "_args": [ "module" ], "taps": [], "interceptors": [], "_x": [] }, "rebuildModule": { "_args": [ null ], "taps": [ { "name": "FlagDependencyExportsPlugin" } ], "interceptors": [] }, "failedModule": { "_args": [ null, "error" ], "taps": [], "interceptors": [] }, "succeedModule": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "addEntry": { "_args": [ "entry", "name" ], "taps": [], "interceptors": [], "_x": [] }, "failedEntry": { "_args": [ null, null, null ], "taps": [], "interceptors": [] }, "succeedEntry": { "_args": [ null, null, null ], "taps": [], "interceptors": [], "_x": [] }, "dependencyReference": { "_args": [ "dependencyReference", "dependency", null ], "taps": [], "interceptors": [] }, "finishModules": { "_args": [ "modules" ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "finishRebuildingModule": { "_args": [ null ], "taps": [ {} ], "interceptors": [] }, "unseal": { "_args": [], "taps": [ { "name": "SplitChunksPlugin" } ], "interceptors": [] }, "seal": { "_args": [], "taps": [ { "name": "WarnCaseSensitiveModulesPlugin" } ], "interceptors": [], "_x": [ null ] }, "beforeChunks": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "afterChunks": { "_args": [ "chunks" ], "taps": [ { "name": "WebAssemblyModulesPlugin" } ], "interceptors": [], "_x": [ null ] }, "optimizeDependenciesBasic": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeDependencies": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeDependenciesAdvanced": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "afterOptimizeDependencies": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "optimize": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "optimizeModulesBasic": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeModules": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeModulesAdvanced": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "afterOptimizeModules": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeChunksBasic": { "_args": [ null, "chunkGroups" ], "taps": [ { "name": "EnsureChunkConditionsPlugin" }, { "name": "RemoveParentModulesPlugin" }, { "name": "RemoveEmptyChunksPlugin" }, { "name": "MergeDuplicateChunksPlugin" } ], "interceptors": [], "_x": [ null, null, null, null ] }, "optimizeChunks": { "_args": [ null, null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeChunksAdvanced": { "_args": [ null, null ], "taps": [ {}, {} ], "interceptors": [], "_x": [ null, null ] }, "afterOptimizeChunks": { "_args": [ null, null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeTree": { "_args": [ null, null ], "taps": [], "interceptors": [], "_x": [] }, "afterOptimizeTree": { "_args": [ null, null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeChunkModulesBasic": { "_args": [ null, null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeChunkModules": { "_args": [ null, null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeChunkModulesAdvanced": { "_args": [ null, null ], "taps": [], "interceptors": [], "_x": [] }, "afterOptimizeChunkModules": { "_args": [ null, null ], "taps": [], "interceptors": [], "_x": [] }, "shouldRecord": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "reviveModules": { "_args": [ null, "records" ], "taps": [ { "name": "RecordIdsPlugin" } ], "interceptors": [], "_x": [ null ] }, "optimizeModuleOrder": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "advancedOptimizeModuleOrder": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "beforeModuleIds": { "_args": [ null ], "taps": [ { "name": "NamedModulesPlugin" } ], "interceptors": [], "_x": [ null ] }, "moduleIds": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeModuleIds": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "afterOptimizeModuleIds": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "reviveChunks": { "_args": [ null, null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "optimizeChunkOrder": { "_args": [ null ], "taps": [ { "name": "OccurrenceOrderChunkIdsPlugin" } ], "interceptors": [], "_x": [ null ] }, "beforeChunkIds": { "_args": [ null ], "taps": [ { "name": "NamedChunksPlugin" } ], "interceptors": [], "_x": [ null ] }, "optimizeChunkIds": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "afterOptimizeChunkIds": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "recordModules": { "_args": [ null, null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "recordChunks": { "_args": [ null, null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "beforeHash": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "contentHash": { "_args": [ "chunk" ], "taps": [ { "name": "JavascriptModulesPlugin" } ], "interceptors": [], "_x": [ null ] }, "afterHash": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "recordHash": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "record": { "_args": [ "compilation", null ], "taps": [], "interceptors": [], "_x": [] }, "beforeModuleAssets": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "shouldGenerateChunkAssets": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "beforeChunkAssets": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "additionalChunkAssets": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "additionalAssets": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "optimizeChunkAssets": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "afterOptimizeChunkAssets": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "optimizeAssets": { "_args": [ "assets" ], "taps": [], "interceptors": [], "_x": [] }, "afterOptimizeAssets": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "needAdditionalSeal": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "afterSeal": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "chunkHash": { "_args": [ null, "chunkHash" ], "taps": [], "interceptors": [], "_x": [] }, "moduleAsset": { "_args": [ null, "filename" ], "taps": [], "interceptors": [] }, "chunkAsset": { "_args": [ null, null ], "taps": [], "interceptors": [], "_x": [] }, "assetPath": { "_args": [ null, "data" ], "taps": [], "interceptors": [] }, "needAdditionalPass": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "childCompiler": { "_args": [ "childCompiler", "compilerName", "compilerIndex" ], "taps": [ { "name": "CachePlugin" } ], "interceptors": [] }, "normalModuleLoader": { "_args": [ "loaderContext", null ], "taps": [ { "name": "LoaderTargetPlugin" }, { "name": "LoaderPlugin" } ], "interceptors": [], "_x": [ null, null ] }, "optimizeExtractedChunksBasic": { "_args": [ null ], "taps": [ {}, {}, {} ], "interceptors": [] }, "optimizeExtractedChunks": { "_args": [ null ], "taps": [], "interceptors": [] }, "optimizeExtractedChunksAdvanced": { "_args": [ null ], "taps": [ {} ], "interceptors": [] }, "afterOptimizeExtractedChunks": { "_args": [ null ], "taps": [], "interceptors": [] } }, "compiler": { "_pluginCompat": { "_args": [ null ], "taps": [ { "name": "Compiler" }, {}, {} ], "interceptors": [] }, "hooks": { "shouldEmit": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "done": { "_args": [ "stats" ], "taps": [ { "name": "helloword" } ], "interceptors": [], "_x": [ null ] }, "additionalPass": { "_args": [], "taps": [], "interceptors": [] }, "beforeRun": { "_args": [ "compiler" ], "taps": [ { "name": "NodeEnvironmentPlugin" } ], "interceptors": [], "_x": [ null ] }, "run": { "_args": [ null ], "taps": [ { "type": "async" } ], "interceptors": [], "_x": [ null ] }, "emit": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "afterEmit": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "thisCompilation": { "_args": [ null, "params" ], "taps": [ { "name": "JsonpTemplatePlugin" }, { "name": "FetchCompileWasmTemplatePlugin" }, {}, {} ], "interceptors": [], "_x": [ null, null, null, null ] }, "compilation": { "_args": [ null, null ], "taps": [ { "name": "FunctionModulePlugin" }, { "name": "NodeSourcePlugin" }, {}, { "name": "EvalDevToolModulePlugin" }, {}, { "name": "JsonModulesPlugin" }, {}, { "name": "SingleEntryPlugin" }, { "name": "CompatibilityPlugin" }, { "name": "HarmonyModulesPlugin" }, { "name": "AMDPlugin" }, { "name": "CommonJsPlugin" }, {}, {}, { "name": "NodeStuffPlugin" }, { "name": "RequireJsStuffPlugin" }, { "name": "APIPlugin" }, { "name": "ConstPlugin" }, { "name": "UseStrictPlugin" }, { "name": "RequireIncludePlugin" }, { "name": "RequireEnsurePlugin" }, { "name": "RequireContextPlugin" }, { "name": "ImportPlugin" }, { "name": "SystemPlugin" }, {}, {}, {}, {}, {}, {}, {}, {}, { "name": "DefinePlugin" }, { "name": "TemplatedPathPlugin" }, {}, {} ], "interceptors": [], "_x": [ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null ] }, "normalModuleFactory": { "_args": [ "normalModuleFactory" ], "taps": [], "interceptors": [], "_x": [] }, "contextModuleFactory": { "_args": [ "contextModulefactory" ], "taps": [], "interceptors": [], "_x": [] }, "beforeCompile": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "compile": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "make": { "_args": [ null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "afterCompile": { "_args": [ null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "watchRun": { "_args": [ null ], "taps": [ {} ], "interceptors": [] }, "failed": { "_args": [ null ], "taps": [], "interceptors": [] }, "invalid": { "_args": [ null, "changeTime" ], "taps": [], "interceptors": [] }, "watchClose": { "_args": [], "taps": [], "interceptors": [] }, "environment": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "afterEnvironment": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "afterPlugins": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "afterResolvers": { "_args": [ null ], "taps": [ {}, {} ], "interceptors": [], "_x": [ null, null ] }, "entryOption": { "_args": [ "context", null ], "taps": [ { "name": "EntryOptionPlugin" } ], "interceptors": [], "_x": [ null ] } }, "outputPath": "D:\\JD-learn\\webpac-plugin-test\\dist", "outputFileSystem": {}, "inputFileSystem": { "fileSystem": {}, "_statStorage": { "duration": 60000, "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 8, "interval": { "_called": false, "_idleTimeout": 530, "_idlePrev": { "_idlePrev": { "_idlePrev": { "_idlePrev": { "_idleStart": 652 }, "_idleStart": 640 } }, "_timer": {} } }, "nextTick": null }, "_readdirStorage": { "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 0, "passive": true }, "_readFileStorage": { "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 7 }, "_readJsonStorage": { "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 6 }, "_readlinkStorage": { "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 10 } }, "records": { "modules": { "byIdentifier": {}, "usedIds": {} }, "chunks": { "byName": {}, "bySource": {}, "usedIds": [] } }, "removedFiles": {}, "fileTimestamps": {}, "contextTimestamps": {}, "resolverFactory": { "_pluginCompat": { "_args": [ null ], "taps": [ { "name": "ResolverFactory" }, {}, {} ], "interceptors": [] }, "hooks": { "resolveOptions": { "_map": {}, "_interceptors": [] }, "resolver": { "_map": {}, "_interceptors": [] } }, "cache1": {}, "cache2": {} }, "resolvers": { "normal": {}, "loader": {}, "context": {} }, "options": { "entry": "D:\\JD-learn\\webpac-plugin-test\\index.js", "output": { "filename": "main.js", "chunkFilename": "[id].main.js", "webassemblyModuleFilename": "[modulehash].module.wasm", "library": "", "hotUpdateFunction": "webpackHotUpdate", "jsonpFunction": "webpackJsonp", "chunkCallbackName": "webpackChunk", "globalObject": "window", "libraryTarget": "var", "sourceMapFilename": "[file].map[query]", "hotUpdateChunkFilename": "[id].[hash].hot-update.js", "hotUpdateMainFilename": "[hash].hot-update.json", "chunkLoadTimeout": 120000, "hashFunction": "md4", "hashDigest": "hex", "hashDigestLength": 20 }, "module": { "rules": [ { "test": {}, "use": "babel-loader" } ], "unknownContextRequest": ".", "wrappedContextRegExp": {}, "defaultRules": [ { "type": "javascript/auto", "resolve": {} }, { "test": {}, "type": "javascript/esm", "resolve": { "mainFields": [ "browser", "main" ] } }, { "test": {}, "type": "json" }, { "test": {}, "type": "webassembly/experimental" } ] }, "plugins": [ {} ], "mode": "development", "context": "D:\\JD-learn\\webpac-plugin-test", "devtool": "eval", "target": "web", "node": { "__filename": "mock" }, "optimization": { "splitChunks": { "minSize": 10000, "minChunks": 1, "maxAsyncRequests": null, "automaticNameDelimiter": "~", "cacheGroups": { "default": { "minChunks": 2, "priority": -20 }, "vendors": { "automaticNamePrefix": "vendors", "test": {}, "priority": -10 } } }, "minimizer": [ {} ] }, "resolve": { "modules": [ "node_modules" ], "extensions": [ ".wasm", ".mjs", ".js", ".json" ], "mainFiles": [ "index" ], "aliasFields": [ null ], "mainFields": [ null, null, null ] }, "resolveLoader": { "mainFields": [ "loader", null ], "extensions": [ null, null ], "mainFiles": [ null ] } }, "requestShortener": { "currentDirectoryRegExp": {}, "parentDirectoryRegExp": {}, "buildinsRegExp": {}, "cache": {} }, "watchFileSystem": { "watcherOptions": {}, "watcher": { "_events": {}, "watcherOptions": {}, "fileWatchers": [], "dirWatchers": [], "mtimes": {}, "aggregatedChanges": [], "aggregatedRemovals": [] } }, "_lastCompilationFileDependencies": {}, "_lastCompilationContextDependencies": {} }, "mainTemplate": { "_pluginCompat": { "_args": [ null ], "taps": [ {}, {} ], "interceptors": [] }, "hooks": { "renderManifest": { "_args": [ "result", null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "modules": { "_args": [ null, null, "hash", "moduleTemplate", "dependencyTemplates" ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "moduleObj": { "_args": [ "source", null, null, "moduleIdExpression" ], "taps": [ { "name": "MainTemplate" } ], "interceptors": [], "_x": [ null ] }, "requireEnsure": { "_args": [ null, null, null, "chunkIdExpression" ], "taps": [ { "name": "JsonpMainTemplatePlugin load" }, { "name": "WasmMainTemplatePlugin" }, { "name": "JsonpMainTemplatePlugin preload" } ], "interceptors": [] }, "bootstrap": { "_args": [ null, null, null, null, null ], "taps": [ { "name": "JsonpMainTemplatePlugin" } ], "interceptors": [], "_x": [ null ] }, "localVars": { "_args": [ null, null, null ], "taps": [ {}, {}, {} ], "interceptors": [], "_x": [ null, null, null ] }, "require": { "_args": [ null, null, null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "requireExtensions": { "_args": [ null, null, null ], "taps": [ {}, {}, {} ], "interceptors": [], "_x": [ null, null, null ] }, "beforeStartup": { "_args": [ null, null, null ], "taps": [ {}, {} ], "interceptors": [], "_x": [ null, null ] }, "startup": { "_args": [ null, null, null ], "taps": [ {}, {} ], "interceptors": [], "_x": [ null, null ] }, "render": { "_args": [ null, null, null, null, null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "renderWithEntry": { "_args": [ null, null, null ], "taps": [], "interceptors": [], "_x": [] }, "moduleRequire": { "_args": [ null, null, null, null ], "taps": [], "interceptors": [], "_x": [] }, "addModule": { "_args": [ null, null, null, null, "moduleExpression" ], "taps": [], "interceptors": [] }, "currentHash": { "_args": [ null, "requestedLength" ], "taps": [], "interceptors": [] }, "assetPath": { "_args": [ "path", null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "hash": { "_args": [ null ], "taps": [ {}, {} ], "interceptors": [], "_x": [ null, null ] }, "hashForChunk": { "_args": [ null, null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "globalHashPaths": { "_args": [ "paths" ], "taps": [], "interceptors": [], "_x": [] }, "globalHash": { "_args": [ null, null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "hotBootstrap": { "_args": [ null, null, null ], "taps": [ {} ], "interceptors": [] }, "jsonpScript": { "_args": [ null, null, null ], "taps": [ {} ], "interceptors": [] }, "linkPreload": { "_args": [ null, null, null ], "taps": [ {} ], "interceptors": [] }, "linkPrefetch": { "_args": [ null, null, null ], "taps": [ {} ], "interceptors": [] } }, "requireFn": "__webpack_require__" }, "chunkTemplate": { "_pluginCompat": { "_args": [ null ], "taps": [ {}, {} ], "interceptors": [] }, "hooks": { "renderManifest": { "_args": [ null, null ], "taps": [ {}, {} ], "interceptors": [] }, "modules": { "_args": [ null, null, null, null ], "taps": [], "interceptors": [] }, "render": { "_args": [ null, null, null, null ], "taps": [ { "name": "JsonpChunkTemplatePlugin" } ], "interceptors": [] }, "renderWithEntry": { "_args": [ null, null ], "taps": [], "interceptors": [] }, "hash": { "_args": [ null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "hashForChunk": { "_args": [ null, null ], "taps": [ {} ], "interceptors": [] } } }, "hotUpdateChunkTemplate": { "_pluginCompat": { "_args": [ null ], "taps": [ {}, {} ], "interceptors": [] }, "hooks": { "modules": { "_args": [ null, null, "removedModules", null, null ], "taps": [], "interceptors": [] }, "render": { "_args": [ null, null, null, null, "id", null, null ], "taps": [ { "name": "JsonpHotUpdateChunkTemplatePlugin" } ], "interceptors": [] }, "hash": { "_args": [ null ], "taps": [ {} ], "interceptors": [] } } }, "runtimeTemplate": {}, "moduleTemplates": { "javascript": { "_pluginCompat": { "_args": [ null ], "taps": [ {}, {} ], "interceptors": [] }, "type": "javascript", "hooks": { "content": { "_args": [ null, null, null, null ], "taps": [], "interceptors": [], "_x": [] }, "module": { "_args": [ null, null, null, null ], "taps": [ { "name": "EvalDevToolModuleTemplatePlugin" } ], "interceptors": [], "_x": [ null ] }, "render": { "_args": [ null, null, null, null ], "taps": [ { "name": "FunctionModuleTemplatePlugin" } ], "interceptors": [], "_x": [ null ] }, "package": { "_args": [ null, null, null, null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "hash": { "_args": [ null ], "taps": [ {}, {} ], "interceptors": [], "_x": [ null, null ] } } }, "webassembly": { "_pluginCompat": { "_args": [ null ], "taps": [ {}, {} ], "interceptors": [] }, "type": "webassembly", "hooks": { "content": { "_args": [ null, null, null, null ], "taps": [], "interceptors": [] }, "module": { "_args": [ null, null, null, null ], "taps": [], "interceptors": [] }, "render": { "_args": [ null, null, null, null ], "taps": [], "interceptors": [] }, "package": { "_args": [ null, null, null, null ], "taps": [], "interceptors": [] }, "hash": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] } } } }, "semaphore": { "waiters": [] }, "entries": [ { "dependencies": [], "blocks": [], "variables": [], "debugId": 1000, "hash": "2334699a2ccc3f956e425bd989a94147", "renderedHash": "2334699a2ccc3f956e42", "factoryMeta": {}, "warnings": [], "errors": [], "buildMeta": {}, "buildInfo": { "fileDependencies": {}, "contextDependencies": {} }, "reasons": [ { "dependency": { "loc": {} } } ], "_chunks": {}, "id": "./index.js", "optimizationBailout": [], "_source": { "_value": "console.log(123);", "_name": "D:\\JD-learn\\webpac-plugin-test\\node_modules\\babel-loader\\lib\\index.js!D:\\JD-learn\\webpac-plugin-test\\index.js" }, "parser": { "_pluginCompat": { "_args": [ null ], "taps": [ { "name": "Parser" }, {}, {} ], "interceptors": [] }, "hooks": { "evaluateTypeof": { "_map": {}, "_interceptors": [] }, "evaluate": { "_map": {}, "_interceptors": [] }, "evaluateIdentifier": { "_map": {}, "_interceptors": [] }, "evaluateDefinedIdentifier": { "_map": {}, "_interceptors": [] }, "evaluateCallExpressionMember": { "_map": {}, "_interceptors": [] }, "statement": { "_args": [ "statement" ], "taps": [], "interceptors": [], "_x": [] }, "statementIf": { "_args": [ null ], "taps": [ {} ], "interceptors": [] }, "label": { "_map": {}, "_interceptors": [] }, "import": { "_args": [ null, null ], "taps": [ { "name": "HarmonyImportDependencyParserPlugin" } ], "interceptors": [] }, "importSpecifier": { "_args": [ null, null, "exportName", "identifierName" ], "taps": [ {} ], "interceptors": [] }, "export": { "_args": [ null ], "taps": [ { "name": "HarmonyExportDependencyParserPlugin" } ], "interceptors": [] }, "exportImport": { "_args": [ null, null ], "taps": [ {} ], "interceptors": [] }, "exportDeclaration": { "_args": [ null, "declaration" ], "taps": [ {} ], "interceptors": [] }, "exportExpression": { "_args": [ null, null ], "taps": [ {} ], "interceptors": [] }, "exportSpecifier": { "_args": [ null, null, null, null ], "taps": [ {} ], "interceptors": [] }, "exportImportSpecifier": { "_args": [ null, null, null, null, null ], "taps": [ {} ], "interceptors": [] }, "varDeclaration": { "_map": {}, "_interceptors": [] }, "varDeclarationLet": { "_map": {}, "_interceptors": [] }, "varDeclarationConst": { "_map": {}, "_interceptors": [] }, "varDeclarationVar": { "_map": {}, "_interceptors": [] }, "canRename": { "_map": {}, "_interceptors": [] }, "rename": { "_map": {}, "_interceptors": [] }, "assigned": { "_map": {}, "_interceptors": [] }, "assign": { "_map": {}, "_interceptors": [] }, "typeof": { "_map": {}, "_interceptors": [] }, "importCall": { "_args": [ "expression" ], "taps": [ { "name": "ImportParserPlugin" } ], "interceptors": [] }, "call": { "_map": {}, "_interceptors": [] }, "callAnyMember": { "_map": {}, "_interceptors": [] }, "new": { "_map": {}, "_interceptors": [] }, "expression": { "_map": {}, "_interceptors": [] }, "expressionAnyMember": { "_map": {}, "_interceptors": [] }, "expressionConditionalOperator": { "_args": [ null ], "taps": [ {} ], "interceptors": [] }, "expressionLogicalOperator": { "_args": [ null ], "taps": [ {} ], "interceptors": [] }, "program": { "_args": [ "ast", "comments" ], "taps": [ { "name": "HarmonyDetectionParserPlugin" }, {} ], "interceptors": [], "_x": [ null, null ] }, "hotAcceptCallback": { "_args": [ null, "requests" ], "taps": [ {} ], "interceptors": [] }, "hotAcceptWithoutCallback": { "_args": [ null, null ], "taps": [ {} ], "interceptors": [] } }, "options": {}, "sourceType": "auto" }, "generator": {}, "loaders": [ { "loader": "D:\\JD-learn\\webpac-plugin-test\\node_modules\\babel-loader\\lib\\index.js" } ], "_buildHash": "09901ef69edc7425c9213c0734790bc7", "buildTimestamp": 1546611808813, "_cachedSources": {} } ], "_preparedEntrypoints": [ {} ], "entrypoints": {}, "chunks": [ { "ids": [ null ], "_modules": { "_cache": {} }, "_groups": {}, "files": [ null ], "hash": "aee5b5a7d22a74f417af402bcc7c46ea", "contentHash": { "javascript": "c7fe528133a7ad8651e3" }, "renderedHash": "aee5b5a7d22a74f417af" } ], "chunkGroups": [ { "groupDebugId": 5000, "options": {}, "_children": {}, "_parents": {}, "_blocks": {}, "chunks": [ null ], "origins": [ {} ], "_moduleIndicies": {}, "_moduleIndicies2": {} } ], "namedChunkGroups": {}, "namedChunks": {}, "modules": [ null ], "_modules": {}, "cache": { "chunkmain": { "source": { "_source": { "children": [ "/******/ (function(modules) { // webpackBootstrap\n", { "_source": { "_value": " \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./index.js\");\n", "_name": "webpack/bootstrap" }, "_prefix": "/******/" }, "/******/ })\n", "/************************************************************************/\n", "/******/ (", "{\n", "\n/***/ \"./index.js\":\n", "/*!******************!*\\\n", " !*** ./index.js ***!\n", " \\******************/\n", "/*! no static exports found */\n", "/***/ (function(module, exports) {\n\n", { "_value": "eval(\"console.log(123);\\n\\n//# sourceURL=webpack:///./index.js?\");" }, "\n\n/***/ })", "\n\n/******/ }", ")", ";" ] }, "_cachedSource": "/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = \"./index.js\");\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ \"./index.js\":\n/*!******************!*\\\n !*** ./index.js ***!\n \\******************/\n/*! no static exports found */\n/***/ (function(module, exports) {\n\neval(\"console.log(123);\\n\\n//# sourceURL=webpack:///./index.js?\");\n\n/***/ })\n\n/******/ });", "_cachedMaps": {}, "existsAt": "D:\\JD-learn\\webpac-plugin-test\\dist\\main.js" } } }, "additionalChunkAssets": [], "assets": {}, "errors": [], "warnings": [], "children": [], "dependencyFactories": {}, "dependencyTemplates": {}, "childrenCounters": {}, "compilationDependencies": {}, "_buildingModules": {}, "_rebuildingModules": {}, "fullHash": "6cd8ab62f0c410c135ec67b04f0dc850", "hash": "6cd8ab62f0c410c135ec", "missingDependencies": {} }, "startTime": 1546611808773, "endTime": 1546611809136 }
近 3000 行,真是让人望而却步呀
不过我们经过格式化后,可以发现这个时候的 stats 对象其实是一个 compilation 对象加上 编译开始和结束的时间戳:
我们继续发现,我们可以发现在 这个 compilation 里面包含了 compiler 对象,好的,那先看看 compiler 对象,如下:
"compiler": { "_pluginCompat": { "_args": [ null ], "taps": [ { "name": "Compiler" }, {}, {} ], "interceptors": [] }, "hooks": { "shouldEmit": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "done": { "_args": [ "stats" ], "taps": [ { "name": "helloword" } ], "interceptors": [], "_x": [ null ] }, "additionalPass": { "_args": [], "taps": [], "interceptors": [] }, "beforeRun": { "_args": [ "compiler" ], "taps": [ { "name": "NodeEnvironmentPlugin" } ], "interceptors": [], "_x": [ null ] }, "run": { "_args": [ null ], "taps": [ { "type": "async" } ], "interceptors": [], "_x": [ null ] }, "emit": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "afterEmit": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "thisCompilation": { "_args": [ null, "params" ], "taps": [ { "name": "JsonpTemplatePlugin" }, { "name": "FetchCompileWasmTemplatePlugin" }, {}, {} ], "interceptors": [], "_x": [ null, null, null, null ] }, "compilation": { "_args": [ null, null ], "taps": [ { "name": "FunctionModulePlugin" }, { "name": "NodeSourcePlugin" }, {}, { "name": "EvalDevToolModulePlugin" }, {}, { "name": "JsonModulesPlugin" }, {}, { "name": "SingleEntryPlugin" }, { "name": "CompatibilityPlugin" }, { "name": "HarmonyModulesPlugin" }, { "name": "AMDPlugin" }, { "name": "CommonJsPlugin" }, {}, {}, { "name": "NodeStuffPlugin" }, { "name": "RequireJsStuffPlugin" }, { "name": "APIPlugin" }, { "name": "ConstPlugin" }, { "name": "UseStrictPlugin" }, { "name": "RequireIncludePlugin" }, { "name": "RequireEnsurePlugin" }, { "name": "RequireContextPlugin" }, { "name": "ImportPlugin" }, { "name": "SystemPlugin" }, {}, {}, {}, {}, {}, {}, {}, {}, { "name": "DefinePlugin" }, { "name": "TemplatedPathPlugin" }, {}, {} ], "interceptors": [], "_x": [ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null ] }, "normalModuleFactory": { "_args": [ "normalModuleFactory" ], "taps": [], "interceptors": [], "_x": [] }, "contextModuleFactory": { "_args": [ "contextModulefactory" ], "taps": [], "interceptors": [], "_x": [] }, "beforeCompile": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "compile": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "make": { "_args": [ null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "afterCompile": { "_args": [ null ], "taps": [ {} ], "interceptors": [], "_x": [ null ] }, "watchRun": { "_args": [ null ], "taps": [ {} ], "interceptors": [] }, "failed": { "_args": [ null ], "taps": [], "interceptors": [] }, "invalid": { "_args": [ null, "changeTime" ], "taps": [], "interceptors": [] }, "watchClose": { "_args": [], "taps": [], "interceptors": [] }, "environment": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "afterEnvironment": { "_args": [], "taps": [], "interceptors": [], "_x": [] }, "afterPlugins": { "_args": [ null ], "taps": [], "interceptors": [], "_x": [] }, "afterResolvers": { "_args": [ null ], "taps": [ {}, {} ], "interceptors": [], "_x": [ null, null ] }, "entryOption": { "_args": [ "context", null ], "taps": [ { "name": "EntryOptionPlugin" } ], "interceptors": [], "_x": [ null ] } }, "outputPath": "/Users/huruji/Documents/webpac-plugin-test/dist", "outputFileSystem": {}, "inputFileSystem": { "fileSystem": {}, "_statStorage": { "duration": 60000, "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 17, "interval": { "_called": true, "_idleTimeout": 530, "_idlePrev": { "_idlePrev": { "_idlePrev": { "_idlePrev": { "_idleStart": 14428, "_destroyed": false } } }, "_timer": {} } }, "nextTick": null }, "_readdirStorage": { "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 0 }, "_readFileStorage": { "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 14 }, "_readJsonStorage": { "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 12 }, "_readlinkStorage": { "running": {}, "data": {}, "levels": [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ], "count": 20 } }, "records": { "modules": { "byIdentifier": {}, "usedIds": {} }, "chunks": { "byName": {}, "bySource": {}, "usedIds": [] } }, "removedFiles": {}, "fileTimestamps": {}, "contextTimestamps": {}, "resolverFactory": { "_pluginCompat": { "_args": [ null ], "taps": [ { "name": "ResolverFactory" }, {}, {} ], "interceptors": [] }, "hooks": { "resolveOptions": { "_map": {}, "_interceptors": [] }, "resolver": { "_map": {}, "_interceptors": [] } }, "cache1": {}, "cache2": {} }, "resolvers": { "normal": {}, "loader": {}, "context": {} }, "options": { "entry": "/Users/huruji/Documents/webpac-plugin-test/index.js", "output": { "filename": "main.js", "chunkFilename": "[id].main.js", "webassemblyModuleFilename": "[modulehash].module.wasm", "library": "", "hotUpdateFunction": "webpackHotUpdate", "jsonpFunction": "webpackJsonp", "chunkCallbackName": "webpackChunk", "globalObject": "window", "libraryTarget": "var", "sourceMapFilename": "[file].map[query]", "hotUpdateChunkFilename": "[id].[hash].hot-update.js", "hotUpdateMainFilename": "[hash].hot-update.json", "chunkLoadTimeout": 120000, "hashFunction": "md4", "hashDigest": "hex" }, "module": { "rules": [ { "test": {}, "use": "babel-loader" } ], "unknownContextRequest": ".", "wrappedContextRegExp": {}, "defaultRules": [ { "type": "javascript/auto", "resolve": {} }, { "test": {}, "type": "javascript/esm", "resolve": { "mainFields": [ "browser", "main" ] } }, { "test": {}, "type": "json" }, { "test": {}, "type": "webassembly/experimental" } ] }, "plugins": [ {} ], "mode": "development", "context": "/Users/huruji/Documents/webpac-plugin-test", "devtool": "eval", "target": "web", "node": { "__filename": "mock" }, "optimization": { "splitChunks": { "minSize": 10000, "minChunks": 1, "maxAsyncRequests": null, "automaticNameDelimiter": "~", "cacheGroups": { "default": { "minChunks": 2, "priority": -20 }, "vendors": { "automaticNamePrefix": "vendors", "test": {}, "priority": -10 } } }, "minimizer": [ {} ] }, "resolve": { "modules": [ "node_modules" ], "extensions": [ ".wasm", ".mjs", ".js", ".json" ], "mainFiles": [ "index" ], "aliasFields": [ null ], "mainFields": [ null, null, null ] }, "resolveLoader": { "mainFields": [ "loader", null ], "extensions": [ null, null ], "mainFiles": [ null ] } }, "requestShortener": { "currentDirectoryRegExp": {}, "parentDirectoryRegExp": {}, "buildinsRegExp": {}, "cache": {} }, "watchFileSystem": { "watcherOptions": {}, "watcher": { "_events": {}, "watcherOptions": {}, "fileWatchers": [], "dirWatchers": [], "mtimes": {}, "aggregatedChanges": [], "aggregatedRemovals": [] } }, "_lastCompilationFileDependencies": {}, "_lastCompilationContextDependencies": {} }
粗略看一下,可以发现 这里主要是 webpack 的配置,输入、输出、监听文件系统的描述,输出地址,compiler 对象的 hooks 等。
我们再看看 compilation 对象,这个对象主要有 assert 、 modules、 chunks、entries的信息。
最近想要了解一下 webpack 的 plugin 怎么写,于是各种文章就会告诉你想要写一个 plugin 那么你首先需要了解一下 Compilation、compiler 对象,然后 plugin 插件其实是一个含有 apply 方法的 class,而 apply 方法的参数就是 compiler 对象,compiler 对象里有各种钩子,这些钩子分别会在 webpack 的运行过程中触发,而实现这些钩子的核心是 tapable ,这个 tapable 还算好理解,可以把它看做是一个更高级的 发布-订阅。然后我想实现以下 done 这个 hook 的功能,你就会发现这个 hook 的参数是 stats 对象,所以问题来了,我想要去实现 一个 plugin,那么是真的要搞清这些对象了。
我先弄了一个最简单的 webpack 配置:
myplugin 是实现在 compiler 的 done hook中,内容如下:
然后控制台会告诉你 stats 对象内有循环引用,所以
JSON.stringify
会报错,那么使用 StackOVerflow 的方法解决:好的,这下可以正常输出了,我们打开我们的文件,文件内容如下:
近 3000 行,真是让人望而却步呀
不过我们经过格式化后,可以发现这个时候的 stats 对象其实是一个 compilation 对象加上 编译开始和结束的时间戳:
我们继续发现,我们可以发现在 这个 compilation 里面包含了 compiler 对象,好的,那先看看 compiler 对象,如下:
粗略看一下,可以发现 这里主要是 webpack 的配置,输入、输出、监听文件系统的描述,输出地址,compiler 对象的 hooks 等。
我们再看看 compilation 对象,这个对象主要有 assert 、 modules、 chunks、entries的信息。