Improving CSS Loading in React Applications: Avoiding `@import` in `createGlobalStyle`
Tags: react, styledcomponents, webperf, cssom
Published: 2024-06-17 14:31:20

When working with React and styled-components, you might encounter performance and compatibility issues if you use `@import` within `createGlobalStyle`. This blog post will explain why this happens and how to resolve it by embedding the stylesheet link directly in your `index.html` file.

## The Problem with `@import` in `createGlobalStyle`

Using `@import` in `createGlobalStyle` can lead to several issues:

1. **CSSOM API Limitations**: The CSS Object Model (CSSOM) API, which allows for programmatic manipulation of CSS, has limitations when handling `@import` rules in dynamically created stylesheets. This can cause unexpected behavior or failures in applying styles.

2. **Performance Issues**: `@import` can cause stylesheets to load sequentially, which slows down the page load time. In contrast, using `<link>` tags allows stylesheets to load in parallel, improving performance.

3. **Predictable Load Order**: `<link>` tags ensure that stylesheets are loaded in the order they appear in the HTML, making the application of styles more predictable and easier to manage.

## Solution: Using `<link>` in `index.html`

To avoid these issues, you can move the font import to the `index.html` file. Here’s how you can do it:

### Step 1: Update `index.html`

Add the following `<link>` tag inside the `<head>` section of your `public/index.html` file:

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta name="description" content="Web site created using create-react-app" />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link
      href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100..900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900&display=swap"
      rel="stylesheet"
    />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
```

### Step 2: Update `GlobalStyles.ts`

Remove the `@import` statement from your `GlobalStyles.ts` file:

```typescript
import { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
	margin: 0;
	padding: 0;
	border: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
	display: block;
}
body {
	line-height: 1;
}
ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}
table {
	border-collapse: collapse;
	border-spacing: 0;
}
* {
  box-sizing: border-box;
}
body {
  font-family: "Noto Sans KR", "Roboto", sans-serif;
  background-color: ${(props) => props.theme.bgColor};
  color: ${(props) => props.theme.textColor};
  line-height: 1.2;
}
a {
  text-decoration: none;
  color:inherit;
}
`;

export default GlobalStyle;
```

## Why This Works

### CSSOM API

The CSSOM API allows for programmatic manipulation of CSS stylesheets. However, it has limitations when dealing with `@import` rules in dynamically created stylesheets. By using `<link>` tags, you avoid these limitations and ensure that styles are applied correctly.

### Performance

Using `<link>` tags allows the browser to load stylesheets in parallel, which can significantly improve page load times. This is especially important for web applications that rely on multiple stylesheets.

### Predictable Load Order

With `<link>` tags, stylesheets are loaded in the order they appear in the HTML. This makes it easier to manage and predict the application of styles, reducing the risk of style conflicts and ensuring a more consistent user experience.

## Conclusion

By moving the font import to the `index.html` file and using `<link>` tags instead of `@import` in `createGlobalStyle`, you can avoid compatibility issues with the CSSOM API, improve performance, and ensure a more predictable load order for your stylesheets. This simple change can lead to a more robust and performant React application.