반응형
$ npx create-next-app . --ts
$ npm i recoil styled-reset styled-components babel-plugin-styled-components && npm i -D @types/styled-components
.babelrc 생성 후 추가 : styled-components의 SSR, CSR 간 className이 달라서 발생하는 에러를 잡아줌
{
"presets": ["next/babel"],
"plugins": ["babel-plugin-styled-components"]
}
// 둘 중에 아무거나 사용, 아래는 조금 더 상세한 정보를 표시해줌
{
"presets": ["next/babel"],
"plugins": [
[
"babel-plugin-styled-components",
{ "fileName": true, "displayName": true, "pure": true, "ssr": true }
]
]
}
.eslintrc.json 수정 : "next/babel"이 없으면 에러가 나는데, 이를 포함해서 lint를 잡아줌.
{
"extends": ["next/babel", "next/core-web-vitals"]
}
.next.config.js 수정하기 : next.js에서 svg파일을 사용하고 싶을 때
$ npm i intercept-stdout
// Recoil의 Key가 SSR, CSR 에서 달라지는데서 발생하는 에러 보기 싫을 때
const intercept = require('intercept-stdout')
function interceptStdout(text) {
if (text.includes('Duplicate atom key')) {
return ''
}
return text
}
intercept(interceptStdout)
// SVG 이용하기
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
module.exports = {
nextConfig,
webpack: (config) => {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'],
})
return config
},
}
tsconfig.ts 수정하기 : 절대 경로를 사용하고 싶을 때
{
"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": {
"/pages" : ["/pages/*"],
"/Recoil" : ["/Recoil/*"],
"/Components" : ["/Components/*"],
}
},
"include" : ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude" : ["node_modules"]
}
pages/_document.js 생성 후 작성 : styled-components가 새로고침 등의 상황에서 깨지는 것을 막아줌.
import Document, { Head, Html, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () => originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
Styles 디렉토리 1 - Styles/Styled.d.ts 생성 후 추가
import 'styled-components'
declare module 'styled-components' {
export interface DefaultTheme {
colors: {
White : ['#FFFFFF'],
Black : ['#000000'],
Red : ['#fff5f5', '#ffe3e3', '#ffc9c9', '#ffa8a8', '#ff8787', '#ff6b6b', '#fa5252', '#f03e3e', '#e03131', '#c92a2a',],
Pink : ['#fff0f6', '#ffdeeb', '#fcc2d7', '#faa2c1', '#f783ac', '#f06595', '#e64980', '#d6336c', '#c2255c', '#a61e4d',],
Orange : ['#fff4e6', '#ffe8cc', '#ffd8a8', '#ffc078', '#ffa94d', '#ff922b', '#fd7e14', '#f76707', '#e8590c', '#d9480f',],
Yellow : ['#fff9db', '#fff3bf', '#ffec99', '#ffe066', '#ffd43b', '#fcc419', '#fab005', '#f59f00', '#f08c00', '#e67700',],
Green : ['#ebfbee', '#d3f9d8', '#b2f2bb', '#8ce99a', '#69db7c', '#51cf66', '#40c057', '#37b24d', '#2f9e44', '#2b8a3e',],
Lime : ['#f4fce3', '#e9fac8', '#d8f5a2', '#c0eb75', '#a9e34b', '#94d82d', '#82c91e', '#74b816', '#66a80f', '#5c940d',],
Teal : ['#e6fcf5', '#c3fae8', '#96f2d7', '#63e6be', '#38d9a9', '#20c997', '#12b886', '#0ca678', '#099268', '#087f5b',],
Cyan : ['#e3fafc', '#c5f6fa', '#99e9f2', '#66d9e8', '#3bc9db', '#22b8cf', '#15aabf', '#1098ad', '#0c8599', '#0b7285',],
Blue : ['#e7f5ff', '#d0ebff', '#a5d8ff', '#74c0fc', '#4dabf7', '#339af0', '#228be6', '#1c7ed6', '#1971c2', '#1864ab',],
Indigo : ['#edf2ff', '#dbe4ff', '#bac8ff', '#91a7ff', '#748ffc', '#5c7cfa', '#4c6ef5', '#4263eb', '#3b5bdb', '#364fc7',],
Violet : ['#f3f0ff', '#e5dbff', '#d0bfff', '#b197fc', '#9775fa', '#845ef7', '#7950f2', '#7048e8', '#6741d9', '#5f3dc4',],
Grape : ['#f8f0fc', '#f3d9fa', '#eebefa', '#e599f7', '#da77f2', '#cc5de8', '#be4bdb', '#ae3ec9', '#9c36b5', '#862e9c',],
Gray : ['#f8f9fa', '#f1f3f5', '#e9ecef', '#dee2e6', '#ced4da', '#adb5bd', '#868e96', '#495057', '#343a40', '#212529',],
},
}
}
Styles 디렉토리 2 - Styles/Theme.ts 생성 후 추가
import { DefaultTheme } from 'styled-components'
export const Theme: DefaultTheme = {
colors: {
White : ['#FFFFFF'],
Black : ['#000000'],
Red : ['#fff5f5', '#ffe3e3', '#ffc9c9', '#ffa8a8', '#ff8787', '#ff6b6b', '#fa5252', '#f03e3e', '#e03131', '#c92a2a',],
Pink : ['#fff0f6', '#ffdeeb', '#fcc2d7', '#faa2c1', '#f783ac', '#f06595', '#e64980', '#d6336c', '#c2255c', '#a61e4d',],
Orange : ['#fff4e6', '#ffe8cc', '#ffd8a8', '#ffc078', '#ffa94d', '#ff922b', '#fd7e14', '#f76707', '#e8590c', '#d9480f',],
Yellow : ['#fff9db', '#fff3bf', '#ffec99', '#ffe066', '#ffd43b', '#fcc419', '#fab005', '#f59f00', '#f08c00', '#e67700',],
Green : ['#ebfbee', '#d3f9d8', '#b2f2bb', '#8ce99a', '#69db7c', '#51cf66', '#40c057', '#37b24d', '#2f9e44', '#2b8a3e',],
Lime : ['#f4fce3', '#e9fac8', '#d8f5a2', '#c0eb75', '#a9e34b', '#94d82d', '#82c91e', '#74b816', '#66a80f', '#5c940d',],
Teal : ['#e6fcf5', '#c3fae8', '#96f2d7', '#63e6be', '#38d9a9', '#20c997', '#12b886', '#0ca678', '#099268', '#087f5b',],
Cyan : ['#e3fafc', '#c5f6fa', '#99e9f2', '#66d9e8', '#3bc9db', '#22b8cf', '#15aabf', '#1098ad', '#0c8599', '#0b7285',],
Blue : ['#e7f5ff', '#d0ebff', '#a5d8ff', '#74c0fc', '#4dabf7', '#339af0', '#228be6', '#1c7ed6', '#1971c2', '#1864ab',],
Indigo : ['#edf2ff', '#dbe4ff', '#bac8ff', '#91a7ff', '#748ffc', '#5c7cfa', '#4c6ef5', '#4263eb', '#3b5bdb', '#364fc7',],
Violet : ['#f3f0ff', '#e5dbff', '#d0bfff', '#b197fc', '#9775fa', '#845ef7', '#7950f2', '#7048e8', '#6741d9', '#5f3dc4',],
Grape : ['#f8f0fc', '#f3d9fa', '#eebefa', '#e599f7', '#da77f2', '#cc5de8', '#be4bdb', '#ae3ec9', '#9c36b5', '#862e9c',],
Gray : ['#f8f9fa', '#f1f3f5', '#e9ecef', '#dee2e6', '#ced4da', '#adb5bd', '#868e96', '#495057', '#343a40', '#212529',],
},
}
Styles 디렉토리 3 - Styles/GlobalStyles.ts
import { createGlobalStyle } from 'styled-components'
import reset from 'styled-reset'
const GlobalStyles = createGlobalStyle`
${reset};
a {
text-decoration : none;
color : inherit;
}
* {
// @ 드래그 방지
user-select : none; -ms-user-select : none; -khtml-user-select : none; -moz-user-select : -moz-none; -webkit-user-select : none;
box-sizing : border-box;
// @ Input의 type="number" 속성에 따라, spin button 없애기
::-webkit-outer-spin-button,
::-webkit-inner-spin-button {
-webkit-appearance : none;
margin : 0;
}
}
html,
body,
/* #root { */
#__next {
-webkit-font-smooting : antialiased;
font-family : -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size : 16px;
width : 100%;
height : 100%
}
`
export default GlobalStyles
_app.tsx 에서 조립하기
import type { AppProps } from 'next/app'
import { RecoilRoot } from 'recoil'
import { ThemeProvider } from 'styled-components'
import GlobalStyles from 'Styles/GlobalStyles'
import { Theme } from 'Styles/Theme'
const App = ({ Component, pageProps }: AppProps) => {
return (
<RecoilRoot>
<GlobalStyles />
<ThemeProvider theme={Theme}>
<Component {...pageProps} />
</ThemeProvider>
</RecoilRoot>
)
}
export default App
반응형
'React 입문자 꼬리표 떼기 > Frontend Setup' 카테고리의 다른 글
Emotion 도입하기 (0) | 2023.06.15 |
---|---|
6. Grid Layout #2 (2) | 2022.02.18 |
6. Grid Layout #1 (0) | 2022.02.14 |
5. Apply Styled-Components (1) | 2022.02.12 |
4. TypeScript - Object (객체) (1) | 2022.02.12 |
댓글