常見問題

我需要做些什麼才能遷移到 v6?

首先,讓我們將必要的套件更新到最新版本。

如果您使用的是 NPM

npm install styled-components@^6.0.0 stylis@^4.0.0
npm uninstall @types/styled-components

如果您使用的是 Yarn

yarn add styled-components@^6.0.0 stylis@^4.0.0
yarn remove @types/styled-components

由於 styled-components 現在提供自己的類型,因此不再需要社群類型。

TypeScript

好消息!現在 styled-components 是使用 TypeScript 原生編寫的!即使您以前沒有使用過 TypeScript,也建議使用它來提高專案的可靠性,因為當您使用未知的 prop 或 prop 的值與預期不同時,它可以提醒您。

但是,如果您在專案中沒有使用 TypeScript,也不用擔心!像 VS Code 這樣的 IDE 仍然會擷取類型並在您編寫程式碼時提供提示。

shouldForwardProp 預設不再提供

如果您尚未將樣式遷移到使用暫時性 props ($prefix),您可能會注意到在 v6 中 React 關於樣式 props 傳遞到 DOM 的警告。 要恢復 v5 行為,請使用 StyleSheetManager

import isPropValid from '@emotion/is-prop-valid';
import { StyleSheetManager } from 'styled-components';


function MyApp() {
    return (
        <StyleSheetManager shouldForwardProp={shouldForwardProp}>
            {/* other providers or your application's JSX */}
        </StyleSheetManager>
    )
}


// This implements the default behavior from styled-components v5
function shouldForwardProp(propName, target) {
    if (typeof target === "string") {
        // For HTML elements, forward the prop if it is a valid HTML attribute
        return isPropValid(propName);
    }
    // For other elements, forward all props
    return true;
}

供應商前綴預設省略

由於網路和瀏覽器在 2023 年已顯著成熟,因此供應商前綴通常是不必要的。 因此,對於 v6 版本,我們決定預設省略自動前綴,以減少傳遞到頁面的 CSS 量。 如果您喜歡 v5 行為,您可以透過 StyleSheetManager 還原它。

import { StyleSheetManager } from 'styled-components';


function MyApp() {
    return (
        <StyleSheetManager enableVendorPrefixes>
            {/* other providers or your application's JSX */}
        </StyleSheetManager>
    )
}

為了適應這種變化,原始的 disableVendorPrefixes prop 已反轉為 enableVendorPrefixes;如果您已設定 disableVendorPrefixes,則現在可以將其刪除,因為它是新的預設值。

更新 stylis 插件

styled-components v6 使用更新的 stylis v4;如果您向 StyleSheetManager 提供 stylisPlugins,請確保插件是最新的。 例如,stylis-plugin-rtl 發布了一個新版本以支援更新的 stylis。

嵌套語法處理

隨著 stylis v4 的升級,嵌套選擇器的處理方式發生了變化,現在可以正確地反映瀏覽器行為。 具體來說,不以 & 開頭的偽選擇器(例如 :before)將不再隱式添加「&」符號。

v5 行為

styled.div`
  :hover { color: red; }
`
// .[classname]:hover { color: red; }


styled.div`
  &:hover { color: red; }
`
// .[classname]:hover { color: red; }

v6 行為

styled.div`
  :hover { color: red; }
`
// .[classname] :hover { color: red; } (equivalent to .[classname] *:hover)


styled.div`
  &:hover { color: red; }
`
// .[classname]:hover { color: red; }

已捨棄暫時性 $as$forwardedAs props

為了減少應用順序的混淆,我們捨棄了暫時性 $as$forwardedAs props。 請改用常規的 asforwardedAs props。

已捨棄舊版 withComponent() API

這個變更已經很久了。 不再支援 withComponent API,請改用 as prop。 您可以透過 attrs 在定義時或在執行時指定 as

import styled from 'styled-components';


const Button = styled.button`
    background: blue;
    color: white;
`;


const ButtonLink = styled(Button).attrs({ as: 'a' })``;


// These are equivalent, but `ButtonLink` allows for attaching further styling if desired.
<Button as="a" href="https://styled-components.dev.org.tw">
<ButtonLink href="https://styled-components.dev.org.tw">

最低 Node 支援提高到 v16+

根據 Node 的維護排程,我們現在支援 v16 作為仍在接收安全修補程式的最舊執行階段。

我需要做些什麼才能遷移到 v5?

準備好了嗎?

npm install styled-components@^5.0.0 react@^16.8 react-dom@^16.8 react-is@^16.8

