首页 > 其他分享 >性能优化 1 - 减小 Bundle 大小(React、Webpack、Minify、代码拆分)

性能优化 1 - 减小 Bundle 大小(React、Webpack、Minify、代码拆分)

时间:2022-09-03 22:14:27浏览次数:111  
标签:Minify 代码 bundle React Bundle 拆分 CSS 加载

性能优化 1 - 减小 Bundle 大小(React、Webpack、Minify、代码拆分)

Photo by 杰克逊·西默 on 不飞溅

优化 JavaScript 和 React 性能的方法之一是尽可能减小通过 Webpack 捆绑的 JavaScript 文件的大小。有几种方法可以做到这一点,首先,让我们看看如何最小化源代码本身,并将捆绑包分成多个文件,而不是使用代码拆分的一个文件。

1. 最小化源代码——minify、uglify

在编写源代码时,您和其他人必须适当地使用空格和换行符,以便您和其他人能够解释和理解您的代码,并且变量和函数的名称可以自己看到并知道它们的作用。但是,对于计算机来说,这些部分,即空格和长变量名,只会起到不必要地增加数据量的作用。因此,为了减少和最小化源代码的长度,需要去掉这两个元素。

缩小 可以称为压缩,指的是删除所有不必要的空格和换行符,并删除语法上非必要的过程(例如 JavaScript 中的分号)。

Uglify被翻译为混淆,是指改变变量和函数名称以使解释变得困难的过程。除了通过缩短名称来去除不必要的数据之外,即使外人打开源代码,也会产生难以解释变量和函数的作用的效果。虽然是很初级的级别,但是却有着最基本的安全效果。

1. JavaScript 压缩和混淆

当模式在 v4 及更高版本中为生产时,Webpack 工作。 自动压缩和混淆 做。在 v5 中,它是这个过程中使用的插件。 测试器-webpack-插件 有内置的 泰瑟 同时混淆。

如果您出于某种原因想跳过此步骤,您可以 优化:{minimze: false} 只需添加 .

2. CSS 压缩

与 JavaScript 一样,CSS 也有解释不需要的空格。官方 Webpack 文档中建议的删除它的方法是 CssMinimizer插件 使用它的方法。此外,将 CSS 分成单独的文件 MiniCssExtract插件 建议使用 .

 const MiniCssExtractPlugin = require("mini-css-extract-plugin");  
 const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");  
  
 模块.exports = {  
 模块: {  
 规则:[  
 {  
 测试:/.s?css$/,  
 使用:[MiniCssExtractPlugin.loader,“css-loader”,“sass-loader”],  
 },  
 ],  
 },  
 优化: {  
 最小化器:[  
 // `...` 用于扩展现有的最小化选项,如果省略,则默认值 terser plugin 被省略,因此 JS minify 不起作用。  
 `...`,  
 新的 CssMinimizerPlugin(),  
 ],  
 },  
 插件:[新的 MiniCssExtractPlugin()],  
 };

上面设置中要注意的一点是css loader。 样式加载器 没有被设置。如果您尝试同时使用两者,您将收到错误“未定义文档”。

原因是 MiniCssExtract 和 style-loader 分离 CSS 文件的角色是冲突的。样式加载器负责将 CSS 直接注入 DOM。因此,它按照从数组中最后一个加载程序执行的设置顺序首先写入。 ( 参考 ) MiniCssExtract 为每个 JS 文件创建不同的 CSS 文件。也就是说,当通过代码拆分创建多个bundle时,将在后面解释,每个文件的CSS都是单独生成的。因此,将这个分离的文件强行注入到 index.html 的 DOM 中是没有意义的。

两者都有自己的优点和缺点。如果通过 style-loader 直接注入到 DOM 中,可以减少接收 CSS 文件的请求数,从而降低页面的加载速度。另一方面,它的缺点是可以在当前页面中注入不必要的 CSS。

另一方面,如果你使用 MiniCssExtract,你可以只通过发送单独的请求来加载 CSS,但它的优点是减少了要加载的数据的大小,因为只加载了要在当前页面中使用的 CSS。

前者用于创建单个文件而不拆分bundle或页面间共享样式较多时,我认为最好选择

