webpack 基础
了解 webpack 的基本配置和一些概念
零配置可以使用的原因
关于 Vue 相关的问题可以阅读一下文章!
1. entry 入口
作用:用于配置 webpack 进行打包编译时查找的第一个文件或多个文件,从而进行构建依赖图
例子:
单入口:
module.exports = {
entry: './src/main.js', // 字符串写入文件地址
entry:{
main: './src/main.js'
}, // 以对象形式
};
多入口:
module.exports = {
entry: ['./src/file_1.js', './src/file_2.js'] // 以数组的形式,虽然就两个入口,但是编译完成后输出的入口文件中 包含两个文件的代码
entry: { // 以对象形式, 编译完成后,会生成对应数量的入口文件
app: './src/app.js',
adminApp: './src/adminApp.js',
},
};
2. output 输出
作用:告知 webpack 如何向硬盘写入编译文件
注意: 即使可以存在多个 entry 起点,但只能指定一个 output 配置。并且 output 属性的最低要求是,将它的值设置为一个对象,然后为将输出文件的文件名配置为一个 output.filename
2.1 filename
例子:
module.exports = {
output: {
filename: 'bundle.js',
},
};
还可以使用占位符来控制输出的文件名称
module.exports = {
output: {
filename: '[id][name][hash][contexthash].js',
},
};
函数的写法
module.exports = {
output: {
filename: (pathData) => {
return pathData.chunk.name === 'main' ? '[name].js' : '[name]/[name].js';
},
},
};
2.2 path
输出到磁盘的路径,切必须是绝对路径
const path = require('path');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist/assets'),
},
};
2.3 publicPath
配置 CDN 或者 配置静态资源加载路径
const path = require('path');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist/assets'),
publicPath: 'https://cdn.example.com/assets/', // 配置 CDN 服务
publicPath: '/prefix/', // 配置请求的前缀,有时候 web 页面不一定放到服务器根目录,可能会放在子目录下
},
};
3. loader
用于转换源代码,可以将文件从不同的语言(如 TypeScript)转换为 JavaScript 或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS 文件!
4. plugin
插件目的在于解决 loader 无法实现的其他事。
插件能够 hook 到每一个编译(compilation)中发出的关键事件中。 在编译的每个阶段中,插件都拥有对 compiler 对象的完全访问能力, 并且在合适的时机,还可以访问当前的 compilation 对象。
5. optimization
主要用于配置优化方面的配置,比如 splitChunks 用于分割代码等。 在正式环境(production)中会默认开启一部分优化功能。
6. resolve
大部分用于配置解析配置相关的,比如 alias 路径别名 extensions 扩展后缀名等
webpack 的一些基本概念
1. runtimeChunk: 运行时缓存
他会生成一个或多个 runtime.js 文件内容只包含了 加载模块、执行模块、缓存模块 等的方法和变量
- 主要内容就是自定义了一个全局变量是一个数组,然后重写了数组的
push方法 - 入口文件等chunk,内容就变成了 全局变量.push(编译后的模块代码了)
2. webpack chunks 缓存
这个主要讲的是 webpack 在打包完成后生成的入口 chunks 或者 splitChunks 的 chunks 的文件名称,通过给文件名称一个稳定的文件名,从而与 http缓存 形成长期的缓存,只要文件名不变,浏览器获取资源就可以通过http 缓存来获取,用于优化
而且 webpack 会称之位长期缓存,之所以被称为“长期缓存”,是因为这样的配置方式可以让浏览器长时间有效地缓存这些资源,即使应用中的其他部分发生了变化,这些被长期缓存的资源仍然保持不变,除非它们自身的内容发生变化。
3. 缓存编译结果
memory: 默认情况会缓存到内存中,及webpack 运行时缓存,webpack 结束后 缓存丢失 Filesystem: 持久化缓存, 把编译后的文件缓存到磁盘上,下次运行还可以获得编译的结果
4. tree shaking
通过 optimization.usedExports = true 来进行 tree shaking
尽量使用 esm 导入导出语法,更符合 webpack 在 tree shaking 时的静态分析
因为 cjs 可能存在动态导入或者是整体引用,webpack 不能确定那些有用到哪些没有用到
混合使用可能也不如 esm 的静态语法分析
5. 懒加载或按需加载
动态引入模块 生成单独的 chunk 在需要时再进行引入
语法 import(modulePath).then((resolve,reject)=>{})
6. 代码分割
按照 splitChunksPlugin 需要配置的参数来进行代码分割,对于满足条件的文件,会对此文件进行代码分割,生成多个 chunks
7. dev-server
主要用于开发阶段,提升开发效率。功能时,对修改的模块文件进行替换,而不是刷新页面 dev-server 具体运行流程可以查看这里!!!
为什么零配置也可以使用
零配置可以使用很好理解,因为 webpack 有一些默认配置。
但是在 webpack 5 中 添加了一些内置的 plugin, 通过配置项就可以实现一些 plugins 的功能, 原因就在 源码中 createCompiler 的 new WebpackOptionsApply().process(options, compiler)
在创建 compiler 时,会通过 options 来进行添加 plugins, 接下来可以看一下源码应该就懂了原因
注:这个 class 代码量有点长,可以的话到源码的位置直接用编辑器查看更方便。代码的位置在 /lib/WebpackOptionsApply.js
【class WebpackOptionsApply 源码】(点击展开)
// lib/WebpackOptionsApply.js
class WebpackOptionsApply extends OptionsApply {
constructor() {
super();
}
process(options, compiler) {
compiler.outputPath = options.output.path;
compiler.recordsInputPath = options.recordsInputPath || null;
compiler.recordsOutputPath = options.recordsOutputPath || null;
compiler.name = options.name;
if (options.externals) {
const ExternalsPlugin = require("./ExternalsPlugin");
new ExternalsPlugin(options.externalsType, options.externals).apply(
compiler
);
}
if (options.externalsPresets.node) {
const NodeTargetPlugin = require("./node/NodeTargetPlugin");
new NodeTargetPlugin().apply(compiler);
}
if (options.externalsPresets.electronMain) {
const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
new ElectronTargetPlugin("main").apply(compiler);
}
if (options.externalsPresets.electronPreload) {
const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
new ElectronTargetPlugin("preload").apply(compiler);
}
if (options.externalsPresets.electronRenderer) {
const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
new ElectronTargetPlugin("renderer").apply(compiler);
}
if (
options.externalsPresets.electron &&
!options.externalsPresets.electronMain &&
!options.externalsPresets.electronPreload &&
!options.externalsPresets.electronRenderer
) {
const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
new ElectronTargetPlugin().apply(compiler);
}
if (options.externalsPresets.nwjs) {
const ExternalsPlugin = require("./ExternalsPlugin");
new ExternalsPlugin("node-commonjs", "nw.gui").apply(compiler);
}
if (options.externalsPresets.webAsync) {
const ExternalsPlugin = require("./ExternalsPlugin");
new ExternalsPlugin(
"import",
options.experiments.css
? ({ request, dependencyType }, callback) => {
if (dependencyType === "url") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `asset ${request}`);
} else if (dependencyType === "css-import") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `css-import ${request}`);
} else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
if (/^\.css(\?|$)/.test(request))
return callback(null, `css-import ${request}`);
return callback(null, `import ${request}`);
}
callback();
}
: /^(\/\/|https?:\/\/|std:)/
).apply(compiler);
} else if (options.externalsPresets.web) {
const ExternalsPlugin = require("./ExternalsPlugin");
new ExternalsPlugin(
"module",
options.experiments.css
? ({ request, dependencyType }, callback) => {
if (dependencyType === "url") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `asset ${request}`);
} else if (dependencyType === "css-import") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `css-import ${request}`);
} else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
if (/^\.css(\?|$)/.test(request))
return callback(null, `css-import ${request}`);
return callback(null, `module ${request}`);
}
callback();
}
: /^(\/\/|https?:\/\/|std:)/
).apply(compiler);
} else if (options.externalsPresets.node) {
if (options.experiments.css) {
const ExternalsPlugin = require("./ExternalsPlugin");
new ExternalsPlugin(
"module",
({ request, dependencyType }, callback) => {
if (dependencyType === "url") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `asset ${request}`);
} else if (dependencyType === "css-import") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `css-import ${request}`);
} else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
if (/^\.css(\?|$)/.test(request))
return callback(null, `css-import ${request}`);
return callback(null, `module ${request}`);
}
callback();
}
).apply(compiler);
}
}
new ChunkPrefetchPreloadPlugin().apply(compiler);
if (typeof options.output.chunkFormat === "string") {
switch (options.output.chunkFormat) {
case "array-push": {
const ArrayPushCallbackChunkFormatPlugin = require("./javascript/ArrayPushCallbackChunkFormatPlugin");
new ArrayPushCallbackChunkFormatPlugin().apply(compiler);
break;
}
case "commonjs": {
const CommonJsChunkFormatPlugin = require("./javascript/CommonJsChunkFormatPlugin");
new CommonJsChunkFormatPlugin().apply(compiler);
break;
}
case "module": {
const ModuleChunkFormatPlugin = require("./esm/ModuleChunkFormatPlugin");
new ModuleChunkFormatPlugin().apply(compiler);
break;
}
default:
throw new Error(
"Unsupported chunk format '" + options.output.chunkFormat + "'."
);
}
}
if (options.output.enabledChunkLoadingTypes.length > 0) {
for (const type of options.output.enabledChunkLoadingTypes) {
const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin");
new EnableChunkLoadingPlugin(type).apply(compiler);
}
}
if (options.output.enabledWasmLoadingTypes.length > 0) {
for (const type of options.output.enabledWasmLoadingTypes) {
const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin");
new EnableWasmLoadingPlugin(type).apply(compiler);
}
}
if (options.output.enabledLibraryTypes.length > 0) {
for (const type of options.output.enabledLibraryTypes) {
const EnableLibraryPlugin = require("./library/EnableLibraryPlugin");
new EnableLibraryPlugin(type).apply(compiler);
}
}
if (options.output.pathinfo) {
const ModuleInfoHeaderPlugin = require("./ModuleInfoHeaderPlugin");
new ModuleInfoHeaderPlugin(options.output.pathinfo !== true).apply(
compiler
);
}
if (options.output.clean) {
const CleanPlugin = require("./CleanPlugin");
new CleanPlugin(
options.output.clean === true ? {} : options.output.clean
).apply(compiler);
}
if (options.devtool) {
if (options.devtool.includes("source-map")) {
const hidden = options.devtool.includes("hidden");
const inline = options.devtool.includes("inline");
const evalWrapped = options.devtool.includes("eval");
const cheap = options.devtool.includes("cheap");
const moduleMaps = options.devtool.includes("module");
const noSources = options.devtool.includes("nosources");
const Plugin = evalWrapped
? require("./EvalSourceMapDevToolPlugin")
: require("./SourceMapDevToolPlugin");
new Plugin({
filename: inline ? null : options.output.sourceMapFilename,
moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
fallbackModuleFilenameTemplate:
options.output.devtoolFallbackModuleFilenameTemplate,
append: hidden ? false : undefined,
module: moduleMaps ? true : cheap ? false : true,
columns: cheap ? false : true,
noSources: noSources,
namespace: options.output.devtoolNamespace
}).apply(compiler);
} else if (options.devtool.includes("eval")) {
const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
new EvalDevToolModulePlugin({
moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
namespace: options.output.devtoolNamespace
}).apply(compiler);
}
}
new JavascriptModulesPlugin().apply(compiler);
new JsonModulesPlugin().apply(compiler);
new AssetModulesPlugin().apply(compiler);
if (!options.experiments.outputModule) {
if (options.output.module) {
throw new Error(
"'output.module: true' is only allowed when 'experiments.outputModule' is enabled"
);
}
if (options.output.enabledLibraryTypes.includes("module")) {
throw new Error(
"library type \"module\" is only allowed when 'experiments.outputModule' is enabled"
);
}
if (options.externalsType === "module") {
throw new Error(
"'externalsType: \"module\"' is only allowed when 'experiments.outputModule' is enabled"
);
}
}
if (options.experiments.syncWebAssembly) {
const WebAssemblyModulesPlugin = require("./wasm-sync/WebAssemblyModulesPlugin");
new WebAssemblyModulesPlugin({
mangleImports: options.optimization.mangleWasmImports
}).apply(compiler);
}
if (options.experiments.asyncWebAssembly) {
const AsyncWebAssemblyModulesPlugin = require("./wasm-async/AsyncWebAssemblyModulesPlugin");
new AsyncWebAssemblyModulesPlugin({
mangleImports: options.optimization.mangleWasmImports
}).apply(compiler);
}
if (options.experiments.css) {
const CssModulesPlugin = require("./css/CssModulesPlugin");
new CssModulesPlugin(options.experiments.css).apply(compiler);
}
if (options.experiments.lazyCompilation) {
const LazyCompilationPlugin = require("./hmr/LazyCompilationPlugin");
const lazyOptions =
typeof options.experiments.lazyCompilation === "object"
? options.experiments.lazyCompilation
: null;
new LazyCompilationPlugin({
backend:
typeof lazyOptions.backend === "function"
? lazyOptions.backend
: require("./hmr/lazyCompilationBackend")({
...lazyOptions.backend,
client:
(lazyOptions.backend && lazyOptions.backend.client) ||
require.resolve(
`../hot/lazy-compilation-${
options.externalsPresets.node ? "node" : "web"
}.js`
)
}),
entries: !lazyOptions || lazyOptions.entries !== false,
imports: !lazyOptions || lazyOptions.imports !== false,
test: (lazyOptions && lazyOptions.test) || undefined
}).apply(compiler);
}
if (options.experiments.buildHttp) {
const HttpUriPlugin = require("./schemes/HttpUriPlugin");
const httpOptions = options.experiments.buildHttp;
new HttpUriPlugin(httpOptions).apply(compiler);
}
new EntryOptionPlugin().apply(compiler);
compiler.hooks.entryOption.call(options.context, options.entry);
new RuntimePlugin().apply(compiler);
new InferAsyncModulesPlugin().apply(compiler);
new DataUriPlugin().apply(compiler);
new FileUriPlugin().apply(compiler);
new CompatibilityPlugin().apply(compiler);
new HarmonyModulesPlugin({
topLevelAwait: options.experiments.topLevelAwait
}).apply(compiler);
if (options.amd !== false) {
const AMDPlugin = require("./dependencies/AMDPlugin");
const RequireJsStuffPlugin = require("./RequireJsStuffPlugin");
new AMDPlugin(options.amd || {}).apply(compiler);
new RequireJsStuffPlugin().apply(compiler);
}
new CommonJsPlugin().apply(compiler);
new LoaderPlugin({}).apply(compiler);
if (options.node !== false) {
const NodeStuffPlugin = require("./NodeStuffPlugin");
new NodeStuffPlugin(options.node).apply(compiler);
}
new APIPlugin().apply(compiler);
new ExportsInfoApiPlugin().apply(compiler);
new WebpackIsIncludedPlugin().apply(compiler);
new ConstPlugin().apply(compiler);
new UseStrictPlugin().apply(compiler);
new RequireIncludePlugin().apply(compiler);
new RequireEnsurePlugin().apply(compiler);
new RequireContextPlugin().apply(compiler);
new ImportPlugin().apply(compiler);
new ImportMetaContextPlugin().apply(compiler);
new SystemPlugin().apply(compiler);
new ImportMetaPlugin().apply(compiler);
new URLPlugin().apply(compiler);
new WorkerPlugin(
options.output.workerChunkLoading,
options.output.workerWasmLoading,
options.output.module,
options.output.workerPublicPath
).apply(compiler);
new DefaultStatsFactoryPlugin().apply(compiler);
new DefaultStatsPresetPlugin().apply(compiler);
new DefaultStatsPrinterPlugin().apply(compiler);
new JavascriptMetaInfoPlugin().apply(compiler);
if (typeof options.mode !== "string") {
const WarnNoModeSetPlugin = require("./WarnNoModeSetPlugin");
new WarnNoModeSetPlugin().apply(compiler);
}
const EnsureChunkConditionsPlugin = require("./optimize/EnsureChunkConditionsPlugin");
new EnsureChunkConditionsPlugin().apply(compiler);
if (options.optimization.removeAvailableModules) {
const RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin");
new RemoveParentModulesPlugin().apply(compiler);
}
if (options.optimization.removeEmptyChunks) {
const RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin");
new RemoveEmptyChunksPlugin().apply(compiler);
}
if (options.optimization.mergeDuplicateChunks) {
const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");
new MergeDuplicateChunksPlugin().apply(compiler);
}
if (options.optimization.flagIncludedChunks) {
const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");
new FlagIncludedChunksPlugin().apply(compiler);
}
if (options.optimization.sideEffects) {
const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin");
new SideEffectsFlagPlugin(
options.optimization.sideEffects === true
).apply(compiler);
}
if (options.optimization.providedExports) {
const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");
new FlagDependencyExportsPlugin().apply(compiler);
}
if (options.optimization.usedExports) {
const FlagDependencyUsagePlugin = require("./FlagDependencyUsagePlugin");
new FlagDependencyUsagePlugin(
options.optimization.usedExports === "global"
).apply(compiler);
}
if (options.optimization.innerGraph) {
const InnerGraphPlugin = require("./optimize/InnerGraphPlugin");
new InnerGraphPlugin().apply(compiler);
}
if (options.optimization.mangleExports) {
const MangleExportsPlugin = require("./optimize/MangleExportsPlugin");
new MangleExportsPlugin(
options.optimization.mangleExports !== "size"
).apply(compiler);
}
if (options.optimization.concatenateModules) {
const ModuleConcatenationPlugin = require("./optimize/ModuleConcatenationPlugin");
new ModuleConcatenationPlugin().apply(compiler);
}
if (options.optimization.splitChunks) {
const SplitChunksPlugin = require("./optimize/SplitChunksPlugin");
new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler);
}
if (options.optimization.runtimeChunk) {
const RuntimeChunkPlugin = require("./optimize/RuntimeChunkPlugin");
new RuntimeChunkPlugin(options.optimization.runtimeChunk).apply(compiler);
}
if (!options.optimization.emitOnErrors) {
const NoEmitOnErrorsPlugin = require("./NoEmitOnErrorsPlugin");
new NoEmitOnErrorsPlugin().apply(compiler);
}
if (options.optimization.realContentHash) {
const RealContentHashPlugin = require("./optimize/RealContentHashPlugin");
new RealContentHashPlugin({
hashFunction: options.output.hashFunction,
hashDigest: options.output.hashDigest
}).apply(compiler);
}
if (options.optimization.checkWasmTypes) {
const WasmFinalizeExportsPlugin = require("./wasm-sync/WasmFinalizeExportsPlugin");
new WasmFinalizeExportsPlugin().apply(compiler);
}
const moduleIds = options.optimization.moduleIds;
if (moduleIds) {
switch (moduleIds) {
case "natural": {
const NaturalModuleIdsPlugin = require("./ids/NaturalModuleIdsPlugin");
new NaturalModuleIdsPlugin().apply(compiler);
break;
}
case "named": {
const NamedModuleIdsPlugin = require("./ids/NamedModuleIdsPlugin");
new NamedModuleIdsPlugin().apply(compiler);
break;
}
case "hashed": {
const WarnDeprecatedOptionPlugin = require("./WarnDeprecatedOptionPlugin");
const HashedModuleIdsPlugin = require("./ids/HashedModuleIdsPlugin");
new WarnDeprecatedOptionPlugin(
"optimization.moduleIds",
"hashed",
"deterministic"
).apply(compiler);
new HashedModuleIdsPlugin({
hashFunction: options.output.hashFunction
}).apply(compiler);
break;
}
case "deterministic": {
const DeterministicModuleIdsPlugin = require("./ids/DeterministicModuleIdsPlugin");
new DeterministicModuleIdsPlugin().apply(compiler);
break;
}
case "size": {
const OccurrenceModuleIdsPlugin = require("./ids/OccurrenceModuleIdsPlugin");
new OccurrenceModuleIdsPlugin({
prioritiseInitial: true
}).apply(compiler);
break;
}
default:
throw new Error(
`webpack bug: moduleIds: ${moduleIds} is not implemented`
);
}
}
const chunkIds = options.optimization.chunkIds;
if (chunkIds) {
switch (chunkIds) {
case "natural": {
const NaturalChunkIdsPlugin = require("./ids/NaturalChunkIdsPlugin");
new NaturalChunkIdsPlugin().apply(compiler);
break;
}
case "named": {
const NamedChunkIdsPlugin = require("./ids/NamedChunkIdsPlugin");
new NamedChunkIdsPlugin().apply(compiler);
break;
}
case "deterministic": {
const DeterministicChunkIdsPlugin = require("./ids/DeterministicChunkIdsPlugin");
new DeterministicChunkIdsPlugin().apply(compiler);
break;
}
case "size": {
const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");
new OccurrenceChunkIdsPlugin({
prioritiseInitial: true
}).apply(compiler);
break;
}
case "total-size": {
const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");
new OccurrenceChunkIdsPlugin({
prioritiseInitial: false
}).apply(compiler);
break;
}
default:
throw new Error(
`webpack bug: chunkIds: ${chunkIds} is not implemented`
);
}
}
if (options.optimization.nodeEnv) {
const DefinePlugin = require("./DefinePlugin");
new DefinePlugin({
"process.env.NODE_ENV": JSON.stringify(options.optimization.nodeEnv)
}).apply(compiler);
}
if (options.optimization.minimize) {
for (const minimizer of options.optimization.minimizer) {
if (typeof minimizer === "function") {
minimizer.call(compiler, compiler);
} else if (minimizer !== "...") {
minimizer.apply(compiler);
}
}
}
if (options.performance) {
const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin");
new SizeLimitsPlugin(options.performance).apply(compiler);
}
new TemplatedPathPlugin().apply(compiler);
new RecordIdsPlugin({
portableIds: options.optimization.portableRecords
}).apply(compiler);
new WarnCaseSensitiveModulesPlugin().apply(compiler);
const AddManagedPathsPlugin = require("./cache/AddManagedPathsPlugin");
new AddManagedPathsPlugin(
options.snapshot.managedPaths,
options.snapshot.immutablePaths
).apply(compiler);
if (options.cache && typeof options.cache === "object") {
const cacheOptions = options.cache;
switch (cacheOptions.type) {
case "memory": {
if (isFinite(cacheOptions.maxGenerations)) {
const MemoryWithGcCachePlugin = require("./cache/MemoryWithGcCachePlugin");
new MemoryWithGcCachePlugin({
maxGenerations: cacheOptions.maxGenerations
}).apply(compiler);
} else {
const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
new MemoryCachePlugin().apply(compiler);
}
if (cacheOptions.cacheUnaffected) {
if (!options.experiments.cacheUnaffected) {
throw new Error(
"'cache.cacheUnaffected: true' is only allowed when 'experiments.cacheUnaffected' is enabled"
);
}
compiler.moduleMemCaches = new Map();
}
break;
}
case "filesystem": {
const AddBuildDependenciesPlugin = require("./cache/AddBuildDependenciesPlugin");
for (const key in cacheOptions.buildDependencies) {
const list = cacheOptions.buildDependencies[key];
new AddBuildDependenciesPlugin(list).apply(compiler);
}
if (!isFinite(cacheOptions.maxMemoryGenerations)) {
const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
new MemoryCachePlugin().apply(compiler);
} else if (cacheOptions.maxMemoryGenerations !== 0) {
const MemoryWithGcCachePlugin = require("./cache/MemoryWithGcCachePlugin");
new MemoryWithGcCachePlugin({
maxGenerations: cacheOptions.maxMemoryGenerations
}).apply(compiler);
}
if (cacheOptions.memoryCacheUnaffected) {
if (!options.experiments.cacheUnaffected) {
throw new Error(
"'cache.memoryCacheUnaffected: true' is only allowed when 'experiments.cacheUnaffected' is enabled"
);
}
compiler.moduleMemCaches = new Map();
}
switch (cacheOptions.store) {
case "pack": {
const IdleFileCachePlugin = require("./cache/IdleFileCachePlugin");
const PackFileCacheStrategy = require("./cache/PackFileCacheStrategy");
new IdleFileCachePlugin(
new PackFileCacheStrategy({
compiler,
fs: compiler.intermediateFileSystem,
context: options.context,
cacheLocation: cacheOptions.cacheLocation,
version: cacheOptions.version,
logger: compiler.getInfrastructureLogger(
"webpack.cache.PackFileCacheStrategy"
),
snapshot: options.snapshot,
maxAge: cacheOptions.maxAge,
profile: cacheOptions.profile,
allowCollectingMemory: cacheOptions.allowCollectingMemory,
compression: cacheOptions.compression
}),
cacheOptions.idleTimeout,
cacheOptions.idleTimeoutForInitialStore,
cacheOptions.idleTimeoutAfterLargeChanges
).apply(compiler);
break;
}
default:
throw new Error("Unhandled value for cache.store");
}
break;
}
default:
throw new Error(`Unknown cache type ${cacheOptions.type}`);
}
}
new ResolverCachePlugin().apply(compiler);
if (options.ignoreWarnings && options.ignoreWarnings.length > 0) {
const IgnoreWarningsPlugin = require("./IgnoreWarningsPlugin");
new IgnoreWarningsPlugin(options.ignoreWarnings).apply(compiler);
}
compiler.hooks.afterPlugins.call(compiler);
if (!compiler.inputFileSystem) {
throw new Error("No input filesystem provided");
}
compiler.resolverFactory.hooks.resolveOptions
.for("normal")
.tap("WebpackOptionsApply", resolveOptions => {
resolveOptions = cleverMerge(options.resolve, resolveOptions);
resolveOptions.fileSystem = compiler.inputFileSystem;
return resolveOptions;
});
compiler.resolverFactory.hooks.resolveOptions
.for("context")
.tap("WebpackOptionsApply", resolveOptions => {
resolveOptions = cleverMerge(options.resolve, resolveOptions);
resolveOptions.fileSystem = compiler.inputFileSystem;
resolveOptions.resolveToContext = true;
return resolveOptions;
});
compiler.resolverFactory.hooks.resolveOptions
.for("loader")
.tap("WebpackOptionsApply", resolveOptions => {
resolveOptions = cleverMerge(options.resolveLoader, resolveOptions);
resolveOptions.fileSystem = compiler.inputFileSystem;
return resolveOptions;
});
compiler.hooks.afterResolvers.call(compiler);
return options;
}
}
大部分代码都是通过 if 条件语句 来执行对应的 plugin 比如:splitPlugin 截取这一段的代码可以快速看一下
if (options.optimization.splitChunks) {
const SplitChunksPlugin = require("./optimize/SplitChunksPlugin");
new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler);
}
这里可以看到,通过 配置 optimization.splitChunks 后,webpack 内部引入了 SplitChunksPlugin 来,所以大家了解了吗?
小结
内容不完整,后面会慢慢补充,大家如果有急切想要了解的,可以留言~~~