如果您使用的是 React Native,您將至少需要 v0.59(第一個支援 hooks 的版本。)

就這樣。 💥


styled-components v5 沒有引入任何破壞性的公共 API 變更,並添加了以下內容

  • 核心樣式表引擎的全面重寫,針對效能進行調整

  • 新的基於 hooks 的組件模型

  • StyleSheetManager 有新的 props

    • disableCSSOMInjection
    • disableVendorPrefixes
    • stylisPlugins
備註

注意:v4 中已棄用的子函數物件形式語法 .attrs({ prop: props => {} }) 在 v5 中已移除。請改用函數形式的 attrs .attrs(props => ({}))(您應該已經看到主控台警告,以便提前進行此更新。)

查看官方公告文章以了解更多資訊,並了解 v5 的內容!

給 Jest 使用者

更新至 jest-styled-components v7

npm install jest-styled-components@^7.0.0

關於 css @importcreateGlobalStyle 的注意事項

目前,由於瀏覽器透過 CSSOM API 處理 @import 的方式存在一些問題,我們不建議在 cGS 中使用 @import。最好將它們放在核心 index.html 檔案(生成的或靜態的)中,放在一個典型的 <style> 標籤內。

我需要做些什麼才能遷移到 v4?

這是一個相當大的版本,底層和 API 層面都有很多變化。隨著 Beta 版的推進,我們將嘗試發布程式碼修改工具,以簡化以下項目。此外,如果您發現以下步驟有任何問題,請留下建設性的意見

  1. 升級到最新的 styled-components
npm install styled-components@^4.0.0
  1. 確保您的應用程式使用 react >= 16.3;我們在內部使用了新的 React.forwardRef API 和新的 context API,如果您想嘗試為舊版 React 版本提供 polyfill 的話。
npm install react@^16.3 react-dom@^16.3
備註

如果您使用的是 enzyme 或其他依賴項,例如 react-test-renderer,如果您使用的是舊版本的 react,則可能需要完成更多相關的升級。

  1. 如果您正在使用 .extend API,請將您的組件切換為使用 styled(StyledComponent)

可以使用程式碼修改工具來加速此過程。

🚫

import styled from 'styled-components'


const Component = styled.div`
  background: blue;
  color: red;
`


const ExtendedComponent = Component.extend`
  color: green;
`

import styled from 'styled-components'


const Component = styled.div`
  background: blue;
  color: red;
`


const ExtendedComponent = styled(Component)`
  color: green;
`

請參閱「擴展樣式」文件以了解更多範例。

  1. 如果您使用 injectGlobal API 將全域樣式添加到您的頁面,請改用新的createGlobalStyle 輔助組件

可以使用程式碼修改工具來加速此過程。

🚫

import { injectGlobal } from 'styled-components'


injectGlobal`
  body {
    color: red;
  }
`

import { createGlobalStyle } from "styled-components"


const GlobalStyle = createGlobalStyle`
  body {
    color: red;
  }
`


// later in your app's render method
<React.Fragment>
  <Navigation />
  <OtherImportantTopLevelComponentStuff />
  <GlobalStyle />
</React.Fragment>

請參閱createGlobalStyle 的文件,了解您可以使用它 انجام哪些以前使用 injectGlobal 無法做到的事情!

  1. 如果您使用的是 innerRef prop,請將其更改為普通的 ref

🚫

const Component = styled.div`
  background: blue;
  color: red;
`


// later in your render method
<Component innerRef={element => { this.myElement = element }}>Something something</Component>

const Component = styled.div`
  background: blue;
  color: red;
`


// later in your render method
<Component ref={element => { this.myElement = element }}>Something something</Component>
  1. 如果您在沒有 css 輔助函數的情況下,在部分組件中使用 keyframes 組件,則現在需要使用輔助函數。一般來說,在組合樣式部分以插入到樣式化組件時,請始終使用 css 輔助函數。

🚫

import styled, { keyframes } from 'styled-components'


const animation = keyframes`
  0% {
    opacity: 0;
  }


  100 {
    opacity: 1;
  }
`


const animationRule = `
  ${animation} 1s infinite alternate
`


const Component = styled.div`
  animation: ${animationRule};
`

import styled, { css, keyframes } from 'styled-components'


const animation = keyframes`
  0% {
    opacity: 0;
  }


  100 {
    opacity: 1;
  }
`


const animationRule = css`
  ${animation} 1s infinite alternate;
`


