July 05, 2021
Webpack을 이용해서 React + Typescript + Styled Components, 그리고 Storybook 세팅하는 방법을 정리한 글입니다.
위에 언급한 라이브러리들이 궁금하시다면 아래 링크를 참고해보시면 좋을거 같습니다!
이 글에서 사용 된 코드들은 아래 레포를 통해 확인하실 수 있습니다.
mkdir react-ts-webpack
cd react-ts-webpack
yarn init -y
yarn add react react-dom
yarn add -D typescript @types/react @types/react-dom
npx tsc --init
{
"compilerOptions": {
...
"jsx": "react-jsx" /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */,
...
}
}
yarn add -D webpack webpack-cli webpack-dev-server ts-loader html-webpack-plugin
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = () => {
const isDevelopment = process.env.NODE_ENV !== 'production'
return {
entry: './src/index.tsx',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
},
devServer: {
port: 3000,
hot: true,
},
devtool: isDevelopment ? 'eval-source-map' : 'source-map',
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: {
loader: 'ts-loader',
options: {
configFile: path.resolve(__dirname, 'tsconfig.json'),
},
},
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
}),
],
}
}
"scripts": {
"prod": "NODE_ENV=production webpack serve",
"dev": "NODE_ENV=development webpack serve",
"build": "NODE_ENV=production webpack",
}
yarn add -D prettier eslint
yarn add -D eslint-config-prettier eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks eslint-config-airbnb-typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser
.prettierrc.js
module.exports = {
/* 원하는 옵션을 적으시면 됩니다. */
}
module.exports = {
env: {
browser: true,
es2021: true,
},
ignorePatterns: ['*.js'],
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:import/recommended',
'plugin:jsx-a11y/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'airbnb-typescript',
'airbnb/hooks',
'prettier',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: 'module',
project: './tsconfig.json',
},
plugins: ['react', 'react-hooks', 'import', 'jsx-a11y', '@typescript-eslint'],
rules: {
'react/jsx-uses-react': 'off',
'react/react-in-jsx-scope': 'off',
},
}
yarn add styled-components
yarn add -D @types/styled-components
npx sb init
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>react typescript boilerplate</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
import styled from 'styled-components'
const Button = styled.button`
background: transparent;
border-radius: 3px;
border: 2px solid palevioletred;
color: palevioletred;
margin: 0 1em;
padding: 0.25em 1em;
`
export default { Button }
import { ButtonHTMLAttributes } from 'react'
import Styled from './Button.styles'
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
text: string
}
const Button = ({ text }: ButtonProps): JSX.Element => (
<Styled.Button>{text}</Styled.Button>
)
export default Button
import React from 'react'
import { Story } from '@storybook/react'
import Button, { ButtonProps } from './Button'
export default {
title: 'shared/Button',
component: Button,
}
const Template: Story<ButtonProps> = (args: ButtonProps) => <Button {...args} />
export const Default = Template.bind({})
Default.args = {
text: 'Button Test',
}
import Button from './Button/Button'
const App = (): JSX.Element => <Button text="App" />
export default App
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
<StrictMode>
<App />
</StrictMode>,
document.getElementById('root')
)
yarn dev
yarn storybook