react-create-app项目解析一 webpack.config.js

此次isEnvProduction=true为例

bail

在第一个错误出现时抛出失败结果,而不是容忍它.开发环境设置为false,生产打包设置为true

devtool

是否生成,以及如何生成 source map

entry

打包入口文件 paths.appIndexJs为我们的入口文件目录

isEnvDevelopment && !shouldUseReactRefresh
				? [webpackDevClientEntry,paths.appIndexJs,]
				: paths.appIndexJs

如果是开发环境,且shouldUseReactRefresh为false,那么就使用数组里面的配置,这个是react-create-app自定义的WebpackDevServer,默认情况它是被禁用的。

output

打包输出文件,下面单独分析。

optimization

下面单独分析。

resolve

resolveLoader

module

plugins

node

performance

output 配置代码

output: {
			// The build folder.
			path: isEnvProduction ? paths.appBuild : undefined,
			// Add /* filename */ comments to generated require()s in the output.
			pathinfo: isEnvDevelopment,
			// There will be one main bundle, and one file per asynchronous chunk.
			// In development, it does not produce real files.
			filename: isEnvProduction
				? "static/js/[name].[contenthash:8].js"
				: isEnvDevelopment && "static/js/bundle.js",
			// TODO: remove this when upgrading to webpack 5
			futureEmitAssets: true,
			// There are also additional JS chunk files if you use code splitting.
			chunkFilename: isEnvProduction
				? "static/js/[name].[contenthash:8].chunk.js"
				: isEnvDevelopment && "static/js/[name].chunk.js",
			// webpack uses `publicPath` to determine where the app is being served from.
			// It requires a trailing slash, or the file assets will get an incorrect path.
			// We inferred the "public path" (such as / or /my-project) from homepage.
			publicPath: paths.publicUrlOrPath,
			// Point sourcemap entries to original disk location (format as URL on Windows)
			devtoolModuleFilenameTemplate: isEnvProduction
				? (info) =>
						path
							.relative(paths.appSrc, info.absoluteResourcePath)
							.replace(/\\/g, "/")
				: isEnvDevelopment &&
				  ((info) =>
						path
							.resolve(info.absoluteResourcePath)
							.replace(/\\/g, "/")),
			// Prevents conflicts when multiple webpack runtimes (from different apps)
			// are used on the same page.
			jsonpFunction: `webpackJsonp${appPackageJson.name}`,
			// this defaults to 'window', but by setting it to 'this' then
			// module chunks which are built will work in web workers as well.
			globalObject: "this",
		},

path: isEnvProduction ? paths.appBuild : undefined,

打包输入文件目录

pathinfo: isEnvDevelopment,

告知 webpack 在 bundle 中引入「所包含模块信息」的相关注释。此选项在 development 模式时的默认值为 true,而在 production 模式时的默认值为 false。当值为 'verbose' 时,会显示更多信息,如 export,运行时依赖以及 bailouts。

filename: isEnvProduction

? "static/js/[name].[contenthash:8].js"

: isEnvDevelopment && "static/js/bundle.js",

打包生成文件名称,

[contenthash:8] hash前8位。

chunkFilename: isEnvProduction
				? "static/js/[name].[contenthash:8].chunk.js"
				: isEnvDevelopment && "static/js/[name].chunk.js",

chunkFile文件名称

publicPath: paths.publicUrlOrPath

指定在浏览器中所引用的「此输出目录对应的公开 URL」。相对 URL(relative URL) 会被相对于 HTML 页面(或  标签)解析。相对于服务的 URL(Server-relative URL),相对于协议的 URL(protocol-relative URL) 或绝对 URL(absolute URL) 也可是可能用到的,或者有时必须用到,例如:当将资源托管到 CDN 时
devtoolModuleFilenameTemplate: isEnvProduction
				? (info) =>
						path
							.relative(paths.appSrc, info.absoluteResourcePath)
							.replace(/\\/g, "/")
				: isEnvDevelopment &&
				  ((info) =>
						path
							.resolve(info.absoluteResourcePath)
							.replace(/\\/g, "/")),

此选项仅在 「devtool 使用了需要模块名称的选项」时使用。

自定义每个 source map 的 sources 数组中使用的名称。可以通过传递模板字符串(template string)或者函数来完成

globalObject: "this",

这默认为 'window',但是通过将其设置为 'this' 然后,构建的模块块也可以在 web worker 中工作。

