啥?线上css样式错乱了?我本地运行没问题啊!
myzbx 2025-01-24 13:03 20 浏览
前言
测试A:那啥!抠图仔,线上样式怎么点着点着就出问题了。
前端:啥?线上css样式错乱了?你是不是有缓存啊!清下缓存试试。
测试A(内心戏:这抠图仔一有问题就赖缓存):清缓存后,还有啊!你看看吧!
前端:见鬼了,我本地没复现啊。
问题背景
在某次迭代中,在做产品体验的时候发现从申请记录页面跳转我的订单,在切回来,发现申请记录页样式错乱了。本地调试发现没有该问题。
问题定位
- 发现该问题测试环境会出现,本地环境未复现
- 打开调试面板,定位到样式出现问题元素。发现antd的样式(.ant-card)覆盖了项目中写的样式(.recordCard___yE53v)。如图:
为什么会出现这种场景?为什么该问题测试环境会出现,本地环境未复现?
调试发现 .ant-card可以从多个chunk文件引入,切换到network面板发现,2966....chunk.css文件是在我们跳转到我的订单页面才引入的。也就是我的订单页面按需加载组件打包出来的样式文件。
到这其实就定位到问题所在了,相同组件在不同页面按需加载的时候css文件被重复打包了。
开发环境不会,是因为我们导入组件是直接导入的node_modules的es模块的文件,如图:
为什么会出现在不同页面按需加载的时候css文件被重复打包了呢?
dynamicImport: {
loading: '@/Loading',
},
umi开启dynamicImport时,会启动按route分包,实现页面级别的按需加载,这种分包模式明显在处理antd的样式模块复用上出现了一些问题。
所以推荐项目开启该模式时,antd应该使用下面的方案二进行处理antd的样式,防止出现偶现的线上问题。
之前代码中会出现很多莫名其妙的!important去提高样式的权重,当然也有在页面级引入antd.css的,可能也是因为遇到了antd样式覆盖的问题。
输出方案
方案一:提高recordCard___yE53v的权重,不推荐。
- 优点:
- 改动对其他业务无任何影响。
- 缺点:
- 治标不治本,其他类似场景问题需要重复处理,代码入侵严重,心智成本比较高。
方案二:修改umi打包配置,对引入多次的antd组件样式不重复打包,需要根据实际项目情况选择。
- 缺点:
- 因为是在整个工程方面改动,影响面比较大,需要放在测试环境验证一段时间
- 打包出来的verdors(3.8M),antdesigns(1.5M)js文件体积会比较大(实际压缩后不会这么大),一定程度上影响首屏加载速度。
- 优点:
- 采用分包,优化大文件资源,减少重复不必要代码。
// ...
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
minChunks: 2,
automaticNameDelimiter: '.',
cacheGroups: {
antd: {
name: 'antdesigns',
test: /[\/]node_modules[\/](antd|antd-mobile|@ant-design)[\/]/,
priority: 20,
},
vendors: {
name: 'vendors',
test({ resource }: any) {
return /[\/]node_modules[\/]/.test(resource);
},
priority: 10,
},
},
},
},
// ...
优化后如图所示,申请记录页面跳转到我的订单页面再跳回来,.ant-card并没有多产生一个css文件引入。整个dist文件包体积从116.5M到108.4M,降低了8.1M。
方案三:直接引入antd的less文件,不推荐
- 样式文件体积过大: 直接引入antd的less文件会导致整个antd样式库被打包到项目中,包括未使用的样式,从而增加了打包后的样式文件体积,影响页面加载性能。
- 影响页面渲染性能: 大量的样式文件会增加浏览器解析和渲染样式的时间,影响页面的加载速度和性能。
- 不利于 缓存 和更新: 直接引入antd的less文件会使样式文件无法通过浏览器缓存和CDN缓存等机制进行有效管理和更新。
webpack优化配置之splitChunks
webpack.docschina.org/plugins/spl…
默认值
- 新的 chunk 可以被共享,或者模块来自于 node_modules 文件夹
- 新的 chunk 体积大于 20kb(在进行 min+gz 之前的体积)
- 当按需加载 chunks 时,并行请求的最大数量小于或等于 30
- 当加载初始化页面时,并发请求的最大数量小于或等于 30
警告
选择了默认配置为了符合 Web 性能最佳实践,但是项目的最佳策略可能有所不同。如果要更改配置,则应评估所做更改的影响,以确保有真正的收益,所以我们做上述分包策略时,需要根据实际项目情况来处理。
// 下面这个配置对象代表 SplitChunksPlugin 的默认行为。
module.exports = {//...
optimization: {
splitChunks: {
// 有效值为 all,async 和 initial
chunks: 'async',
// 生成 chunk 的最小体积(以 bytes 为单位)。
minSize: 20000,
// 通过确保拆分后剩余的最小 chunk 体积超过限制来避免大小为零的模块。
minRemainingSize: 0,
// 拆分前必须共享模块的最小 chunks 数。
minChunks: 1,
// 按需加载时的最大并行请求数。
maxAsyncRequests: 30,
// 入口点的最大并行请求数。
maxInitialRequests: 30,
// 强制执行拆分的体积阈值和其他限制(minRemainingSize,maxAsyncRequests,maxInitialRequests)将被忽略。
enforceSizeThreshold: 50000,
/**
* 缓存组可以继承和/或覆盖来自 splitChunks.* 的任何选项。
* 但是 test、priority 和 reuseExistingChunk 只能在缓存组级别上进行配置。
* 将它们设置为 false以禁用任何默认缓存组。
*/
cacheGroups: {
defaultVendors: {
/**
* 控制此缓存组选择的模块。省略它会选择所有模块。
* 注:使用/是因为要同时适配unix和windows系统
*/
test: /[\/]node_modules[\/]/,
// 优先级,默认值0
priority: -10,
// 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块。这可能会影响 chunk 的结果文件名。
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
webpack知识延展
线上和本地运行结果不一致,一直是一件让前端开发者头痛的问题。造成这种情况的原因之一呢?是因为场景不一样,webpack提供了两种模式。
- Development 模式:
- 在开发模式下,Webpack 会生成映射文件(source map),以便于调试代码。
- 生成的代码不会被压缩,可读性更强,包括注释和格式化。
- 启用了热模块替换(Hot Module Replacement),可以在不刷新页面的情况下更新模块。
- 通常会有更多的详细的错误日志和警告信息,方便开发者排查问题。
- Production 模式:
- 在生产模式下,Webpack 会对代码进行压缩和优化,以减小文件大小和提高性能。
- 不会生成映射文件,以减少额外的文件大小。
- 移除了开发时的一些辅助功能,如热模块替换,以提高性能。
- 通常会有更少的详细错误日志和警告信息,以减少额外的开销。
我们要杜绝发生线上和本地运行结果不一致的这种情况,需要我们深入了解项目中会用到的webpack,vite,rollup等前端工程化工具的内部打包机制。
知识补充
- class="name1 name2"样式覆盖不是根据这里的类名先后来的 而是根据生成的样式表中的顺序。
作者:城主北宁
链接:https://juejin.cn/post/7346884660443988019
相关推荐
- C语言备忘录 - 09. 数组与字符串(c语言数组字符串长度)
-
C语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。一、数组定义/*定义一个一维数组数...
- Java 读取 xml 文件的五种方式(java读取xml工具类)
-
1、Java读取xml文件的五种方式在Java中读取XML文件有多种方法,这里列出五种常见的方式:DOM解析器(DocumentObjectModel):DOM是处理XML文...
- 如何获取一个APP的所有接口API和参数签名信息?
-
先给出所需的工具:步骤工具/技术抓包Charles、Fiddler、Wireshark、tcpdump反编译Jadx、JEB、Apktool动态调试Frida、IDAPro、Unidbg/Unico...
- 编辑距离算法详解:Levenshtein Distance算法
-
算法基本原理:假设我们可以使用d[i,j]个步骤(可以使用一个二维数组保存这个值),表示将串s[1…i]转换为串t[1…j]所需要的最少步骤个数,那么,在最基本的情况下,即在i等...
- RTCP协议详解(SR、RR、SDES、BYE、APP、NACK、TCC、PLI、SLI)
-
RTCP协议规范中定义了五种类型的RTCP包:接收方报告(RR)、发送方报告(SR)、源描述(SDES)、成员管理(BYE)和应用程序定义(APP)。SR:payload...
- javascript实现获取中文汉字拼音首字母
-
今天分享一个日常开发中可能会用到的一个小功能,简单说就是输入中文汉字可转换得到中文汉字拼音首字母。当然我可写不出这样的功能,源码来自于其他民间大神的分享,博主在此记录一下功能demo,方便日后复用,同...
- 记一次前端逻辑绕过登录到内网挖掘
-
前言在测试一个学校网站的时候发现一个未授权访问内网系统,但是这个未授权并不是接口啥的,而是对前端js的审计和调试发现的漏洞,这里给大家分享一下这次的漏洞的过程文章中涉及的敏感信息均已做打码处理,文...
- Node.js 是怎么找到模块的?(node.js有哪些模块)
-
大家好,我是前端西瓜哥,今天我们来看看Node.js模块查找的原理。模块种类模块有三种来源。核心模块:Node.js内置的包。比如http、fs、path;自定义模块:NPM包。比如axi...
- 细节确定成败!全网最详细的xxs夸脚本攻击以及测试方法(上)
-
XSS全称是CrossSiteScripting也是跨站脚本,他也分为三种类型存储型,反射型,DOM型。当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就...
- 简单易懂的KMP字符串匹配算法(实现kmp字符串匹配)
-
什么是KMPKMP算法是Knuth、Morris和Pratt三人设计的线性时间字符串匹配算法。算法的核心思想是尽可能地利用已知信息,减少尝试匹配的次数,从而降低时间复杂度。要想彻底地弄懂KMP算法,需...
- golang标准库每日一库之strings(golang 字符串操作)
-
以下为Go语言strings包的深度解析,涵盖字符串切割、替换、查找等核心操作及高效处理技巧:一、基础字符串操作1.字符串切割(Split)函数作用描述示例strings.Split(s,s...
- 开源轻量级BT下载器qBittorrent 5.1.1发布:改进Wayland会话
-
IT之家6月24日消息,科技媒体9to5Linux昨日(6月23日)发布博文,报道称开源轻量级BT下载器qBittorrent发布5.1.1版本更新,主要改进支持Lin...
- 晨雾轻散时!2 道 JS 面试题细解,静享知识慢时光
-
清晨的雾气渐渐散去,阳光透过纱窗洒在桌前,泡一杯温热的蜂蜜水,让我们在这宁静的氛围里,以轻松的节奏聊聊两道JavaScript高频面试题。就像在晨光中散步,不急不躁地探索知识,让学习成为一种治愈的...
- JS 写正则表达式,判断是否为手机号
-
以下是使用JavaScript写正则表达式,判断一个字符串是否为手机号的示例代码:在上述代码中,我们定义了一个isPhoneNumber函数,该函数接收一个字符串作为参数,使用正则表达式判断该...
- 不用任何 js 库,纯前端导出数据到 Excel / CSV 文件就简单几行代码
-
最近实现的导出数据为表格的需求,不需要工具库,也不要后端实现,mark一下。js导出excel表格最近工作中又遇到了将表格数据导出为excel表格的需求,我第一时间想到的是之前我的网站上推...
- 一周热门
- 最近发表
-
- C语言备忘录 - 09. 数组与字符串(c语言数组字符串长度)
- Java 读取 xml 文件的五种方式(java读取xml工具类)
- 如何获取一个APP的所有接口API和参数签名信息?
- 编辑距离算法详解:Levenshtein Distance算法
- RTCP协议详解(SR、RR、SDES、BYE、APP、NACK、TCC、PLI、SLI)
- javascript实现获取中文汉字拼音首字母
- 记一次前端逻辑绕过登录到内网挖掘
- Node.js 是怎么找到模块的?(node.js有哪些模块)
- 细节确定成败!全网最详细的xxs夸脚本攻击以及测试方法(上)
- 简单易懂的KMP字符串匹配算法(实现kmp字符串匹配)
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 选择器 (30)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)