์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- emtion app router
- ๋ฐฑ์ค 1339๋ฒ js
- emotion RSC
- ํ๋ก๊ทธ๋๋จธ์ค ๋ฌธ์์ด ์์ถ
- ๋ฐฑ์ค 1339๋ฒ ์๋ฐ์คํฌ๋ฆฝํธ
- js
- ์๋ฐ์คํฌ๋ฆฝํธ ์ค์ฝํ
- ํ๋ก๊ทธ๋๋จธ์ค ๊ฑฐ๋ฆฌ๋๊ธฐ ํ์ธํ๊ธฐ
- js ๊ฑฐ๋ฆฌ๋๊ธฐ ํ์ธํ๊ธฐ
- ๋ฐฑ์ค 2108 ์๋ฐ์คํฌ๋ฆฝํธ
- ์นด์นด์ค ์ฝํ
- suspense ๋น๋๊ธฐ
- js ์ค์ฝํ
- ์ต์ ๋์ฒด์ด๋
- ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ์์ด ์์ถ
- suspense ๋์์๋ฆฌ
- suspense react-query
- ๊ตฌ๋ฆํค ์ฑ๋ฆฐ์ง
- TypeError: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more:
- ๋ฆฌ์กํธ์ฟผ๋ฆฌ suspense
- ๋ฐฑ์ค 1339๋ฒ nodejs
- suspense ๋ณ๋ชฉํ์
- next13 emotion
- ์ค์ฝํ
- js ๋ฌธ์์ด ์์ถ
- ๋ฐฑ์ค 2108 nodejs
- ๊ตฌ๋ฆํค ์ฑ๋ฆฐ์ง ํ๊ณ
- app router emotion
- ๊ตฌ๋ฆํค
- ์ฌ์ฉ์ฑ ๊ฐ์
- Today
- Total
Lennon FE
[Next.js 13] Emotion์ผ๋ก app router RSC๋ฅผ ๊ตฌ์ฑํด๋ณด์ ๋ณธ๋ฌธ
[Next.js 13] Emotion์ผ๋ก app router RSC๋ฅผ ๊ตฌ์ฑํด๋ณด์
Lennon 2023. 7. 17. 23:28Next13์ app router ๋ฐฉ์์์ ํ์ฌ Emotion์ ๊ณต์์ ์ผ๋ก ์ง์ํด์ฃผ์ง ์๋๋ค.๐ฅฒ
๊ทธ๋ ์ง๋ง Project์์ Emotion lib๋ฅผ ์ฌ์ฉํ๊ณ , css์์ฑ์ ์ฌ์ฉํ๊ณ , app router์ RSC๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ ์ฌ๋๋ค์ด ์์๊น ๋ด(๋ณธ์ธ ํฌํจ!)
๋ฐฉ๋ฒ์ ์๋ ค์ฃผ๋ คํ๋ค.
๋ค๋ค ์๋ค์ํผ Emotion์ css ์์ฑ์ ์ฌ์ฉํ๋ ค๋ฉด tsconfig.json์
"jsxImportSource": "@emotion/react",
์์ ๊ฐ์ ์์ฑ์ ๋ฃ์ด์ผ ํ๋ค.
๊ทธ๋ฌ๋ฉด ๋ชจ๋ ํ๊ทธ์ css๋ฅผ ๋ฃ์ ์ ์์ด ์๋์ฒ๋ผ ์์ฑํ ์ ์๊ฒ ๋๋ค.
import { css } from '@emotion/react';
<div
ref={sectionImageRef}
css={css`
width: 240px;
`}
>
<Image
src={'/pngwing.png'}
width={800}
height={450}
alt="main"
/>
</div>
๊ทธ๋ ์ง๋ง tsconfig์
"jsxImportSource": "@emotion/react",
์ ์์ฑ์ ๊ฐ์ง ํ๊ทธ๋ ๋ชจ๋ client ์ปดํฌ๋ํธ์ด๋ค.
์ด์ ๋ ์๋์ ๊ฐ์ด ํ๊ทธ์ css๊ฐ optional๋ก ๋ค์ด๊ฐ ๋ฒ๋ฆฐ๋ค.
์ด๋ ๊ฒ ๋๋ฉด app router ๋ฐฉ์์์ ์๋ฒ์ฌ์ด๋๋ ๋๋ง์ ์ ํ ํ์ง ๋ชปํ๊ฒ ๋๋ค.
์ปดํ์ผํ ๋ ์ ์ด์ emotionํ๊ทธ๋ฅผ ์ฌ์ฉํด ๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์
// ex) app/auth/signIn/page.tsx
// โ Error => use client๋ฅผ ๋ถ์ด์ธ์! ๋ผ๋ ์๋ฌ๋ฅผ ๋ฑ์
const SignIn = () => {
return <div>1234</div>
};
export default SignIn;
// โ
OK but No RSC๐
"use client";
const SignIn = () => {
return <div>1234</div>
};
export default SignIn;
์์ ๊ฐ์ ๊ธฐ๋ณธ์ ์ธ ํ๊ทธ์๋ "use client"๋ฅผ ๋ถ์ฌ์ค์ผ ํ๋ค.
๊ทธ๋ฌ๋ฉด Emotion์ ์ฌ์ฉํ๋ ํ๋ก์ ํธ๋ app router ๋ฐฉ์์ RSC๋ฅผ ํ์ฉํ์ง ๋ชปํ ๊น?
์๋๋ค! ๋ฐฉ๋ฒ์ ์๋ค :)
ํด๊ฒฐ ๋ฐฉ์
next.config.js์์ webpack ์ปค์คํ ์ค์ ์ ํ๋ ๊ฒ์ด๋ค.
// next.config.js
/** @type {import('next').NextConfig} */
const enableEmotionRSC = require('./enableEmotionRSC');
const nextConfig = enableEmotionRSC({
reactStrictMode: true,
experimental: { appDir: true },
swcMinify: true,
output: 'standalone',
async rewrites() {
return [
{
source: '/api/:path*',
destination: `http://${process.env.REACT_APP_SERVER_DOMAIN_URL}/api/:path*`
}
];
}
});
module.exports = nextConfig;
์๋ ๋ด nextConfig ์ค์ ์ด๋ค.
๋ค๋ฅธ ๊ฑฐ๋ ๋ฌด์ํ๊ณ enableEmotionRSC๋ฅผ ์ดํด๋ณด์.
// enableEmotionRSC.js
const path = require('path');
const includedDirs = [path.resolve(__dirname, 'src')];
module.exports = function enableEmotionRSC(nextConfig) {
return {
...nextConfig,
webpack: (config, { isServer }) => {
config.module.rules = config.module.rules.filter(
(rule) =>
!(rule.test && rule.test.test && rule.test.test('.tsx'))
);
config.module.rules.push({
test: /\.tsx?$/,
include: includedDirs,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
configFile: path.resolve(__dirname, 'tsconfig.json')
}
}
]
});
if (isServer) {
config.resolve.alias['@emotion/react'] = 'react';
}
return config;
}
};
};
nextConfig๋ฅผ ์ธ์๋ก ๋ฐ๊ณ , ์ถ๊ฐ์ ์ผ๋ก webpack ์ค์ ์ ํด์ค๋ค.
webpack์ options์์ dev, isServer ๋ฑ๋ฑ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ ์๋ค.
๋๋ isServer ๋ฐ์ดํฐ๋ง ์ผ๋จ ํ์ํด์ ํด๋น ๊ฐ๋ง ๊ฐ์ ธ์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ts-loader๋ฅผ ์ฌ์ฉํด tsconfig๋ฅผ reslove ํด์ฃผ๊ณ ,
๊ทธ ๋ค์
if (isServer) {
config.resolve.alias['@emotion/react'] = 'react';
}
์์์ isServer๋ฅผ ๋ถ๊ธฐ๋ก ๊ฐ์ ์ค์ ํด ์ค๋ค
์๋ฒ์ฌ์ด๋๋ ๋๋ง(SSR)์ ํ ๋๋ @emotion/react์ ๊ฐ์ react๋ก ๋์ฒดํด ์ค๋ค๋ ์๋ฏธ์ด๋ค.
๋ฌผ๋ก ๋น์ฐํ๊ฒ๋ emotion์ ์ฌ์ฉํ๋ tsconfig.json์
"jsxImportSource": "@emotion/react",
์์ ๊ฐ์ ๊ฐ์ด ๋ค์ด๊ฐ ์์ด์ผ ํ๋ค.
๊ทธ๋ฌ๋ฉด emotion์ ํ์ฉํ๋ฉด์, app router ๋ฐฉ์์ RSC ํ๊ฒฝ์ ๊ตฌ์ฑํ ์ ์๊ฒ ๋๋ค.
์ ์ฒด ์ฝ๋๋ ์๋์ ๊ฐ๋ค.
์ถ๊ฐ์ ์ธ eslint์ค์ ์ ๋ณธ์ธ ์ ๋ง์ ๋ง๊ฒ ๋ณ๊ฒฝํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค!
// root/tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"jsxImportSource": "@emotion/react",
"plugins": [
{
"name": "next"
}
]
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"cypress/**/*",
"**/*.cy.ts",
".next/types/**/*.ts",
"enableEmotionRSC.js"
],
"exclude": ["node_modules"]
}
// root/enableEmotionRSC.js
const path = require('path');
const includedDirs = [path.resolve(__dirname, 'src')];
module.exports = function enableEmotionRSC(nextConfig) {
return {
...nextConfig,
webpack: (config, { isServer }) => {
config.module.rules = config.module.rules.filter(
(rule) =>
!(rule.test && rule.test.test && rule.test.test('.tsx'))
);
config.module.rules.push({
test: /\.tsx?$/,
include: includedDirs,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
configFile: path.resolve(__dirname, 'tsconfig.json')
}
}
]
});
if (isServer) {
config.resolve.alias['@emotion/react'] = 'react';
}
return config;
}
};
};
// root/next.config.js
/** @type {import('next').NextConfig} */
const enableEmotionRSC = require('./enableEmotionRSC');
const nextConfig = enableEmotionRSC({
reactStrictMode: true,
experimental: { appDir: true },
swcMinify: true,
output: 'standalone',
async rewrites() {
return [
{
source: '/api/:path*',
destination: `http://${process.env.REACT_APP_SERVER_DOMAIN_URL}/api/:path*`
}
];
}
});
module.exports = nextConfig;
'๐งโ๐ป Web > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[React] Cypress๋ก e2e ํ ์คํธ๋ฅผ ๊ตฌํํด๋ณด์ (2) | 2023.05.14 |
---|---|
[React] ์ต์ ๋ ์ฒด์ด๋ (0) | 2022.07.21 |
[React] ๋น๋๊ธฐ useState ๋๊ธฐ๋ก ์ฒ๋ฆฌํ๊ธฐ (0) | 2022.06.30 |
[React] PostCSS์์ style๊ฐ์ root์ฒ๋ผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ (2) | 2022.05.21 |
[React] React Route์ ๋ํด ์์๋ณด์ (0) | 2022.05.19 |