create-react-app,webpack配置超强解析
0 条评论【create-react-app,webpack配置超强解析】【建议收藏】😎这一次再也不怕webpack面试了
掘金作者:吃饺子不吃馅
原文链接:https://juejin.cn/post/7459740471654023220
Create React App (CRA) 是 React 官方推荐的脚手架工具,它封装了 Webpack、Babel、ESLint 等工具,提供了开箱即用的开发环境。虽然 CRA 隐藏了大部分配置细节,但在某些情况下,我们可能需要自定义 Webpack 配置。本文将详细解读 CRA 的 Webpack 配置文件,帮助你理解其工作原理和核心配置。
1. 配置文件概览
我们先用create-react-app创建一个项目,然后npm run eject,可以看到webpack的配置文件webpack.config.js
CRA 的 Webpack 配置它是一个函数,接收 webpackEnv
参数(表示当前环境,如 development
或 production
),并返回一个 Webpack 配置对象。
配置文件的主要部分包括:
- 入口和输出配置
- 模块解析规则
- 插件配置
- 优化配置
- 开发和生产环境的差异处理
- 缓存配置
2. 核心配置解析
2.1 入口和输出配置
入口(Entry)
1 | javascript 代码解读复制代码entry: paths.appIndexJs, |
paths.appIndexJs
是应用的入口文件,通常是src/index.js
或src/index.tsx
。
输出(Output)
1 | javascript 代码解读复制代码output: { |
path
:构建输出的目录,通常是build
。filename
:主 bundle 的文件名,生产环境使用哈希值以支持缓存。chunkFilename
:异步加载的 chunk 文件名。assetModuleFilename
:静态资源(如图片、字体)的输出路径和文件名。publicPath
:静态资源的公共路径,通常与homepage
配置相关。
2.2 模块解析规则【loader】
模块解析(resolve)
源码如下:
1 | javascript 代码解读复制代码resolve: { |
modules
:模块查找路径,优先从node_modules
和项目根目录的node_modules
中查找。extensions
:支持的扩展名,如.js
、.jsx
、.ts
、.tsx
。alias
:路径别名,支持 React Native Web 和自定义别名。ModuleScopePlugin
:限制模块导入范围,防止从src
目录外导入模块。paths.appPackageJson
:项目的package.json
文件。reactRefreshRuntimeEntry
:React 热更新的运行时入口文件。reactRefreshWebpackPluginRuntimeEntry
:React 热更新插件的运行时入口文件。babelRuntimeEntry
:Babel 运行时的入口文件。babelRuntimeEntryHelpers
:Babel 运行时的辅助函数文件。babelRuntimeRegenerator
:Babel 运行时的 regenerator 文件。
模块规则(Module Rules)
源码如下:
1 | javascript 代码解读复制代码 module: { |
module
是 Webpack 配置的核心部分,用于定义如何处理不同类型的文件(模块)。它包含两个主要属性:
strictExportPresence
:设置为true
,表示如果模块导出不存在,Webpack 会抛出错误。rules
:定义了一系列规则(rules
),每个规则指定了如何处理特定类型的文件。
接下来一个一个分析其作用
处理 Source Maps
1 | javascript 代码解读复制代码shouldUseSourceMap && { |
- 作用:在开发环境中,使用
source-map-loader
加载 Source Maps,以便在调试时能够定位到源代码。 enforce: 'pre'
:确保该 loader 在其他 loader 之前执行。exclude
:排除@babel/runtime
中的文件,避免重复处理。test
:匹配 JavaScript、TypeScript 和 CSS 文件。
oneOf
规则
oneOf
是 Webpack 的一种优化机制,它会按顺序遍历规则列表,直到找到匹配的规则。如果没有匹配的规则,则使用最后的 file-loader
。
处理 AVIF 图片
1 | javascript 代码解读复制代码{ |
- 作用:处理 AVIF 格式的图片。
type: 'asset'
:将文件作为资源处理,小于imageInlineSizeLimit
的图片会转为 Base64 编码。mimetype
:指定文件的 MIME 类型。
处理常见图片格式
1 | javascript 代码解读复制代码{ |
- 作用:处理 BMP、GIF、JPEG、PNG 等常见图片格式。
type: 'asset'
:将文件作为资源处理,小于imageInlineSizeLimit
的图片会转为 Base64 编码。
处理 SVG 图片
1 | javascript 代码解读复制代码{ |
- 作用:处理 SVG 图片,并使用
@svgr/webpack
将其转换为 React 组件。 @svgr/webpack
:将 SVG 文件转换为 React 组件。file-loader
:处理 SVG 文件的静态资源路径。
处理应用代码(JavaScript/TypeScript)
1 | javascript 代码解读复制代码{ |
- 作用:使用 Babel 编译应用代码(JavaScript 和 TypeScript)。
include
:仅处理src/
目录下的文件。babel-loader
:使用 Babel 编译代码。presets
:使用babel-preset-react-app
预设,支持 React 和 TypeScript。plugins
:react-refresh/babel
:在开发环境中启用 React 热更新。babel-plugin-transform-antd-resize-table
:自定义插件,用于处理 Ant Design 表格组件的调整大小功能。
cacheDirectory
:启用 Babel 缓存,加快构建速度。
处理第三方库代码
1 | javascript 代码解读复制代码{ |
- 作用:使用 Babel 编译第三方库代码。
exclude
:排除@babel/runtime
中的文件。presets
:使用babel-preset-react-app/dependencies
预设,仅编译标准的 ES 特性。
处理 CSS 文件
1 | javascript 代码解读复制代码{ |
- 作用:处理普通的 CSS 文件。
getStyleLoaders
:返回一组 loader,包括style-loader
、css-loader
和postcss-loader
。modules.mode: 'icss'
:启用 ICSS(Interoperable CSS)模式。
处理 CSS Modules
1 | javascript 代码解读复制代码{ |
- 作用:处理 CSS Modules 文件。
modules.mode: 'local'
:启用 CSS Modules 的局部作用域。getLocalIdent
: 使用 CRA 的类名生成规则
处理 Sass 文件
1 | javascript 代码解读复制代码{ |
- 作用:处理普通的 Sass 文件。
sass-loader
:将 Sass 编译为 CSS。
处理 Sass Modules
1 | javascript 代码解读复制代码{ |
- 作用:处理 Sass Modules 文件。
modules.mode: 'local'
:启用 CSS Modules 的局部作用域。
处理其他文件
1 | javascript 代码解读复制代码{ |
- 作用:处理其他类型的文件(如图片、字体等)。
type: 'asset/resource'
:将文件作为静态资源处理,并输出到指定目录。
2.3 插件配置【plugin】
源码如下:
1 | javascript 代码解读复制代码plugins: [ |
HtmlWebpackPlugin
1 | javascript 代码解读复制代码new HtmlWebpackPlugin( |
- 作用:生成
index.html
文件,并自动注入打包后的 JavaScript 和 CSS 文件。 - 配置:
inject: true
:自动将生成的资源文件注入到 HTML 中。template: paths.appHtml
:使用指定的 HTML 模板文件(通常是public/index.html
)。minify
:在生产环境中启用 HTML 压缩,移除注释、空白字符等。
InlineChunkHtmlPlugin
1 | javascript 代码解读复制代码isEnvProduction && |
- 作用:将 Webpack 的 runtime 代码内联到 HTML 中,减少网络请求。
- 条件:仅在生产环境且
shouldInlineRuntimeChunk
为true
时启用。 - 参数:
HtmlWebpackPlugin
:指定要操作的 HTML 插件。[/runtime-.+[.]js/]
:匹配需要内联的 runtime 文件。
InterpolateHtmlPlugin
1 | javascript 代码解读复制代码new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw) |
- 作用:在 HTML 中插入环境变量。例如,
%PUBLIC_URL%
会被替换为publicUrlOrPath
。 - 参数:
HtmlWebpackPlugin
:指定要操作的 HTML 插件。env.raw
:环境变量对象。
ModuleNotFoundPlugin
1 | javascript 代码解读复制代码new ModuleNotFoundPlugin(paths.appPath) |
- 作用:在模块未找到时提供更友好的错误提示,帮助开发者快速定位问题。
- 参数:
paths.appPath
:项目的根目录。
DefinePlugin
1 | javascript 代码解读复制代码new webpack.DefinePlugin(env.stringified) |
- 作用:在编译时将环境变量注入到代码中。例如,
process.env.NODE_ENV
会被替换为"production"
或"development"
。 - 参数:
env.stringified
:环境变量对象,键值对会被注入到代码中。
ReactRefreshWebpackPlugin
1 | javascript 代码解读复制代码isEnvDevelopment && |
- 作用:在开发环境中启用 React 组件的热更新(Hot Module Replacement, HMR)。
- 条件:仅在开发环境且
shouldUseReactRefresh
为true
时启用。 - 参数:
overlay: false
:禁用错误覆盖层。
CaseSensitivePathsPlugin
1 | javascript 代码解读复制代码isEnvDevelopment && new CaseSensitivePathsPlugin() |
- 作用:在开发环境中检查文件路径的大小写敏感性,避免因路径大小写不一致导致的错误。
- 条件:仅在开发环境中启用。
MiniCssExtractPlugin
1 | javascript 代码解读复制代码isEnvProduction && |
- 作用:将 CSS 提取为单独的文件,而不是内联到 JavaScript 中。
- 条件:仅在生产环境中启用。
- 参数:
filename
:主 CSS 文件的输出路径和名称。chunkFilename
:异步加载的 CSS 文件的输出路径和名称。
WebpackManifestPlugin
1 | javascript 代码解读复制代码new WebpackManifestPlugin({ |
- 作用:生成资源清单文件(
asset-manifest.json
),记录所有打包后的资源文件及其路径。 - 参数:
fileName
:清单文件的名称。publicPath
:资源的公共路径。generate
:自定义清单文件的生成逻辑。
IgnorePlugin
1 | javascript 代码解读复制代码new webpack.IgnorePlugin({ |
- 作用:忽略
moment.js
中的本地化文件,减少打包体积。 - 参数:
resourceRegExp
:匹配要忽略的资源。contextRegExp
:匹配资源的上下文。
WorkboxWebpackPlugin.InjectManifest
1 | javascript 代码解读复制代码isEnvProduction && |
- 作用:生成 Service Worker 文件,支持 PWA(渐进式 Web 应用)。
- 条件:仅在生产环境且
swSrc
文件存在时启用。 - 参数:
swSrc
:Service Worker 的源文件路径。dontCacheBustURLsMatching
:匹配不需要缓存的文件。exclude
:排除不需要缓存的文件。maximumFileSizeToCacheInBytes
:设置缓存文件的最大大小。
ForkTsCheckerWebpackPlugin
1 | javascript 代码解读复制代码useTypeScript && |
- 作用:在单独的进程中检查 TypeScript 类型错误,提升构建速度。
- 条件:仅在项目使用 TypeScript 时启用。
- 参数:
async: isEnvDevelopment
:在开发环境中异步检查类型错误。typescript
:TypeScript 配置,包括路径、编译器选项等。issue
:指定需要检查的文件范围。logger
:控制日志输出。
ESLintPlugin
1 | javascript 代码解读复制代码!disableESLintPlugin && |
- 作用:在 Webpack 构建过程中运行 ESLint,检查代码规范。
- 条件:仅在未禁用 ESLint 时启用。
- 参数:
extensions
:需要检查的文件扩展名。formatter
:指定 ESLint 的输出格式。failOnError
:在发现错误时是否终止构建。context
:指定 ESLint 的工作目录。cache
:启用 ESLint 缓存,提升检查速度。baseConfig
:指定 ESLint 的基础配置。
2.4 优化配置
代码压缩
1 | javascript 代码解读复制代码optimization: { |
TerserPlugin
:压缩 JavaScript 代码。CssMinimizerPlugin
:压缩 CSS 代码。
代码分割
1 | javascript 代码解读复制代码splitChunks: { |
splitChunks
:将公共代码提取到单独的 chunk 中。runtimeChunk
:提取 Webpack 的 runtime 代码,减少重复加载。
2.5 缓存配置
1 | js 代码解读复制代码 cache: { |
缓存的作用
Webpack 的缓存机制可以显著提升构建性能,尤其是在大型项目中。它的核心作用包括:
- 减少重复编译:通过缓存已编译的模块,避免重复处理未变化的文件。
- 加快构建速度:在后续构建中直接使用缓存结果,减少构建时间。
- 支持增量构建:只重新编译变化的文件,而不是整个项目。
配置详解
type: 'filesystem'
1 | javascript 代码解读复制代码type: 'filesystem' |
- 作用:启用文件系统缓存,将缓存数据存储到磁盘中。
- 说明:
- Webpack 5 引入了持久化缓存功能,支持将缓存数据存储到文件系统中。
- 与内存缓存(
memory
)相比,文件系统缓存在重启构建后仍然有效。
version: createEnvironmentHash(env.raw)
1 | javascript 代码解读复制代码version: createEnvironmentHash(env.raw) |
- 作用:为缓存生成一个唯一的版本标识符。
- 说明:
createEnvironmentHash
是一个工具函数,用于根据环境变量(env.raw
)生成哈希值。- 当环境变量发生变化时,缓存版本会更新,确保缓存数据的有效性。
cacheDirectory: paths.appWebpackCache
1 | javascript 代码解读复制代码cacheDirectory: paths.appWebpackCache |
- 作用:指定缓存文件的存储目录。
- 说明:
paths.appWebpackCache
是缓存目录的路径,通常是node_modules/.cache/webpack
。- 缓存文件会存储在该目录下,以便后续构建时复用。
store: 'pack'
1 | javascript 代码解读复制代码store: 'pack' |
- 作用:指定缓存存储的方式。
- 说明:
pack
是 Webpack 5 中的一种缓存存储方式,它会将缓存数据打包成一个文件。- 这种方式可以减少文件数量,提升缓存读写效率。
buildDependencies
1 | javascript 代码解读复制代码buildDependencies: { |
- 作用:指定构建依赖,当这些依赖发生变化时,缓存会失效。
- 说明:
defaultWebpack: ['webpack/lib/']
:将 Webpack 的核心库作为构建依赖。如果 Webpack 版本发生变化,缓存会失效。config: [__filename]
:将当前配置文件(webpack.config.js
)作为构建依赖。如果配置文件发生变化,缓存会失效。tsconfig: [paths.appTsConfig, paths.appJsConfig]
:将 TypeScript 配置文件(tsconfig.json
)和 JavaScript 配置文件(jsconfig.json
)作为构建依赖。如果这些文件发生变化,缓存会失效。
- 本文链接:https://xuehuayu.cn/article/a91910b6.html
- 版权声明:① 标为原创的文章为博主原创,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接。② 标为转载的文章来自网络,已标明出处,侵删。