这周主要在写公司内部的一个全栈小项目,修复一系列小问题后,接下来主要需要解决加载时间的问题。

这个项目的加载时间主要分为两部分:后端从 AWS 读取数据的时间,以及前端页面加载的时间。

后端方面,之前读取数据很慢的原因是,每次检索数据,都会新生成一个检索执行 ID,重新检索数据库,返回需要的数据。其实,这份数据在 AWS 上已经缓存好了,如果数据不会频繁发生变化,对于相同的检索语句,后端可以直接请求之前缓存的结果。修改了一下 AWS 上给的一个例子,加入了请求缓存的部分,后端这部分的问题就解决了。

前端页面的打包大小对页面首次加载时间有影响。尤其是在网络不是很好的情况下,如果网页的资源过大,用户等待时间就会过长。之前学校一个项目做的原型项目,前端没怎么优化,结果打包完要好几个 MB。

当时因为也没有发布到生产环境的要求,只是做个演示,所以重点就没有放到这方面的优化上。这次,面向公司内部的工具,质量是绝对要保证的。

项目采用了 React + Ant Design v3 + MobX 作为前端。有几个数据可视化组件用到了 Bizchart。优化的目标就是尽可能减小 bundle.js 的大小。

一开始,bundle.js 的大小是将近 4MB。

首先,用 BundleAnalyzerPlugin 看一下每个包的大小。

yarn add webpack-bundle-analyzer -D
// webpack.config.js 

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;

// plugins 中添加
plugins: [
    new BundleAnalyzerPlugin({ analyzerPort: 8999 }), // 默认端口是 8888
]

再运行 yarn build 就会弹出分析包大小的页面:
(这张图是用自己的另一个项目截的图,作为示例)
【插入图片】

当时的图片显示 antd.css 和 bizchart.js 都占了大头。And Design 的组件虽然配置了按需加载,但是组件的 CSS 当时没有配置。BizChart 也是没有配置按需加载。

配置按需加载

首先是 Ant Design。

安装 lessless-loader。这里由于比较新的版本不支持 Inline JavaScript 了,所以安装了下面这两个指定的版本:

yarn add -D less@3.9.0 less-loader@4.1.0

设置 Webpack 解析 .less 文件:

// webpack.config.js

module: {
    rules: [
     // ...
      {
        test: /\.less$/,
        use: [
          {
            loader: "style-loader",
          },
          {
            loader: "css-loader",
          },
          {
            loader: "less-loader",
            options: {
              javascriptEnabled: true, // 比较新的版本不支持这一设置
              lessOptions: {
                paths: [path.resolve(__dirname, "node_modules")],
              },
            },
          },
        ],
      },
    ]
  }

配置完成后,删除项目中引入 antd.css 的代码。这样,Ant Design 的样式也实现了按需加载。

接下来是 BizChart,参考官方文档,按照上面说明的写法引入组件,即可完成按需加载:

自 bizcharts@3.1.8 版本起,开始支持按需加载资源文件的功能。

import Chart from 'bizcharts/lib/components/Chart';
import Axis from 'bizcharts/lib/components/Axis';
import Line from 'bizcharts/lib/components/TypedGeom/Line';
// 如果有其他组件,也可以按照类似的写法来引入,注意判断是引用 TypedGeom 还是直接引用

至此,打包文件的大头都实现了按需加载,打包文件也变小了一些。

常见的优化方法还有使用动态链接,不过我配置之后,打包文件的大小并没有变化。也可能是我的配置出了问题,这个之后需要再研究一下。

Gzip 压缩

除了实现按需加载,其他的 Webpack 插件用了之后暂时没有很好的效果。但是,在那张打包文件可视化的图上,其实可以看到另外一组数据:Gzip 压缩文件大小。对于本项目,可以将文件压缩至600 KB。这和优化之前相比,是不小的改进了。上网搜索了一番,实现 Gzip 也比较容易。

首先,在请求头部添加一个设置项:

service = axios.create({
    // ...
    headers: {"accept-encoding": "gzip"}
});

然后,安装 compression-webpack-plugin:

yarn add -D compression-webpack-plugin

在 Webpack 设置中添加:

plugins: [
    new CompressionPlugin(),
]

再运行 yarn build 就会看到新生成了一个 bundle.js.gz 文件,只有 600KB。

在服务器上,也需要进行 Gzip 的配置。项目服务器用的是 Nginx,配置如下:

server {
    gzip on;
    gzip_static on;    
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_proxied  any;
    gzip_vary on;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;    
    ...
}

重启 nginx 服务器,重新加载页面时,在浏览器开发者工具的 Network 一栏中,看到 bundle.js 的文件大小确实为 600KB。大功告成!

小结

本文记录了项目初步优化 Webpack 配置的过程,主要实现了组件的按需加载以及打包文件压缩。虽然最后的结果还不是最理想的,但是相对于一开始来说已经是不错的改进,已经可以满足内部使用的需求。后续当项目变得更复杂以后,还会继续探索其他用于优化打包过程和结果的插件。

参考文章

https://medium.com/@selvaganesh93/how-to-serve-webpack-gzipped-file-in-production-using-nginx-692eadbb9f1c
重构之路:webpack打包体积优化 https://juejin.im/post/5c6fae50e51d45196636bf07