const Component = styled.div`
  animation: ${animationRule};
`
  1. 如果您正在使用 attrs({}) 而且您傳遞給它的一些屬性是函數,建議您切換到新的 attrs(props => ({})) 語法,以便更容易、更強大的組合。

🚫

import styled from 'styled-components'


const Input = styled.input.attrs({
  type: props => props.inputType,
})`
  background: blue;
  color: red;
`

import styled from 'styled-components'


const Input = styled.input.attrs(props => ({
  type: props.inputType,
}))`
  background: blue;
  color: red;
`
  1. 如果您使用的是 TypeScript,現在可以在 DefinitelyTyped 中找到類型定義。
npm install @types/styled-components

就這樣!除了遷移之外,我們還強烈建議您閱讀新的"as" prop,它旨在將來取代withComponent API

我可以嵌套規則嗎?

可以:嵌套是從 Sass 故意移植過來的功能。少量使用它可以減少為每個元素創建顯式類別的需求,從而減輕程式碼的負擔。

父組件也可以使用它來定義上下文約束,而這些約束並非受影響子組件的真正關注點。

First
Second
Third
First
Second
Third

同時定位媒體查詢也非常方便,因為我們可以一目了然地看到組件在任何解析度下的反應。

Hello world!

我可以使用 CSS 框架嗎?

將現有的 CSS 框架與 styled-components 集成非常容易!您可以將其現有的類別名稱與您的組件一起使用。

例如,假設您有一個現有的應用程式,其中包含兩個您想再次使用的類別:.small.big。如果您希望該類別始終附加到組件,則應使用attrs 方法來附加它。如果您只想在某些情況下附加它,您可以像往常一樣使用 className props!

如果框架有一堆需要包含在頁面上的原始全域 CSS,您可以使用createGlobalStyle API新增它。這也適用於 CSS 重置等。

備註

請注意,對於 styled-components v3 及以下版本,以前的全域樣式 API 是injectGlobal

如何使用更高的特異性覆蓋樣式?

使用高特異性覆蓋樣式的方法很簡單,就是提高您自己樣式的特異性。這可以使用 !important 來完成,但這容易出錯,通常不是一個好主意。

我們建議使用以下技巧

const MyStyledComponent = styled(AlreadyStyledComponent)`
  &&& {
    color: #BF4F74;
    font-weight: bold;
  }
`

每個 & 都會被生成的類別取代,因此注入的 CSS 看起來像這樣

.MyStyledComponent-asdf123.MyStyledComponent-asdf123.MyStyledComponent-asdf123 {
  color: #BF4F74;
  font-weight: bold;
}

重複的類別將特異性提高到足以覆蓋原始順序,而編寫起來並不太繁瑣!

如何覆蓋內聯樣式?

內聯樣式始終優先於外部 CSS,因此您不能僅僅透過提高特異性來覆蓋它。

然而,有一個巧妙的技巧,那就是將樣式 element-attr CSS 選擇器與 !important 結合使用

const MyStyledComponent = styled(InlineStyledComponent)`
  &[style] {
    font-size: 12px !important;
    color: blue !important;
  }
`

為什麼我的 DOM 節點有兩個類別?

每個節點實際上都連接著兩個類別:一個是每個組件的靜態類別,這意味著樣式化組件的每個元素都具有此類別。它沒有附加任何樣式。相反,它用於快速識別 DOM 物件屬於哪個樣式化組件,或在開發工具中進行少量更改。它也用於組件選擇器。靜態類別可能看起來像這樣:.sc-fVOeaW

另一個是動態的,這意味著根據插值結果的不同,樣式化組件的每個元素在不同的 props 下都會有所不同。它可能看起來像 .fVOeaW(注意缺少「sc」前綴。)

例如,樣式化組件 <Button /> 每次都會以相同的靜態類別呈現。如果使用插值更改樣式,例如 <Button secondary />,則動態類別將是不同的,而靜態類別將保持不變。

何時使用 attrs?

您可以使用 attrs 將屬性傳遞給樣式化組件,但並非總是合理的做法。

經驗法則是,當您希望樣式化組件的每個實例都具有該屬性時,使用 attrs;而當每個實例需要不同的屬性時,則直接傳遞屬性

const PasswordInput = styled.input.attrs(props => ({
  // Every <PasswordInput /> should be type="password"
  type: "password"
}))``


// This specific one is hidden, so let's set aria-hidden
<PasswordInput aria-hidden="true" />

這同樣適用於可以根據另一個屬性的「模式」推斷出的屬性。在這種情況下,您可以將 attrs 上的屬性設定為一個函式,該函式根據其他屬性計算該屬性。

