블로그

vscode는 tw.macro 자동 완성의 꿈을 꾸는가?

서론emotion과 tw.macro로 즐거운 시간을 보내고 있던 어느 날, 여러분은 이상한 점을 발견하게 됩니다.자동 완성에 아무 것도 나타나지 않습니다! 당황한 나머지 익스텐션을 다시 깔아봐도 자동 완성은 꿈쩍도 않습니다.기존의 방식대로 입력을 하니 비로소 제대로 작동합니다.이게 무슨 일인가요? 혹시 얼어 죽어도 class단이 마침내 그 사악한 손길을 자동 완성으로까지 뻗은 건 아닐까요?! 꽤 흥미롭지만, 아닙니다. 해결 방법이 있으니까요.자동 완성을 돌려줘!모든 문제는 공식 tailwindcss 익스텐션이 attributes를 사용하지 않는 상황을 염두하지 않고 만들어져 발생했습니다.tailwindCSS.classAttributes The HTML attributes for which to provide class completions, hover previews, linting etc. Default: class, className, ngClass tailwindCss.classAttribute에 tailwindcss 익스텐션은 HTML attributes에만 자동 완성을 제공합니다. 즉, class=""와 같은 형식에 자동 완성을 제공합니다. 아, 그럼 저기에 tw를 집어넣으면 되지 않겠나고요? 좋은 시도지만 일부분만 해결해 줄 뿐입니다. tw=""은 자동 완성이 되겠지만 emotion을 사용하는 경우는 해결되지 않으니까요.그래서 익스텐션 개발자는 여러 상황에도 자동 완성을 가능하게 만들기 위해서 experimental 설정을 제공했습니다. 이름하야, tailwindCSS.experimental.classRegex입니다.{ ..., "tailwindCSS.experimental.classRegex": [ "tw`([^`]*)", // tw`...` "tw=\"([^\"]*)", // <div tw="..." /> "tw={\"([^\"}]*)", // <div tw={"..."} /> "tw\\.\\w+`([^`]*)", // tw.xxx`...` "tw\\(.*?\\)`([^`]*)" // tw(Component)`...` ] }이 설정은 간단합니다. Regex로 자동 완성의 적용을 원하는 경우를 싹 다 적어서 넣으렴! 이라는거죠.해당 설정을 입맛에 맞게 수정한 다음, vscode의 settings.json에 적어주세요. 이렇게 한다면...우리의 친구 자동 완성이 돌아왔습니다!우리 오래 가자......!TMI도움이 됐나요?그렇다구요? 다행입니다!!오늘도 즐거운 개발이 되셨음 합니다!Reference[Custom class name completion contexts · Issue #7553 · tailwindlabs/tailwindcss · GitHub](https://github.com/tailwindlabs/tailwindcss/issues/7553)      

프론트엔드tailwindcsstwin.macrocompletionsautocompletevscode

nextjs 12에서 emotion과 함께하는 tailwindcss

Nextjs 12 is coming...nextjs 12에서 놀라운 소식이 전해졌습니다. 컴파일러로 swc를 채택했다는 것을요! 여러가지 이유가 있겠지만 가장 중요한 건 기존에 사용하던 babel보다 빌드가 최대 5배나 빨라졌다는 겁니다. 참고로 fast refresh는 최대 3배나 빨라졌다네요!좋은 소식입니다. 하지만 변화에는 언제나 문제가 발생하기 마련입니다. swc를 활성화하기 위해서는 .babelrc와 같은 바벨 설정 파일을 완전히 제거해야 합니다. 이런, 그럼 무조건 바벨을 설정해야 하는 경우는요?그렇습니다. 문제의 발생입니다! 특히 twin.macro을 아끼는 저는 그만 눈물을 닦아낼 수 밖에 없었습니다. 어떤 분께서 이를 대체하는 stailwc를 만들었지만 아직은 이르다는 느낌이 어렴풋이 들고 맙니다. 그렇다면, twin.macro를 포기할 수 밖에 없는 걸까요? 아닙니다!emotionyarn add @emotion/react @emotion/styled or npm install @emotion/react @emotaion/styledemotion을 설치합니다.tailwindcssyarn add tailwindcss or npm install tailwindcss tailwindcss만 설치하면 됩니다.twin.macropackagesyarn 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-reacttwin.macro와 함께 설정에 필요한 babel 관련 패키지를 설치합니다. 상황에 따라 더 늘어날 수도 있습니다.configurationwithTwin.jsconst 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.jsconst withTwin = require("./withTwin"); const nextConfig = withTwin({ // <<- `withTwin` 함수 적용 reactStrictMode: true, swcMinify: true, }); module.exports = nextConfig;작성한 withTwin 함수를 적용해 nextjs를 설정합니다.typestsconfig.json{ ..., "types": [ "@types" ] }타입을 인식할 디렉토리를 설정합니다.@types/twin.d.tsimport "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)

프론트엔드nextjstailwindcssemotionswctwin.macro