首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >前端高级进阶:如何更好地优化打包资源

前端高级进阶:如何更好地优化打包资源

作者头像
winty
发布于 2020-03-02 07:45:38
发布于 2020-03-02 07:45:38
1.7K00
代码可运行
举报
文章被收录于专栏:前端Q前端Q
运行总次数:0
代码可运行

这是山月关于高级前端进阶暨前端工程系列文章的第 M 篇文章 (M 随便打的,毕竟也不知道能写多少篇),关于前 M-1 篇文章,可以从我的 github repo shfshanyue/blog[1] 中找到,如果点进去的话可以捎带~点个赞~,如果没有点进去的话,那就给这篇文章点个赞。。今天的文章开始了

本篇文章地址在 前端工程化系列[2],欢迎订阅。


在前端中但凡谈到打包,肯定要提及到 webpack,毕竟它现在已经是最为流行的打包工具。但 webpack 更多地是表现在 上,于是我决定写这篇文章,更多地讲解一些关于 的。

对于一个前端而言,生产环境的静态资源优化,它既是面试中的高频问题,同时也最容易成为平时工作中的 OKR/KPI。如果你经常致力于优化前端打包提及,必然会对一些数字极为敏感,比如:

  1. lodashreact gzip 后的体积是多少 (定性,可以给出范围)
  2. 打包 moment 时会有什么问题
  3. 你们线上前端项目首屏静态资源 gzip 后的体积是多少

如果你负责了你们前端项目的打包优化,如果以上问题连一个都不了解那么是说不通的。以我作为面试官的两年经验中,如果候选人对这些问题有所了解的话,往往对打包以及webpack的了解就会相对深入一些

原则

一般谈到打包会有两方面的意思,第一在于提高打包的速度,第二在于对打包后的静态资源的优化。而对于静态资源的优化又不仅仅是打包提及的缩减。

对于打包资源优化的总体原则,在于尽可能的减少或者延迟模块的引用。主要遵循以下三点

  1. 减小打包的整体体积
  2. Code Splitting: 按需加载,优化页面首次加载体积。如根据路由按需加载,根据是否可见按需加载
  3. Bundle Splitting:分包,根据模块更改频率分层次打包,充分利用缓存

接下来本篇文章将会结合实例分别阐述这三点

01 减小打包的整体体积

第一种方法是减小打包的整体体积。减小打包的总体积有多种方式,这往往也是打包资源优化的着力点,一方面操作性高易于实践,~另一方面有具体数据支撑易于写PPT来晋升~。我从网站性能优化的实践角度,来分为以下几个方面

代码压缩

代码压缩可以非常可观地减小资源打包体积,但是它的可操作性空间过小。可操作性低的意思是这一项不太容易出现在晋级评审的PPT上,如同 CDN 在网站性能优化的重要程度一样,重要但不归你做(或者傻瓜式配置)。

它良好的模块化,以致于 webpack 就自作主张在生产环境中默认把这件事给做了。

那它是如何压缩代码的?最典型的两种方法就是空白符替换以及缩短变量名,如代码所示,仅仅通过这两种方式就大大压缩了 javascript 资源:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 压缩前
function sum (first, second) {
  return first + second;
}

// 压缩后
function s(x,y){return a+b}

关于代码压缩,可以参考山月的前端高级进阶系列[3]javascript 代码的体积是如何被压缩的[4]

移除不必要的模块

这句话好像是废话,但它却是真正有用并且极为容易实现的一点。

在以下代码中,对 lodash 这个模块进行了引入,但在之后的代码中并无使用 lodash,那在 webpack 中这个模块还会继续打包吗?

很遗憾,仍会对它进行打包。但好消息是这一点优化起来相当简单。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 仅仅引入而未在代码中使用,该模块仍然会被打包
import _ from 'lodash'

对于这类问题总应该防患于未然,扼杀于摇篮中。eslint 的用武之地来了,它除了统一团队的代码风格以外,也用来提高团队的代码质量以及性能。

选择可替代的体积较小的模块

针对这一条,有一个典型的例子是以体积过大而臭名昭著的 moment.js 模块,它仅仅用于 DateTime 的格式化及各种计算。但你 import 之后它的体积竟然达到了 200kb+,gzip 后仍然有 69kb。以至于在 github 上有一个仓库专门用来介绍如何优化它,

  • How to optimize moment.js with webpack[5]

再来一张图感受一下它巨大的体积吧:

此时可以选择一个可替代它功能,但体积更小的模块。与 moment.js API 兼容的 day.js,它 gzip 后体积仅仅只有 2kb。

按需引入模块

