当前位置: 移动技术网 > IT编程>开发语言>JavaScript > 详解css-vars-ponyfill 在ie环境下使用问题(nextjs 构建)

详解css-vars-ponyfill 在ie环境下使用问题(nextjs 构建)

2020年08月18日  | 移动技术网IT编程  | 我要评论
css-vars-ponyfill通过css变量来实现网页换肤的过程中,会出现兼容性问题。为了解决ie,qq,百度浏览器等兼容性问题,引入css-vars-ponyfill,但是在ie浏览器下,css

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属性,希望后续可以优化。

总结

到此这篇关于css-vars-ponyfill 在ie环境下使用问题(nextjs 构建)的文章就介绍到这了,更多相关css-vars-ponyfill使用内容请搜索移动技术网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持移动技术网!

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网