React 被大量用于前端密集型应用程序,具有其独特的性能和尺寸优化方式。改进两者将对 React 包大小产生相当大的可衡量的影响。考虑到我们专注于客户端渲染的应用程序,包大小越小,加载时间越快。
服务器端渲染将进一步缩短加载时间。在服务器端渲染中,当用户请求网页时,React 组件将在服务器本身中渲染为 HTML 代码。然后这个预渲染的页面被发送到浏览器,让用户立即看到页面,而无需 JS 加载时间的开销。
但这完全是一个不同的故事。让我们主要关注通过在代码中进行调整来改善包包大小来尝试改进客户端呈现的站点。让我们深入探讨一下。
React 代码的“捆绑”是跟踪所有导入和代码并将其组合成一个名为“Bundle”的单个文件的过程。 Webpack、Browserify 等已经为我们做到了这一点。
Webpack 有一个名为“代码分割”的功能,负责将单个包分割成更小的块,对块进行重复数据删除,并“按需”导入它们。这会显着影响应用程序的加载时间。
module.exports = { // Other webpack configuration options... optimization: { splitChunks: { chunks: 'all', // Options: 'initial', 'async', 'all' minSize: 10000, // Minimum size, in bytes, for a chunk to be generated maxSize: 0, // Maximum size, in bytes, for a chunk to be generated minChunks: 1, // Minimum number of chunks that must share a module before splitting maxAsyncRequests: 30, // Maximum number of parallel requests when on-demand loading maxInitialRequests: 30, // Maximum number of parallel requests at an entry point automaticNameDelimiter: '~', // Delimiter for generated names cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
使用 React Suspense 延迟加载组件 (React 18):与动态导入相结合将显示组件加载时间的明显改进。
通常,当我们在父组件中导入子组件时,我们是静态导入的。为了防止在我们实际必须渲染它之前导入该组件,我们可以将动态导入与 React Suspense 结合使用。 React Suspense 可以按需加载组件。它显示了 Fallback UI,同时动态导入然后渲染相应的组件。
import { lazy } from 'react'; // The lazy loaded Component has to be exported as default const BlogSection = lazy(() => import('./BlogSection.tsx')); export default function HomePage() { return ( <> <Suspense fallback={<Loading />}> <BlogSection /> </Suspense> </> ); } function Loading() { return <h2>Component is Loading...</h2>; }
这是 JavaScript 捆绑程序使用的一种技术,用于在创建捆绑包之前删除所有未使用的代码。 ES6代码可以进行tree-shaking;但是,基于 CommonJS 的代码(即使用“require”)不能进行 tree-shaken。
Webpack Bundle Analyzer 是一个插件,可帮助您通过交互式地图可视化 Webpack 的大小。
npm install --save-dev webpack-bundle-analyzer npm install -g source-map-explorer
然后配置您的 webpack 以将上述内容添加为插件:
plugins: [ new BundleAnalyzerPlugin(), new HtmlWebpackPlugin({ template: './public/index.html', // Path to your HTML template filename: 'index.html', // Output HTML file name inject: true, // Inject all assets into the body }), ];
确保您的脚本配置为运行 Webpack:
"build": "webpack --config webpack.config.js --mode production"
运行yarn build来生成report.html,它将帮助您有效地可视化您的包大小。
它看起来像这样:
让我们首先了解什么是阻塞渲染。阻塞渲染是指主线程(UX 更新)被阻塞,因为 React 在后台执行一些不太重要的任务。 React 16 之前都是这种情况。
React 18 引入了并发功能,这意味着它将:
使用 startTransition() 钩子将 React 更新视为非紧急更新,帮助 React 优先考虑紧急更新,例如用户输入和用户与组件的交互。
module.exports = { // Other webpack configuration options... optimization: { splitChunks: { chunks: 'all', // Options: 'initial', 'async', 'all' minSize: 10000, // Minimum size, in bytes, for a chunk to be generated maxSize: 0, // Maximum size, in bytes, for a chunk to be generated minChunks: 1, // Minimum number of chunks that must share a module before splitting maxAsyncRequests: 30, // Maximum number of parallel requests when on-demand loading maxInitialRequests: 30, // Maximum number of parallel requests at an entry point automaticNameDelimiter: '~', // Delimiter for generated names cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
在这个例子中,当输入值改变时,handleChange函数被调用。 startTransition 函数用于将对列表状态的更新标记为非紧急。这允许 React 优先更新值状态,确保即使列表很大时输入也能保持响应。
使用 useDeferredValue 钩子推迟一个值(通常是昂贵的计算),直到 UI 不那么繁忙。
import { lazy } from 'react'; // The lazy loaded Component has to be exported as default const BlogSection = lazy(() => import('./BlogSection.tsx')); export default function HomePage() { return ( <> <Suspense fallback={<Loading />}> <BlogSection /> </Suspense> </> ); } function Loading() { return <h2>Component is Loading...</h2>; }
在此示例中,useDeferredValue 挂钩用于推迟值状态,直到 UI 不那么繁忙。这有助于通过将大列表的渲染推迟到处理输入更新之后来保持输入响应。
并发渲染的主要优点:
如果您知道应用程序在加载过程中会获取任何大量资源,那么预加载资源是一个好主意。这些资源可以是字体、图像、样式表等
预加载有益的场景:
module.exports = { // Other webpack configuration options... optimization: { splitChunks: { chunks: 'all', // Options: 'initial', 'async', 'all' minSize: 10000, // Minimum size, in bytes, for a chunk to be generated maxSize: 0, // Maximum size, in bytes, for a chunk to be generated minChunks: 1, // Minimum number of chunks that must share a module before splitting maxAsyncRequests: 30, // Maximum number of parallel requests when on-demand loading maxInitialRequests: 30, // Maximum number of parallel requests at an entry point automaticNameDelimiter: '~', // Delimiter for generated names cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
有趣的事实:实施预加载后,包括 Shopify、Financial Times 和 Treebo 在内的许多网站都发现以用户为中心的指标(例如交互时间和用户感知延迟)提高了 1 秒。
我希望您觉得这个博客有帮助!您的反馈对我来说非常宝贵 ,所以请在下面的评论中留下您的想法和建议。
请随时在 LinkedIn 上与我联系以获取更多见解和更新。让我们保持联系,继续共同学习和成长!
以上是快速优化您的 ReactJS 应用程序的性能和大小的详细内容。更多信息请关注PHP中文网其他相关文章!