当你面对一个巨无霸的,捆绑式的大型模块时,可能你并不会使用到它的所有的功能,你只需要按照你的需求引入模块就可以了。那经常会有哪些巨无霸模块呢?

lodash (勉强算),antdecharts,我相信这三个模块对于以 React 为主的前端工程师都或多或少使用过。对你所需要使用的模块单独引入:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import DatePicker from 'antd/es/date-picker'; // for js
import 'antd/es/date-picker/style/css'; // for css

import get from 'lodash.get'

02 Code Splitting: 按需加载,优化页面首次加载体积

懒加载,如果面试中提到懒加载的话,大概率面试官此时是想问你关于图片懒加载的问题。

前端开发中的图片懒加载如何实现[6]

通过 Code Splitting 可以只加载当前所需要的核心资源:

  1. 如果你处在首页,并且首页中有占用资源过重的图表,需要对图表懒加载,否则它会大幅拖垮应用的首次渲染,加大白屏时间
  2. 如果你处在首页,你无需加载当前不可见屏幕下方的复杂组件
  3. 如果你处在页面 A,你没有必要加载页面 B 的资源

他们实现起来均需要额外编写代码,所以可操作性中等,但是好在它能够带来极大的益处,投资回报率较高,操作起来也极为简单,接下来就属于体力活了:

  • 使用 import() 动态加载模块
  • 使用 React.lazy() 动态加载组件
  • 使用 lodable-component 动态加载路由,组件或者模块

大部分情况下,你只要做一个莫得感情的 API 工程师调用以上三个 API 就可以解决问题,大幅度降低页面的首次加载体积。但是在前往高级前端工程师的路上,你有可能需要了解其中的原理,(有可能并不需要,数据比原理重要) 来做更加精细化的控制,比如针对缓存。

Code Splitting 的原理是什么?[7]

03 Bundle Splitting

除了资源体积上的优化,另一个大的优化就是缓存。单页应用有一个最好的方面,就是所有资源都是带有指纹信息的,这意味着所有的资源都是能够设置永久缓存的。

但仅仅如此了吗?

如果你所有的 js 资源都打包成一个文件,它确实有永久缓存的优势。但是当有一行文件进行修改时,这一个大包的指纹信息发生改变,永久缓存失效。

所以我们现在需要做到的是:当修改文件后,造成最小范围的缓存失效,这样便能够更充分的利用缓存,减小宽带,减小服务器费用。一个好消息是 webpack 等打包工具虽然在 optimization 上内置了很多性能优化,但它不会帮你做这件事,它并不知道你有哪些模块,以及这些模块的重要紧急程度,你终于可以大展拳脚了。

此时我们可以对资源进行分层次缓存的打包方案,这是一个建议方案

  1. webpack-runtime: 应用中的 webpack 的版本比较稳定,分离出来,保证长久的永久缓存
  2. react-runtime: react 的版本更新频次也较低
  3. vundor: 常用的第三方模块打包在一起,如 lodashclassnames 基本上每个页面都会引用到,但是它们的更新频率会更高一些

随着 http2 的发展,特别是多路复用,初始页面的静态资源不受资源数量的影响。因此为了更好的缓存效果以及按需加载,也有很多方案建议把所有的第三方模块进行单模块打包。

在 webpack 中,使用 splitChunks.cacheGroups

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  splitChunks: {
    cacheGroups: {
      react: {
        test: /[\\/]node_modules[\\/](react|react-dom "\\/]node_modules[\\/")[\\/]/,
        name: 'react',
        chunks: 'all'
      },
      vendor: {

      }
    }
  },
  runtimeChunk: {
    name: entrypoint => `runtime-${entrypoint.name}`,
  },
}

小结

毫无疑问在前端中更好地优化打包资源属于网站性能优化强操作性部分的重中之重,整理下本篇文章关于资源优化的所有内

  1. 减小打包的整体体积
    • 代码压缩
    • 移除不必要的模块
    • 按需引入模块
    • 选择可以替代的体积较小的模块
  2. Code Splitting: 按需加载,优化页面首次加载体积。如根据路由按需加载,根据是否可见按需加载
    1. 使用 import() 动态加载模块
    2. 使用 React.lazy() 动态加载组件
    3. 使用 lodable-component 动态加载路由,组件或者模块
  3. Bundle Splitting:分包,根据模块更改频率分层次打包,充分利用缓存

参考资料

[1]

shfshanyue/blog: https://github.com/shfshanyue/blog

[2]

前端工程化系列: https://github.com/shfshanyue/blog/tree/master/frontend-engineering

[3]

