1. 관련 패키지 설치
npm init -y
npm install -D webpack webpack-cli @babel/core @babel/preset-env @babel/preset-react
npm install -D webpack-dev-server html-webpack-plugin babel-loader mini-css-extract-plugin
2. 웹팩 환경설정
process.ENV
)npm install process
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
name: "styled-components_v1",
mode: "development",
resolve: {
extensions: [".js", ".jsx"],
},
entry: "./src/index.jsx",
module: {
rules: [
{
test: /\.jsx?/,
loader: "babel-loader",
// babelrc
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "index.html",
filename: "index.html",
}),
],
output: {
filename: "bundle.js",
path: path.join(__dirname, "dist"),
},
devServer: {
static: {
directory: path.join(__dirname, "dist"),
},
compress: true,
port: 3001,
hot: true,
historyApiFallback: true,
},
};
+) 간편 핫로딩을 위한 package.json
설정
"scripts": {
"dev" : "webpack server"
},
3. 리액트 & 스타일드 컴포넌트 설치
npm install react react-dom styled-component
4. 기본 디렉토리 & 파일 생성
|-- src
|---- app.js
|---- index.jsx
|-- index.html
위 트리구조를 따라 파일을 생성합니다
[index.html]
<body>
<div id="root"></div>
</body>
[./src/app.jsx]
import React from 'react';
const App = () => {
return <>Hello world!</>
}
export default App
[./src/index.jsx]
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App></App>);
5. 웹팩 번들링 & 서버 실행
npx webpack
npx webpack server
npm run dev
(*위 명령어 각각이 어떻게 동작하는지 설명할 수 있어야 합니다)
스타일드 컴포넌트를 다루기 전에 CSS-loader
를 먼저 설정하도록 하겠습니다
<head><style></style>
<head><link href...>
npm install -D mini-css-extract-plugin css-loader styled-components
1. 웹팩 환결설정 수정
[webpack.config.js]
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
name: "styled-components_v1",
mode: "development",
resolve: {
extensions: [".js", ".jsx"],
},
entry: "./src/index.jsx",
module: {
rules: [
{
test: /\.jsx?/,
loader: "babel-loader",
// babelrc
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
},
},
{
test: /\.css/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "index.html",
filename: "index.html",
}),
new MiniCssExtractPlugin({ filename: "bundle.css" })
],
output: {
filename: "bundle.js",
path: path.join(__dirname, "dist"),
},
devServer: {
static: {
directory: path.join(__dirname, "dist"),
},
compress: true,
port: 3001,
hot: true,
historyApiFallback: true,
},
};
2. 디렉토리 구조 수정
|-- /src
|---- /components
|----- button.jsx
|---- /pages
|----- main.jsx
|---- index.jsx
|---- app.jsx
App
컴포넌트에서 main
컴포넌트를 불러옵니다import React from "react";
import Main from "./pages/main";
const App = () => {
return (
<>
<Main />
</>
);
};
export default App;
./pages/main.jsx
, ./component/button.jsx
[main.jsx]
import React from "react";
import Button from "../components/button"
const Main = () => {
return (
<>
<h1>Logo</h1>
<ul>
<li>Hello world</li>
<li>
<Button>
<span>버튼1</span>
</Button>
<Button>
<span>버튼1</span>
</Button>
</li>
<li></li>
</ul>
</>
);
};
export default Main
[button.jsx]
import React from 'react';
const StyledButton = ({ children }) => {
return <button>{children}</button>
}
export default StyledButton
StyledButton으로 내보내고(export), Button으로 받았습니다(require)
위와 같이 컴포넌트를 주고받을 때 변수명은 달라져도 상관없습니다
컴포넌트의 innerHTML은 children으로 전달하는 것이 직관적입니다
그리고 children에는 엘리먼트도 함께 포함시켜서 전달할 수 있습니다
(<Button><span>버튼1</span></Button>
에서 <span>
도 children으로 전달)
[button.jsx]
import React from "react";
import styled, { css } from "styled-components";
const flexCenter = css`
display: inline-flex;
justify-content: center;
align-items: center;
outline: none;
border: none;
`
const Button = styled.button`
${flexCenter}
padding: 7px 14px;
font-size: 11px;
font-weight: bold;
`
const StyledButton = ({ children }) => {
return <Button>{children}</Button>;
};
export default StyledButton;
[App.js]
import React from "react";
import Main from "./pages/main";
import { ThemeProvider } from "styled-components";
const App = () => {
const colorChip = {
blue: '#228be6',
gray: "#adb5db",
pink: "#f06595",
}
return (
<>
<ThemeProvider theme={colorChip}>
<Main></Main>
</ThemeProvider>
</>
);
};
export default App;
최상위 컴포넌트에서 기본 컬러를 설정하고 하위 컴포넌트에 프롭스로 전달합니다
(전역 상태의 원리에 대해서는 추후에 Redux를 배우면서 파악하기로...)
[button.jsx]
import React from "react";
import styled, { css } from "styled-components";
const flexCenter = css`
display: inline-flex;
justify-content: center;
align-items: center;
outline: none;
border: none;
`;
// 특정 props 값이 존재한다면 넓이 100% 부여하기
const fullWidthStyle = css`
${(props) => {
return (
props.fullWidth &&
css`
width: 100%;
// 두 번째 버튼 간격을 벌리고 싶을 때
& + & {
margin-top: 10px;
}
& + & {
margin-right: 10px;
}
`
);
}}
`;
const Button = styled.button`
${flexCenter}
${fullWidthStyle}
padding: 7px 14px;
font-size: 11px;
font-weight: bold;
// 기본 색상 설정
/* background: ${(props) => {
switch (props.color) {
case "blue":
return props.theme.blue;
case "gray":
return props.theme.gray;
case "pink":
return props.theme.pink;
}
}}; */
background: ${(props) => props.theme[props.color]};
color: #fff;
// hover
&:hover {
background-color: #3399a4;
cursor: pointer;
}
& span {
color: #fff;
}
`;
// 자바스크립트 객체의 중괄호와, JSX 문법을 쓰기 위한 중괄호를 구분할 수 있어야 돼요
const StyledButton = ({ children, ...rest }) => {
return <Button {...rest}>{children}</Button>;
};
export default StyledButton;