我是一位函式庫作者。我應該將 styled-components 與我的函式庫捆綁在一起嗎?

如果您是函式庫作者,我們建議您不要將 styled-components 模組與您的函式庫捆綁並發佈。要做到這一點,您需要執行兩個步驟

  • 在您的套件依賴項中將 styled-components 標記為外部依賴項
  • 從您的函式庫捆綁包中移除 styled-components

在您的套件依賴項中將 styled-components 標記為外部依賴項

為此,您需要將其從 dependencies 移至 devDependencies,並將其包含在您的 package.json 檔案中的 peerDependencies 列表中。

{
-   "dependencies" : {
+   "devDependencies" : {
      "styled-components": "^3.4.9"
    },
+   "peerDependencies" : {
+     "styled-components": ">= 3"
+   }
  }

styled-components 移至 devDependencies 將確保它不會與您的函式庫一起安裝(安裝函式庫時,npm installyarn add 會忽略 devDependencies)。

styled-components 新增至 peerDependencies 將向您的函式庫使用者發出訊號,表明 styled-components 未包含在函式庫中,他們需要自行安裝。

另外,請注意,在 peerDependencies 部分中,版本字串已設為更寬鬆的 >= 3。這允許未來版本的 styled-components 自動運作,如果最終新增了重大變更,您可以簡單地通過對您的函式庫進行修補更新來縮小範圍。

從您的函式庫捆綁包中移除 styled-components

如果您在發佈函式庫之前將其捆綁,請確保您沒有將 styled-components 與其捆綁在一起。以下是一些如何使用一些流行的模組捆綁工具執行此操作的範例

使用 Microbundle

如果您使用的是 Microbundle,它將自動處理此步驟。Microbundle 將 peerDependencies 列表中的每個依賴項都視為外部依賴項,並將其從構建中排除。

使用 Rollup.js

如果您使用的是 Rollup.js,您應該在您的配置中提供一個 external 選項

export default {
    entry: "my-awesome-library.js",
+   external: [
+     "styled-components"
+   ]
  }

另一種方法是使用 rollup-plugin-peer-deps-external 插件,它將自動為您將 peerDependencies 新增到 external 選項陣列中。

+ import peerDepsExternal from 'rollup-plugin-peer-deps-external';

  export default {
    entry: "my-awesome-library.js",
+   plugins: [
+    // Preferably set as first plugin.
+    peerDepsExternal(),
+   ]
  }

使用 Webpack

如果您使用的是 Webpack,您應該在您的配置中提供一個 externals 選項

modules.export = {
    entry: "my-awesome-library.js",
+   externals: {
+     "styled-components": {
+       commonjs: "styled-components",
+       commonjs2: "styled-components",
+       amd: "styled-components",
+     },
+   },
  }
備註

您可以在 Webpack 文件的 「撰寫函式庫」 部分找到更多關於如何使用 Webpack 捆綁函式庫的有用資訊。

為什麼我會收到關於頁面上有多個模組實例的警告?

如果您在控制台中看到如下所示的警告訊息,則您的頁面上可能初始化了多個 styled-components 實例。

It looks like there are several instances of "styled-components" initialized in this application. This may cause dynamic styles not rendering properly, errors happening during rehydration process and makes you application bigger without a good reason.


If you are using a building tool like webpack, consider checking your bundle for duplication of the "styled-components" module.

如果您使用伺服器端渲染,這可能會導致動態樣式無法正常工作,甚至在重新水合過程中出錯。

可能的原因

發生這種情況有幾個常見原因

  • 您在同一個頁面上運行了多個使用 styled-components 的應用程式(例如,webpack 中的多個入口點都載入了同一個頁面)
  • 您的依賴項中還有另一個 styled-components 函式庫
  • 您的專案採用 monorepo 結構(例如,lerna、yarn workspaces),並且 styled-components 模組在多個套件中都是依賴項(這或多或少與前一個原因相同)

在一個頁面上運行多個應用程式

如果您在一個頁面上運行了多個應用程式,請考慮為所有應用程式使用一個 styled-components 模組。如果您使用的是 webpack,則可以使用 CommonsChunkPlugin 建立一個 明確的供應商區塊,其中將包含 styled-components 模組

module.exports = {
    entry: {
+     vendor: ["styled-components"],
      app1: "./src/app.1.js",
      app2: "./src/app.2.js",
    },
    plugins: [
+     new webpack.optimize.CommonsChunkPlugin({
+       name: "vendor",
+       minChunks: Infinity,
+     }),
    ]
  }

node_modules 中的重複模組

如果您認為問題出在依賴項中某處的重複 styled-components 模組,則可以使用多種方法檢查這一點。您可以在應用程式資料夾中使用 npm ls styled-componentsyarn list --pattern styled-componentsfind -L ./node_modules | grep /styled-components/package.json 命令。

如果以上指令都無法找出重複項目,請嘗試分析您的 bundle 中是否有多個 styled-components 實例。您可以直接檢查 bundle 原始碼,或使用像是 source-map-explorerwebpack-bundle-analyzer 等工具。

如果您確認重複項目是您遇到的問題,您可以嘗試以下幾種方法來解決它

如果您使用的是 npm,您可以嘗試執行 npm dedupe 指令。這個指令會搜尋本地端的 dependencies,並嘗試將共同的 dependencies 移到目錄樹的上層來簡化結構。

備註

請注意,npm dedupe 指令在處理符號連結資料夾(例如,當您使用 npm link 時)的效果不佳。

如果您使用的是 webpack,您可以更改它 解析 styled-components 模組的方式。您可以覆寫 webpack 搜尋 dependencies 的預設順序,讓您的應用程式 node_modules 的優先順序高於預設的 node 模組解析順序。

resolve: {
+   alias: {
+     "styled-components": path.resolve(appFolder, "node_modules", "styled-components"),
+   }
  }

在 Lerna 中使用

要讓 styled-components 在 Lerna monorepo 中跨套件運作,一個可能的解決方法是將共用的 dependencies 提升 (hoist) 到 monorepo 根目錄。嘗試使用 `--hoist` 旗標執行 bootstrap 選項。

lerna bootstrap --hoist

或者,您可以從 package.json 檔案中移除 styled-components,並手動將其提升到頂層的 package.json 檔案中。

Lerna 根資料夾中 package.json 檔案的範例

{
  "name": "my-styled-monorepo",
  "devDependencies": {
    "lerna": "3.6.0"
  },
  "dependencies": {
    "styled-components": "3.4.5"
  },
  "scripts": {
    "bootstrap": "lerna bootstrap",
    "clean": "lerna clean",
    "start": "lerna run start",
    "build": "lerna run build"
  }
}

為什麼應該避免在 render 方法中宣告 styled components?

在 React 元件的 render 方法中宣告 styled component,會在每次渲染時動態建立一個新的元件。這表示 React 必須在每次後續渲染時捨棄並重新計算 DOM 子樹的該部分,而不是僅計算它們之間差異。這會導致效能瓶頸和不可預測的行為。

🚫

const Header = () => {
  const Title = styled.h1`
    font-size: 10px;
  `


  return (
    <div>
      <Title />
    </div>
  )
}

const Title = styled.h1`
  font-size: 10px;
`


const Header = () => {
  return (
    <div>
      <Title />
    </div>
  )
}

為什麼我會收到 HTML 屬性警告?

以下警告訊息表示非標準屬性正被附加到 HTML DOM 元素,例如 <div><a>。如果您看到此警告訊息,則可能是您或您正在使用的程式庫將 props 作為屬性附加到 HTML DOM 元素。

Warning: Received "true" for a non-boolean attribute

如果您看到此警告,您可能在應該使用 "true" 的地方傳遞了 true。這很可能來自 .attrs 屬性,或者來自您傳遞給 styled(Component) 元件的完全不相關的 prop。

要瞭解更多關於 props 如何傳遞的資訊,請參閱此章節

例如

const Link = props => (
  <a {...props} className={props.className}>
    {props.text}
  </a>
)


const StyledComp = styled(Link)`
  color: ${props => (props.red ? 'red' : 'blue')};
`


<StyledComp text="Click" href="https://www.styled-components.com/" red />

這將會渲染

<a text="Click" href="https://www.styled-components.com/" red="true" class="[generated class]">Click</a>

React 會針對附加的非標準屬性發出警告,例如 "red" 和 "text",這些屬性對於 <a> 元素而言不是有效的 HTML 屬性。

要解決此問題,您可以使用 transient props 或解構 props

transient props(自 5.1 版起)

您可以使用 transient props 來解決此問題

const Link = ({ className, text, ...props }) => (
  <a {...props} className={className}>
    {text}
  </a>
)


const StyledComp = styled(Link)`
  color: ${props => (props.$red ? 'red' : 'blue')};
`


<StyledComp text="Click" href="https://www.styled-components.com/" $red />

解構 props

如果您使用的版本低於 5.1 或無法使用 transient props,您可以使用參數解構來拉出那些已知的樣式 props

const Link = ({ className, red, text, ...props }) => (
  <a {...props} className={className}>
    {text}
  </a>
)


const StyledComp = styled(Link)`
  color: ${props => (props.red ? 'red' : 'blue')};
`


<StyledComp text="Click" href="https://www.styled-components.com/" red />

這將會渲染

<a href="https://www.styled-components.com/" class="[generated class]">Click</a>

當您使用參數解構時,從 props 物件中拉出的任何變數將不會包含在展開套用剩餘 props (...props) 時;

支援哪些瀏覽器?

styled-components 支援與目前 React 版本相同的瀏覽器。

  • v2.x (React v0.14+):IE9+,所有 Evergreen 瀏覽器
  • v3.x (React v0.14+):IE9+,所有 Evergreen 瀏覽器
  • v4.x (React v16.3+):IE11,IE 9+ (搭配 Map + Set polyfills),所有 Evergreen 瀏覽器
  • v5.x (React v16.3+):IE11,所有 Evergreen 瀏覽器

Evergreen 瀏覽器包含 Chrome 和 Firefox(及其衍生版本),因為它們可以更新,不受作業系統版本限制。 Edge 和 Safari 也應該可以正常運作,因為過去幾年的所有版本都支援相關的 API。

如何搭配 create-react-app 使用 styled-components?

程式庫的基本功能應該可以像其他程式庫一樣開箱即用。

但是,如果您想進行伺服器端渲染或利用 styled-components babel 插件 的一些進階功能而不需 eject,則需要設定 react-app-rewiredreact-app-rewire-styled-components

使用 npm linkyarn link 時,如何解決問題?

本地連結是同時協作開發專案的 útil 工具。然而,它會為像是 React 和 styled-components 這種應該以單例模式使用的程式庫,創造出混亂的局面,因為您的每個本地專案可能都下載了一整套開發 dependencies(而且 bundler 預設會優先使用本地版本的 dependencies)。

解決方案是新增別名。以下是一個 webpack 的設定範例

// const path = require('path');


{
  resolve: {
    alias: {
      // adjust this path as needed depending on where your webpack config is
      'styled-components': path.resolve('../node_modules/styled-components')
    }
  }
}

這可確保您的建置始終使用程式庫的相同副本,即使是跨符號連結的專案也是如此。

在 SSR 情境下連結

如果您在具有連結元件的專案上使用 collectStyles 函式,您將會遇到複雜的情況。基本上,由於 v4 新的靜態 context API,不同的 styled-component 模組現在管理自己的 styled-components 列表來渲染,從主應用程式看來,似乎沒有任何東西可以提取,因為在該作用域中沒有建立任何 styled components,它們是從連結的套件作用域建立的。

我该如何解决?

一種解決方案是在 styled-components 模組路徑解析中新增一個別名,使其始終指向「主」應用程式。幸運的是,有很多程式庫可以做到這一點,我們將在此範例中使用 module-alias。在您的 SSR 索引檔案的最頂端新增

const path = require('path');
const moduleAlias = require('module-alias');


moduleAlias.addAlias('styled-components', path.join(__dirname, '../node_modules/styled-components'));

這會告知 node 將所有 styled-components 的 import/require 解析為 __dirname, '../node_modules/styled-components'

如何在伺服器端渲染後修復文字閃爍問題?

當使用像是 createGlobalStyle 或以前的 injectGlobal 等全域樣式 API 時,在 DOM 中新增和移除某些樣式(例如 @font-face 定義)可能會導致頁面上的文字 momentarily 閃爍。這通常發生在伺服器端渲染的注水階段。我們仍在調整這些行為的運作方式,以長期避免此問題。

但是,在 font-display CSS 規則 中有一個 CSS 解決方案可以解決此問題。藉由將規則設定為「fallback」模式,一旦載入字型後,就不會再次載入。這可以消除閃爍問題。

@font-face {
  font-family: 'Foo';
  src: url('/path/to/foo.woff') format('woff');
  font-style: normal;
  font-weight: 400;
  font-display: fallback; /* <- this can be added to each @font-face definition */
}

缺少 styled-components/native 的宣告?

如果您收到錯誤訊息

Could not find a declaration file for module 'styled-components/native'

在使用 TypeScript 的 React Native 專案中,這是因為您需要新增 @types/styled-components-react-native