前端高级进阶系列: https://github.com/shfshanyue/blog/tree/master/frontend-engineering

[4]

javascript 代码的体积是如何被压缩的: https://github.com/shfshanyue/blog/blob/master/frontend-engineering/uglify.md

[5]

How to optimize moment.js with webpack: https://github.com/jmblog/how-to-optimize-momentjs-with-webpack

[6]

前端开发中的图片懒加载如何实现: https://q.shanyue.tech/fe/html/1.html

[7]

Code Splitting 的原理是什么?: https://q.shanyue.tech/fe/webpack/206.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端Q 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
「influxDB 原理与实践(四)」保留策略
一台InfluxDB服务器每秒可以处理近百万条时序数据。如果所有数据都持久保存,数据量非常大,造成存储成本高昂。 常见的解决方法就是降低数据精度,即详细的、高时间精度的数据只能保留一段时间,同时对这些数据进行聚合计算得到低精度的、符合我们需求的数据,再根据实际情况存储一段时间然后删除高精度的数据,只保留低精度的数据。
源码之路
2020/09/04
1.5K0
「influxDB 原理与实践(四)」保留策略
Influx Sql系列教程四:series/point/tag/field
influxdb中的一条记录point,主要可以分为三类,必须存在的time(时间),string类型的tag,以及其他成员field;而series则是一个measurement中保存策略和tag集构成;本篇教程将介绍一些这几个概念
一灰灰blog
2019/08/21
1.4K0
时序数据库 InfluxDB(一)
数据库种类有很多,比如传统的关系型数据库 RDBMS( 如 MySQL ),NoSQL 数据库( 如 MongoDB ),Key-Value 类型( 如 redis ),Wide column 类型( 如 HBase )等等等等,当然还有本系列文章将会介绍的时序数据库 TSDB( 如 InfluxDB )。
凌虚
2020/07/17
3.8K0
时序数据库技术体系(二)–初识InfluxDB
在上篇文章《时序数据库体系技术 – 时序数据存储模型设计》中笔者分别介绍了多种时序数据库在存储模型设计上的一些考虑,其中OpenTSDB基于HBase对维度值进行了全局字典编码优化,Druid采用列式存储并实现了Bitmap索引以及局部字典编码优化,InfluxDB和Beringei都将时间线挑了出来,大大降低了Tag的冗余。在这几种时序数据库中,InfluxDB无疑显的更加专业。接下来笔者将会针对InfluxDB的基本概念、内核实现等进行深入的分析。本篇文章先行介绍一些相关的基本概念。 InfluxDB
企鹅号小编
2018/02/01
1.9K0
时序数据库技术体系(二)–初识InfluxDB
饿了么Influxdb实践之路
作者 | 刘平 文章来源GitChat,CSDN独家合作发布,查看交流实录:http://gitbook.cn/books/59428f6f7e850f039399fd02/index.html Influxdb是一个基于golang编写,没有额外依赖的开源时序数据库,用于记录metrics、events,进行数据分析。这篇文章谈论的influxdb版本在1.2.0以上。这篇文章只谈论influxdb在监控中的数据存储应用,不会谈论influxdb提供的整套监控方案。本文主要谈论五个方面:时序数据库选
CSDN技术头条
2018/02/08
5.1K0
饿了么Influxdb实践之路
java使用influxDB时序数据库
InfluxDB的字段类型,由第一条插入的值得类型决定;tags的类型只能是String型,可以作为索引,提高检索速度。
半条命专刊
2020/09/14
3K0
Influx Sql系列教程三:measurement 表
在influxdb中measurement相当于mysql中的表,可以理解为一条一条记录都是存与measurent中的,一个数据库中可以有多个measurement,一个measurement中可以存很多的数据。虽然可将measurement类比为mysql中的表,但是他们之间的差别也挺明显的
一灰灰blog
2019/08/21
1.7K0
InfluxDB
另外,InfluxDB也提供了多个可能需要自定义端口的插件,所以的端口映射都可以通过配置文件修改,对于默认安装的InfluxDB,这个配置文件位于/influxdb/influxdb.conf。
框架师
2021/03/05
1.6K0
influxdb 简介与实现(一)
InfluxDB是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及执行分析。
Timu
2018/07/17
1.5K0
influxdb 简介与实现(一)
influxdb的命令们
influxdb的单机版是开源的,而集群版是商业版,influxdb被设计运行在SSD上,如果使用机器或者网络磁盘作为存储介质,会导致性能下降至少一个数量级。influxdb支持restful api,同时也支持https,为了保证安全性,非局域网建议使用https与Influxdb进行通信。
luoxn28
2020/02/17
1.9K0
influxdb的命令们
时序数据库 InfluxDB(二)
先回顾一下 RP 策略( retention policy ),它由三个部分构成:
凌虚
2020/07/17
1.8K0
influxdb安装和学习
https://docs.docker.com/samples/library/influxdb/
Ryan-Miao
2019/06/21
1.7K0
大数据ClickHouse(二):多种安装方式
在官网中可以看到ClickHouse可以基于多种方式安装,rpm安装、tgz安装包安装、docker镜像安装、源码编译安装等。这里我们使用rpm安装包安装。目前Clickhouse仅支持Linux系统且cpu必须支持SSE4.2指令集,可以通过以下命令查询Linux是否支持:
Lansonli
2022/08/09
3.6K0
大数据ClickHouse(二):多种安装方式
influxdb基本操作_一个数据库只有一个内模式
转载于:https://juejin.im/post/5c4f07b7e51d454b0d75d883
全栈程序员站长
2022/11/16
3470
时序数据库influxdb简介
influxdb是一款开源的时序数据库,可以用作监控系统的数据存储或用来存储基于时序进行分析的业务系统的数据存储。
俊才
2020/05/04
2.9K0
influxdb 时间序列数据库
1、InfluxDB 是用Go语言编写的一个开源分布式时序、事件和指标数据库,无需外部依赖。 基于时间序列,支持与时间有关的相关函数(如最大,最小,求和等) 可度量性:你可以实时对大量数据进行计算 基于事件:它支持任意的事件数据 1)无结构(无模式):可以是任意数量的列 2)可拓展的 3)支持min, max, sum, count, mean, median 等一系列函数,方便统计 4)原生的HTTP支持,内置HTTP API 5)强大的类SQL语法 6)自带管理界面,方便使用 2、安装: rpm -ivh https://dl.influxdata.com/influxdb/releases/influxdb-0.13.0.x86_64.rpm 3、启动: sudo service influxdb start 4、客户端: 在usr/bin里使用influx即可登入Influx服务器。也可以将路径加入环境变量中,这样既可在任意地方使用influx。 InfluxDB自带web管理界面,在浏览器中输入 http://服务器IP:8083 即可进入web管理页面。 5、基本概念: database 数据库 measurement 表 point 表中的一行数据 point由time(自动生成的时间戳),field数据,tags由索引的数据 series所有在数据库中的数据,都需要通过图表来展示,而这个series表示这个表里面的数据,可以在图表上画成几条线:通过tags排列组合算出来。 6、基本操作: 客户端命令行、HTTP API、各语言API库 show databases; create database test drop database test use test
用户5760343
2022/05/14
1.3K0
influxdb 时间序列数据库
2.InfluxDB2.x数据库实践使用
描述: 在 V2.x 版本中 influx 客户端命令已独立处理, 其与V1.x版本的 influx cli 参数与使用大不相同, 此处主要讲解V2.x相关语法参数,但也会简单提及一下V1.x版本语法及其使用。
全栈工程师修炼指南
2022/09/29
6K1
2.InfluxDB2.x数据库实践使用
Oracle RMAN 基础配置和常用命令
1、备份保留策略rman连接到 RMAN 管理工具, rman 默认配置[oracle@orcl:/home/oracle]$ rman target /Recovery Manager: Release 11.2.0.4.0 - Production on Wed Jun 15 13:11:22 2022Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.connected to target datab
用户8006012
2022/06/17
1.3K0
InfluxDB 设置数据保留策略,验证保留的数据存储大小
在使用Telegraf+InfluxDB+Grafana监控服务器资源的时候,如果influxdb中的数据不设置超时过期的机制的话,那么数据就会默认一直保存。这样一直保存的话,数据量就会导致偏大。 这时候就要适当调整influxdb的数据存储时长,保留最近一段时间的数据即可。
Devops海洋的渔夫
2019/12/02
12.4K0
Influx Sql系列教程五:insert 添加数据
接下来开始进入influxdb的curd篇,首先我们看一下如何添加数据,也就是insert的使用姿势
一灰灰blog
2019/08/21
1.5K0
相关推荐
「influxDB 原理与实践(四)」保留策略
更多 >
LV.3
Server后端 & 爬虫 & IT & DBA
目录
  • 原则
  • 01 减小打包的整体体积
    • 代码压缩
    • 移除不必要的模块
    • 选择可替代的体积较小的模块
    • 按需引入模块
  • 02 Code Splitting: 按需加载,优化页面首次加载体积
  • 03 Bundle Splitting
  • 小结
    • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档