optimization 配置代码


		optimization: {
			minimize: isEnvProduction,
			minimizer: [
				// This is only used in production mode
				new TerserPlugin({
					terserOptions: {
						parse: {
							// We want terser to parse ecma 8 code. However, we don't want it
							// to apply any minification steps that turns valid ecma 5 code
							// into invalid ecma 5 code. This is why the 'compress' and 'output'
							// sections only apply transformations that are ecma 5 safe
							// https://github.com/facebook/create-react-app/pull/4234
							ecma: 8,
						},
						compress: {
							ecma: 5,
							warnings: false,
							// Disabled because of an issue with Uglify breaking seemingly valid code:
							// https://github.com/facebook/create-react-app/issues/2376
							// Pending further investigation:
							// https://github.com/mishoo/UglifyJS2/issues/2011
							comparisons: false,
							// Disabled because of an issue with Terser breaking valid code:
							// https://github.com/facebook/create-react-app/issues/5250
							// Pending further investigation:
							// https://github.com/terser-js/terser/issues/120
							inline: 2,
						},
						mangle: {
							safari10: true,
						},
						// Added for profiling in devtools
						keep_classnames: isEnvProductionProfile,
						keep_fnames: isEnvProductionProfile,
						output: {
							ecma: 5,
							comments: false,
							// Turned on because emoji and regex is not minified properly using default
							// https://github.com/facebook/create-react-app/issues/2488
							ascii_only: true,
						},
					},
					sourceMap: shouldUseSourceMap,
				}),
				// This is only used in production mode
				new OptimizeCSSAssetsPlugin({
					cssProcessorOptions: {
						parser: safePostCssParser,
						map: shouldUseSourceMap
							? {
									// `inline: false` forces the sourcemap to be output into a
									// separate file
									inline: false,
									// `annotation: true` appends the sourceMappingURL to the end of
									// the css file, helping the browser find the sourcemap
									annotation: true,
							  }
							: false,
					},
					cssProcessorPluginOptions: {
						preset: [
							"default",
							{ minifyFontValues: { removeQuotes: false } },
						],
					},
				}),
			],
			// Automatically split vendor and commons
			// https://twitter.com/wSokra/status/969633336732905474
			// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
			splitChunks: {
				chunks: "all",
				name: isEnvDevelopment,
			},
			// Keep the runtime chunk separated to enable long term caching
			// https://twitter.com/wSokra/status/969679223278505985
			// https://github.com/facebook/create-react-app/issues/5358
			runtimeChunk: {
				name: (entrypoint) => `runtime-${entrypoint.name}`,
			},
		},

minimize: isEnvProduction,

告知 webpack 使用 TerserPlugin 或其它在 optimization.minimizer定义的插件压缩 bundle。

minimizer

仅用于生产模式。 TODO

resolve

module配置代码

module: {
			strictExportPresence: true,
			rules: [
				// Disable require.ensure as it's not a standard language feature.
				{ parser: { requireEnsure: false } },
				{
					// "oneOf" will traverse all following loaders until one will
					// match the requirements. When no loader matches it will fall
					// back to the "file" loader at the end of the loader list.
					oneOf: [
						// TODO: Merge this config once `image/avif` is in the mime-db
						// https://github.com/jshttp/mime-db
						{
							test: [/\.avif$/],
							loader: require.resolve("url-loader"),
							options: {
								limit: imageInlineSizeLimit,
								mimetype: "image/avif",
								name: "static/media/[name].[hash:8].[ext]",
							},
						},
						// "url" loader works like "file" loader except that it embeds assets
						// smaller than specified limit in bytes as data URLs to avoid requests.
						// A missing `test` is equivalent to a match.
						{
							test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
							loader: require.resolve("url-loader"),
							options: {
								limit: imageInlineSizeLimit,
								name: "static/media/[name].[hash:8].[ext]",
							},
						},
						// Process application JS with Babel.
						// The preset includes JSX, Flow, TypeScript, and some ESnext features.
						{
							test: /\.(js|mjs|jsx|ts|tsx)$/,
							include: paths.appSrc,
							loader: require.resolve("babel-loader"),
							options: {
								customize: require.resolve(
									"babel-preset-react-app/webpack-overrides"
								),
								presets: [
									[
										require.resolve(
											"babel-preset-react-app"
										),
										{
											runtime: hasJsxRuntime
												? "automatic"
												: "classic",
										},
									],
								],

								plugins: [
									[
										require.resolve(
											"babel-plugin-named-asset-import"
										),
										{
											loaderMap: {
												svg: {
													ReactComponent:
														"@svgr/webpack?-svgo,+titleProp,+ref![path]",
												},
											},
										},
									],
									isEnvDevelopment &&
										shouldUseReactRefresh &&
										require.resolve("react-refresh/babel"),
								].filter(Boolean),
								// This is a feature of `babel-loader` for webpack (not Babel itself).
								// It enables caching results in ./node_modules/.cache/babel-loader/
								// directory for faster rebuilds.
								cacheDirectory: true,
								// See #6846 for context on why cacheCompression is disabled
								cacheCompression: false,
								compact: isEnvProduction,
							},
						},
						// Process any JS outside of the app with Babel.
						// Unlike the application JS, we only compile the standard ES features.
						{
							test: /\.(js|mjs)$/,
							exclude: /@babel(?:\/|\\{1,2})runtime/,
							loader: require.resolve("babel-loader"),
							options: {
								babelrc: false,
								configFile: false,
								compact: false,
								presets: [
									[
										require.resolve(
											"babel-preset-react-app/dependencies"
										),
										{ helpers: true },
									],
								],
								cacheDirectory: true,
								// See #6846 for context on why cacheCompression is disabled
								cacheCompression: false,

								// Babel sourcemaps are needed for debugging into node_modules
								// code.  Without the options below, debuggers like VSCode
								// show incorrect code and set breakpoints on the wrong lines.
								sourceMaps: shouldUseSourceMap,
								inputSourceMap: shouldUseSourceMap,
							},
						},
						// "postcss" loader applies autoprefixer to our CSS.
						// "css" loader resolves paths in CSS and adds assets as dependencies.
						// "style" loader turns CSS into JS modules that inject