Detailed explanation of the use of css-vars-ponyfill in IE environment (nextjs build)

Detailed explanation of the use of css-vars-ponyfill in IE environment (nextjs build)

css-vars-ponyfill

When using CSS variables to achieve web page skinning, compatibility issues may arise.

In order to solve the compatibility issues of IE, QQ, Baidu browser, etc., css-vars-ponyfill was introduced. However, in IE browser, css-vars-ponyfill performs poorly under nextjs. The main defect is that since the page is rendered on the server side, after the user sees the interface, dynamic theme colors and other styles cannot be rendered quickly, but there is a transition time (css-vars-ponyfill only supports client-side), and there will be an obvious color replacement process, which leads to poor user experience. By reading the source code, we can see that cssVars needs to wait until the browser content is loaded before it is triggered. Otherwise, it will keep listening to the dom's data content event, which will cause experience problems.

Solution

1. Parsing speed

By directly removing the restriction condition of document.readyState !== 'loading' , the browser can parse it and then change the introduction method of css-vars-ponyfill (the old introduction method is to introduce the module in mainjs in nextjs, and then call cssVars() directly. In this way, other unrelated chunks will be parsed before calling the ponyfill script. In order to parse the css variables faster, you need to manually select the insertion position). The changed css-vars-ponyfill finds the location of the css variable (nextjs packages the styles under different components in the header), and then inserts the changed ponyfill into the style for calling. This step is changed in the _document.tsx file rendered on the server.

2. Analysis stability

By manually changing the file parsing location and making relevant changes to the conditional trigger mechanism of the source code, the color rendering speed of the home page has been improved to a certain extent. However, there is still a problem. That is, when a new style chunk is inserted through the route jump interface, effective CSS variable parsing cannot be performed (I have tried to configure the cssVars option to turn on MutationObserver).

Therefore, the solution is to determine the UA so that all routes in browsers such as IE can be redirected through the a tag, triggering the re-parsing and execution of 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>
    </>
  )
}

Here, the type of children is ReactElement , rather than ReactNode that is usually supported in slots. This is mainly because we don’t want to consider the situation of directly inserting strings, which will increase the complexity of the problem. Therefore, we directly restrict it at the type level. Fragments are not considered, and no valid Fragments type is found, so it cannot be Omitted in ReactNode. If Fragments are inserted into the first layer, the Link in nextjs cannot jump normally. The possible reason is that it is impossible to bind valid events on Fragments. Currently, Fragments (16.13.1) only support key attributes. I hope it can be optimized later.

Summarize

This is the end of this article about the use of css-vars-ponyfill in the IE environment (nextjs build). For more relevant css-vars-ponyfill usage content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

<<:  Json string + Cookie + localstorage in JS

>>:  Detailed process of FastAPI deployment on Docker

Recommend

Analysis of MySQL latency issues and data flushing strategy process

Table of contents 1. MySQL replication process 2....

Vue implements simple notepad function

This article example shares the specific code of ...

About front-end JavaScript ES6 details

Table of contents 1. Introduction 1.1 Babel Trans...

Detailed explanation of using MySQL where

Table of contents 1. Introduction 2. Main text 2....

MySQL foreign key (FOREIGN KEY) usage case detailed explanation

Introduction: The disadvantages of storing all da...

jQuery simulates picker to achieve sliding selection effect

This article shares the specific code of jQuery t...

4 flexible Scss compilation output styles

Many people have been told how to compile from th...

Using js to implement simple switch light code

Body part: <button>Turn on/off light</bu...

How to use SessionStorage and LocalStorage in Javascript

Table of contents Preface Introduction to Session...

The difference between name and value in input tag

type is the control used for input and output in t...

How to get the height of MySQL innodb B+tree

Preface The reason why MySQL's innodb engine ...

Detailed explanation of Nginx static file service configuration and optimization

Root directory and index file The root directive ...