css-vars-ponyfill
通过css变量来实现网页换肤的过程中,会出现兼容性问题。
为了解决ie,qq,百度浏览器等兼容性问题,引入css-vars-ponyfill,但是在ie浏览器下,css-vars-ponyfill 的在nextjs下表现不佳,主要缺陷是由于页面是服务端渲染,因此用户在看到界面后,动态主题色等样式不能很快渲染好,而是有一个过渡的时间(css-vars-ponyfill 仅支持client-side),颜色会存在明显替换的过程用户体验差。通过阅读 源码 可以看到,cssVars需要等到浏览器contentLoaded之后,才会触发,否则一直监听dom的data content事件,这就导致了体验上的问题。
解决方案
1.解析速度
通过把直接去除 document.readyState !== 'loading'
这样的限制条件使得浏览器在解析到,然后更改css-vars-ponyfill 的引入方式(旧的引入方式是在nextjs中的mainjs中引入module,然后直接调用cssVars(),这样在调用到ponyfill的脚本前还会解析其他不相关的chunk,为了更快的解析css变量,需要手动选择插入位置),更改之后的css-vars-ponyfill 通过找到css变量的位置(nextjs 通过将不同组件下的style,统一打包在header里面),然后将更改后的ponyfill 插入到style 之后进行调用,这一步选择在服务端渲染的 _document.tsx 文件中更改。
2.解析稳定性
通过手动更改文件解析位置,以及对源码的条件触发机制进行相关更改,首页颜色渲染速度有了一定提升。但是仍存在一个问题,即通过路由跳转的界面,如果有新的style chunk,插入时不能进行有效的css变量解析(已尝试配置cssVars的option 打开MutationObserver)。
因此,解决方案是通过判断UA,来让ie等浏览器下所有的路由通过a标签跳转,触发css-ponyfill的重新解析执行。
export function browser() { const UA = window.navigator.userAgent if (UA.includes("qqbrowser")) return "qqbrowser" if (UA.includes("baidu")) return "baidu" if (UA.includes("Opera")) return "Opera" if (UA.includes("Edge")) return "Edge" if (UA.includes("MSIE") || (UA.includes("Trident") && UA.includes("rv:11.0"))) return "IE" if (UA.includes("Firefox")) return "Firefox" if (UA.includes("Chrome")) return "Chrome" if (UA.includes("Safari")) return "Safari" }
type CommonLinkProps = { children: ReactElement href?: string target?: string outerLink?: boolean styles?: unknown } export default function CustomLink(props: CommonLinkProps) { const { children, href, target, as, outerLink, styles = emptyStyles } = props const [isIE, setIE] = useState<boolean>(false) const cloneEl = (c: ReactElement, props?: any) => React.cloneElement(c, { href: as ?? href, target, ...props }) useEffect(() => { if (["IE", "qqbrowser", "baidu"].includes(browser())) { setIE(true) } }, []) function renderLink() { if (Children.only(children).type === "a") { const node = cloneEl(children as ReactElement) return node } else { let fn: () => void | null = null if (outerLink) { fn = () => { window.open(as ?? href) } } else { fn = () => { window.location.href = as ?? href } } const node = cloneEl(children as ReactElement, { onClick: () => { fn() }, }) return node } } return ( <> {!href ? ( children ) : isIE ? ( renderLink() ) : ( <Link {...props}>{children}</Link> )} <style jsx>{styles}</style> </> ) }
这里children的type 选择了 ReactElement
,而不是插槽中通常支持的 ReactNode
主要是不想考虑直接插入字符串这种情况,会增加问题的复杂度,因此直接在type这层做限制。还有Fragments 也没有考虑,且没有找到有效的Fragments 类型,没法在ReactNode 中把它Omit掉,nextjs 里面的Link 如果首层插入了Fragments 后,也无法正常跳转,可能原因也是无法再Fragments 上面绑定有效的事件吧,目前Fragments(16.13.1) 只支持key属性,希望后续可以优化。
总结
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]