详解css-vars-ponyfill在ie环境下使⽤问题(nextjs构建)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.解析速度
通过把直接去除adyState !== '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 (ly(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 ? (
css变量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属性,希望后续可以优化。
总结
到此这篇关于css-vars-ponyfill 在ie环境下使⽤问题(nextjs 构建)的⽂章就介绍到这了,更多相关css-vars-ponyfill使⽤内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章,希望⼤家以后多多⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论