参考 - 何时分别使用 style-loader 和 MiniCssExtractPlugin?

2.代码拆分

捆绑模块是为了克服如果每个模块被分成一个单独的文件,必须发送太多请求的缺点。这个过程可以通过捆绑器自动化,它会自动分析模块之间的依赖关系并将它们变成一个单独的包。但是,如果代码量太大,一个bundle文件可能会变得太大,加载和执行文件可能需要很长时间。所以代码拆分是必要的。代码拆分的优点是可以通过只加载必要的代码和并行处理请求来提高加载速度。

代码拆分有两个维度。一个是 网络包配置 二是使用 在 React 中利用惰性 这是为了指定应用程序的各个部分将被分成单独的包。在前一种方法中,很容易将多个块中重复使用的代码(例如使用的外部包)分离到单独的包中。

1. Webpack 设置

webpack自动判断重复代码并将其分离到单独文件中的设置如下。

 输出: {  
 // 单独的 bundle 名称 => 避免产生文件名冲突  
 文件名:'[name].bundle.js',  
 路径:path.join(__dirname, '/dist'),  
 干净:真实  
 },  
  
 拆分块:{  
 块:'全部'  
 }

如果应用上述设置,您可以看到源代码和包是分开的,如下所示。

패키지 번들과 소스 코드 번들이 분리된 모습

但是,通过这种方式,所有页面都将加载相同的包捆绑包。因此,需要额外的工作来仅加载特定页面使用的包的代码。

2. 使用 React.lazy 拆分页面

用来隔离源代码本身的是 动态导入 成为。这是一种允许异步和动态加载 EcmaScript 模块的方法。使用它,在需要模块时执行代码并加载模块,而不是将其依赖的模块包含在同一个包中。

在 React 中,有一个函数可以让你通过这个过程动态加载组件。 React.lazy 成为。另外,如果你使用 Suspense,你可以延迟加载一个组件,直到需要它,并在成功加载时渲染它。官方文档说将它与 React Router 一起使用。 如何动态加载每条路由 它也被解释了。

如上配置后,如果你用webpack打包,你可以看到为每个根创建了一个单独的文件。

但是,如果通过默认设置将包分开,它的缺点是会创建一个以自动生成的 id 作为其名称的包。 (在上面的bundle分析图中,801是根据自动生成的id创建的文件名。)如果要给bundle文件命名一个有意义的名字,需要额外的设置。

首先,在动态导入过程中要命名单独的源代码包。 特别说明 必须插入。

 // webpack.config.js  
 输出: {  
 文件名:'[name].bundle.js',  
 chunkFilename: '[name].chunk.bundle.js',  
 路径:path.resolve(__dirname, 'dist'),  
 } // 应用程序.js  
 const Home = React.lazy(() => (  
 进口( /* webpackChunkName: "home" */ './routes/home')  
 ))

如果如上设置,当 webpack 打包这个模块时,它会识别出这个模块的名称是 home,并创建一个名称类似于 home.bundle.js 的文件。

这里需要注意的一点是,如果使用 TypeScript,编译 TypeScript 时会删除所有不必要的注释,并且 webpack 可能无法正常工作,因为它们在有机会分析上述注释之前就被删除了。为了防止这种情况,必须在 tsconfig 中关闭取消注释设置。关闭它是可以的,因为无论如何在 webpack 的缩小过程中删除了注释。 ( 参考 )

 编译器选项:{  
 “删除评论”:假,  
 // ...  
 }

此外,可以根据需要分离和捆绑外部包以创建捆绑包,并且可以为每个捆绑包指定不同的名称。

 优化: {  
 拆分块:{  
 // ...  
 缓存组:{  
 反应:{  
 测试:/[\\/]node_modules[\\/](react|react-dom)[\\/]/,  
 名称:'反应',  
 块:'全部',  
 },  
 },  
 },  
 },

资源 - 如何命名 webpack 块

如果加上上面的设置,react 和 react-dom 包的代码会打包成一个块,创建一个单独的包,然后 react.bundle.js 变成

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/11834/54070321

标签:Minify,代码,bundle,React,Bundle,拆分,CSS,加载
From: https://www.cnblogs.com/amboke/p/16653797.html

相关文章