在CodeSandbox上创建React + TailwindCSS + twin.macro环境

The goal

我希望在想要轻松尝试一些实现的时候,不必每次都在本地环境中创建React应用程序,因此我创建了一个云环境上的实验场所。由于在想要轻松尝试时将CSS分开编写也很麻烦,所以我决定使用tailwindcss。因为我担心只使用tailwindcss可能无法满足复杂的布局需求,所以我还引入了twin.macro,使得可以在emotion中编写内联CSS。

CodeSandbox是什么

这是一个在云端上能够创建各种环境的便捷的网站。只需选择模板,即可帮助您创建应用程序,无论是React应用程序,还是Next.js、Vue.js、Node.js等都可选择。就React而言,您可以通过选择模板来实现想要使用vite而不是create-react-app作为构建系统,或者想要引入typescript的需求。

环境

在CodeSandbox上构建以下环境。

React(使用Vite和Typescript)
TailwindCSS
twin.macro

步骤

在CodeSandbox上使用React模板创建应用程序。

スクリーンショット 2023-07-03 011557.png
スクリーンショット 2023-07-03 012101.png
スクリーンショット 2023-07-03 012243.png

用React模板创建应用程序已经完成。

安装TailwindCSS

参考TailwindCSS公式文档并安装TailwindCSS,文档连接https://tailwindcss.com/docs/guides/vite。

スクリーンショット 2023-07-03 012539.png
スクリーンショット 2023-07-03 013001.png

执行完上述命令后,继续执行下一条命令。
运行 npx tailwindcss init -p。

将 tailwind.config.js 文件按照以下方式进行修改。

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

请将index.css文件根据以下方式修改。修改完成后,可能会出现未知的@tailwindcss(unknownAtRules)规则警告,但是不用担心,可以忽略这个警告,没有问题。

@tailwind base;
@tailwind components;
@tailwind utilities;

现在TailwindCSS的安装已经完成,请将App.tsx文件适当修改,以确认是否应用了TailwindCSS。

function App() {
  return (
    <div
      className="w-48 h-48 bg-black"
    />
  );
}

export default App;
スクリーンショット 2023-07-03 013639.png
スクリーンショット 2023-07-03 013817.png

TailwindCSS的安装已完成。下一步是安装twin.macro。

安装 twin.macro

我已参考了以下文章:
https://osu-log.com/archives/975#toc2

首先,安装twin.macro。

yarn add @emotion/react @emotion/styled
yarn add --dev twin.macro @emotion/babel-plugin-jsx-pragmatic babel-plugin-macros tailwindcss -D

接下来在src文件夹中创建GlobalStyles.tsx,并开始编写其内容。

import React from 'react'
import { css, Global } from '@emotion/react'
import tw, { theme, GlobalStyles as BaseStyles } from 'twin.macro'

const customStyles = css({
  body: {
    WebkitTapHighlightColor: theme`colors.purple.500`,
    ...tw`antialiased`,
    // グローバルスタイルをカスタマイズしたいなら、ここに追記していく
  },
})

const GlobalStyles = () => (
  <>
    <BaseStyles />
    <Global styles={customStyles} />
  </>
)

export default GlobalStyles

接下来,从src/main.tsx中导入创建的GlobalStyles.tsx。

import React from 'react'
import ReactDOM from 'react-dom/client'
import GlobalStyles from './GlobalStyles' // この文を追記
import App from './App'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <GlobalStyles /> // この文を追記
    <App />
  </React.StrictMode>
)

请编辑vite.config.js文件,将twin.macro插件添加到vite中。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          'babel-plugin-macros',
          [
            '@emotion/babel-plugin-jsx-pragmatic',
            {
              export: 'jsx',
              import: '__cssprop',
              module: '@emotion/react',
            },
          ],
          [
            '@babel/plugin-transform-react-jsx',
            { pragma: '__cssprop' },
            'twin.macro',
          ],
        ],
      },
    }),
  ],
  esbuild: {
    logOverride: { 'this-is-undefined-in-esm': 'silent' }
  },
});

最后进行Typescript的设置。创建src/types/twin.d.ts文件,并写入以下内容。

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

declare module 'twin.macro' {
  // The styled and css imports
  const styled: typeof styledImport
  const css: typeof cssImport
}

declare module 'react' {
  // The css prop
  interface HTMLAttributes<T> extends DOMAttributes<T> {
    css?: CSSInterpolation
    tw?: string
  }
  // The inline svg css prop
  interface SVGProps<T> extends SVGProps<SVGSVGElement> {
    css?: CSSInterpolation
    tw?: string
  }
}

在tsconfig.json文件中添加以下内容。

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "jsxImportSource": "@emotion/react" << この一行を追記
  },
  "include": ["src"],
  "references": [
    {
      "path": "./tsconfig.node.json"
    }
  ]
}

完成了twin.macro的配置。最后,确认twin.macro是否正确应用了。

import tw, { css } from "twin.macro";
import "./App.css";

function App() {
  return (
    <div
      tw="w-48 h-48 bg-black"
      css={css`
        box-shadow: 10px 5px 5px red;
      `}
    ></div>
  );
}

export default App;
スクリーンショット 2023-07-03 015606.png

我希望能够充分利用React,以及当我有一些想尝试或想制作的东西时,能够更好地与它相处。感谢那些已经实践过这些步骤的人辛苦了。

bannerAds