$ npx create-next-app --typescript
Would you like to se ESLint with this project? -> Yes 선택
$ npx eslint --init
eslint-plugin-react@latest # 리액트 관련 규칙
@typescript-eslint/eslint-plugin@latest
@typescript-eslint/parser@latest
eslint@latest
Would you like to install them now? -> Yes
npm i -D eslint-plugin-react-hooks
npm i -D eslint-plugin-import
npm i -D prettier eslint-plugin-prettier eslint-config-prettier
npm i -D eslint-config-airbnb
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"airbnb",
"plugin:jsx-a11y/recommended",
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"plugin:import/recommended"
],
"overrides": [],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["react", "@typescript-eslint", "prettier", "import"],
"rules": {
"import/extensions": [
"error",
"ignorePackages",
{
"js": "never",
"jsx": "never",
"ts": "never",
"tsx": "never",
"json": "never"
}
],
"react/jsx-filename-extension": [
2,
{ "extensions": [".js", ".jsx", ".ts", ".tsx"] }
],
"prettier/prettier": ["error", { "endOfLine": "auto" }],
"import/prefer-default-export": "off",
"react/react-in-jsx-scope": "off",
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }],
"react/jsx-props-no-spreading": ["warn"]
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".jsx", ".ts", ".tsx"]
}
}
}
}
"off" or 0: 규칙을 사용하지 않음
"warn" or 1: 규칙을 경고로 사용
"error" or 2: 규칙을 오류로 사용
{
"singleQuote": true,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80,
"arrowParens": "always",
"orderedImports": true,
"bracketSpacing": true,
"jsxBracketSameLine": false
}
전역 설정 json 파일, settings가 먼저 적용되고 prettierrc 파일이 있으면 그 파일을 뒤에 적용함
내 settings.json
{
"liveServer.settings.donotShowInfoMsg": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"liveServer.settings.useLocalIp": true,
"liveServer.settings.host": "192.168.0.46",
"terminal.integrated.defaultProfile.windows": "Command Prompt",
"bracket-pair-colorizer-2.depreciation-notice": false,
"workbench.editorAssociations": {
"*.docx": "default"
},
"code-runner.runInTerminal": true,
"code-runner.terminalRoot": "/",
"emmet.triggerExpansionOnTab": true,
"editor.tabSize": 2,
"javascript.updateImportsOnFileMove.enabled": "always",
"materialTheme.accent": "Bright Teal",
"settingsSync.ignoredExtensions": [],
"editor.tokenColorCustomizations": {
"textMateRules": [
{
"scope": ["comment", "keyword.control"],
"settings": { "fontStyle": "bold " } //주석과 키워드에 적용된 이탤릭 폰트스타일 해제
}
],
"comments": "#16bda7" //주석 색상변경
},
"workbench.iconTheme": "eq-material-theme-icons-ocean",
"workbench.colorTheme": "Community Material Theme Darker High Contrast",
"prettier.singleQuote": true,
"javascript.format.enable": false,
"typescript.updateImportsOnFileMove.enabled": "always",
"editor.codeActionsOnSave": { "source.fixAll.eslint": true },
"files.autoSave": "onFocusChange",
"remote.SSH.remotePlatform": {},
"window.zoomLevel": -1
}
$ npm i styled-components @types/styled-components
styled-components는 문자열 안에 css를 작성하는데 자바스크립트 컴파일러인 babel이 못알아먹어서 .babelrc파일 안에 styled-components에 대해 써줌
$ npm i --save-dev babel-plugin-styled-components
위 플러그인 설치 후 .babelrc를 생성하고 아래와 같이 작성
{
"presets": ["next/babel"],
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": true
}
]
]
}
그 후 SSR을 할 때에도 Styled-Components 사용을 위해 _document.tsx를 수정
import Document, { DocumentContext, DocumentInitialProps } from "next/document";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static async getInitialProps(
ctx: DocumentContext
): Promise<DocumentInitialProps> {
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();
}
}
}
import type { AppProps } from 'next/app';
import Head from 'next/head';
import { ThemeProvider } from 'styled-components';
import { GlobalStyle } from '../styles/global-style';
import { theme } from '../styles/theme';
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>MyApp</title>
</Head>
<GlobalStyle />
<ThemeProvider theme={theme}>
<Component {...pageProps} />
</ThemeProvider>
</>
);
}
export default MyApp;