nextjs 12에서 emotion과 함께하는 tailwindcss

Nextjs 12 is coming...

nextjs 12에서 놀라운 소식이 전해졌습니다. 컴파일러로 swc를 채택했다는 것을요! 여러가지 이유가 있겠지만 가장 중요한 건 기존에 사용하던 babel보다 빌드가 최대 5배나 빨라졌다는 겁니다. 참고로 fast refresh는 최대 3배나 빨라졌다네요!

좋은 소식입니다. 하지만 변화에는 언제나 문제가 발생하기 마련입니다. swc를 활성화하기 위해서는 .babelrc와 같은 바벨 설정 파일을 완전히 제거해야 합니다. 이런, 그럼 무조건 바벨을 설정해야 하는 경우는요?

그렇습니다. 문제의 발생입니다! 특히 twin.macro을 아끼는 저는 그만 눈물을 닦아낼 수 밖에 없었습니다. 어떤 분께서 이를 대체하는 stailwc를 만들었지만 아직은 이르다는 느낌이 어렴풋이 들고 맙니다. 그렇다면, twin.macro를 포기할 수 밖에 없는 걸까요? 아닙니다!

emotion

yarn add @emotion/react @emotion/styled

or

npm install @emotion/react @emotaion/styled

emotion을 설치합니다.

tailwindcss

yarn add tailwindcss

or

npm install tailwindcss

 tailwindcss만 설치하면 됩니다.

twin.macro

packages

yarn add twin.macro babel-loader babel-plugin-macros @babel/plugin-syntax-typescript @babel/preset-react

or

npm install twin.macro babel-loader babel-plugin-macros @babel/plugin-syntax-typescript @babel/preset-react

twin.macro와 함께 설정에 필요한 babel 관련 패키지를 설치합니다. 상황에 따라 더 늘어날 수도 있습니다.

configuration

withTwin.js

const path = require("path");

const includedDirs = [
  path.resolve(__dirname, "components"),
  path.resolve(__dirname, "pages"),
  path.resolve(__dirname, "styles"),
];

module.exports = function withTwin(nextConfig) {
  return {
    ...nextConfig,
    webpack(config, options) {
      const { dev, isServer } = options;
      config.module = config.module || {};
      config.module.rules = config.module.rules || [];
      config.module.rules.push({
        test: /\.(tsx|ts)$/,
        include: includedDirs,
        use: [
          options.defaultLoaders.babel,
          {
            loader: "babel-loader",
            options: {
              sourceMaps: dev,
              presets: [
                [
                  "@babel/preset-react",
                  { runtime: "automatic", importSource: "@emotion/react" },
                ],
              ],
              plugins: [
                require.resolve("babel-plugin-macros"),
                require.resolve("@emotion/babel-plugin"),
                [
                  require.resolve("@babel/plugin-syntax-typescript"),
                  { isTSX: true },
                ],
              ],
            },
          },
        ],
      });

      if (!isServer) {
        config.resolve.fallback = {
          ...(config.resolve.fallback || {}),
          fs: false,
          module: false,
          path: false,
          os: false,
          crypto: false,
        };
      }

      if (typeof nextConfig.webpack === "function") {
        return nextConfig.webpack(config, options);
      } else {
        return config;
      }
    },
  };
};

babel 설정 파일을 대신해 babel을 설정합니다.

next.config.js

const withTwin = require("./withTwin");

const nextConfig = withTwin({		// <<- `withTwin` 함수 적용
  reactStrictMode: true,
  swcMinify: true,
});

module.exports = nextConfig;

작성한 withTwin 함수를 적용해 nextjs를 설정합니다.

types

tsconfig.json

{
  ...,
  "types": [
    "@types"
  ]
}

타입을 인식할 디렉토리를 설정합니다.

@types/twin.d.ts

import "twin.macro";
import { css as cssImport } from "@emotion/react";
import styledImport from "@emotion/styled";
import { CSSInterpolation } from "@emotion/serialize";

// `twin.macro`에 다음 타입을 넣음
declare module "twin.macro" {
  const styled: typeof styledImport;
  const css: typeof cssImport;
}

// DOM의 attribute에 다음 타입을 넣음
declare module "react" {
  interface DOMAttributes<T> {
    tw?: string;
    css?: CSSInterpolation;
  }
}

twin.macro와 관련된 타입을 설정합니다.

TMI

사용하고 있는 tailwindcss에 적용할 수 있나요?

네, class로 tailwindcss를 사용하고 있더라도 설치, 설정을 통해 twin.macro를 사용할 수 있습니다.

왜 css 관련 설정을 하지 않나요?

twin.macro는 입력받은 클래스들을 독립적으로 사용 가능한 css로 변환합니다. 따로 정의된 css의 도움을 받지 않고서요.

이 때 변환은 twin.macro로 이뤄집니다. class로도 tailwindcss를 사용해야 한다면 css 설정을 거쳐야 합니다.

도움이 됐나요?

됐다구요? 다행입니다!

즐거운 개발이 되길 바랄게요!

reference

[GitHub - ben-rogerson/twin.macro: 🦹‍♂️ Twin blends the magic of Tailwind with the flexibility of css-in-js (emotion, styled-components, stitches and goober) at build time.](https://github.com/ben-rogerson/twin.macro)

[Enable SWC on next examples · ben-rogerson/twin.examples@36ac8c6 · GitHub](https://github.com/ben-rogerson/twin.examples/commit/36ac8c6dcfa80fcf9cfd65b5c4835b8f3aa79c00#diff-8e7430aee7d110ee12e0366c43b2e8328e0eae8fe870a88eae4bbb7532ec26e1)

[Support SWC · Discussion #516 · ben-rogerson/twin.macro · GitHub](https://github.com/ben-rogerson/twin.macro/discussions/516)

[How to config Nextjs for Babel Plugin Macros like twin.macro without disabling swc complier](https://blog.mrcatdev.com/how-to-config-nextjs-for-babel-plugin-macros-like-twinmacro-without-disabling-swc-compiler)

댓글을 작성해보세요.

  • ina mojae
    ina mojae

    덕분에 프로젝트에 손쉽게 tw.macro 세팅 마쳤습니다. 감사해요!