티스토리 뷰
1. 지금까지는 index.html파일에 script 테그로 CDN 링크를 사용하여 React를 사용하였다.
2. 보통 React 프로그램은 React를 내장으로 사용하므로 npm으로 React, React-dom 설치한다.
3. webpack은 npm으로 설치한 외장 라이브러리와 사용자가 작성한 코드를 하나의 파일로 만들어 준다.
3-1 webpack을 아래와 같이 설치한다.
3-2 srcipts 속성에 build라는 이름으로 webpack 명령어를 추가하면 다음과 같다.
{
"name": "react-basic",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --watch",
"serve": "live-server public/",
"build-babel": "babel src/app.js --out-file public/scripts/app.js --presets=@babel/preset-env,@babel/preset-react --watch",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@babel/cli": "^7.12.1",
"@babel/core": "^7.12.3",
"@babel/preset-env": "^7.12.1",
"@babel/preset-react": "^7.12.1",
"live-server": "^1.2.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"webpack": "^5.3.0"
},
"devDependencies": {
"webpack-cli": "^4.1.0"
}
}
3-2-1 webpack-cli는 npm run build 명령어를 실행하면 설치하라고 화면이 뜨는데 설치하면 된다.
3-3 webpack은 사용하여 하나의 bundle js파일을 만들려면 설정파일이 필요하다.
3-3-1 즉, 어떤 파일이 시작코드인지 그리고 어떤 폴더에 저장할지, 그리고 어떤 변환이 필요한지 등이다.
3-3-2 webpack은 하나의 자동화 도구로 볼 수 있기 때문에 스크립트를 필요로 한다.
3-3-3 프로젝트 루트에 webpack.config.js 파일을 생성하고 다음과 같이 기록한다.
3-3-3-1 이렇게 기록하면 src/app.js가 첫 시작 파일, 결과물은 절대경로의 프로젝트 폴더/public에 저장된다.
3-3-3-2 이름은 bundle.js가 된다.
const path = require('path')
module.exports = {
entry: './src/app.js',
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
}
3-4 npm run build를 실행하면 일반적인 자바스크립트는 문제없이 실행되고 결과물 bundle.js가 생성된다.
3-5 하지만, 우리는 React를 사용하고 있기 때문에 jsx를 파싱할 babel이 여전히 필요해서 에러가 발생한다.
3-5-1 webpack은 외부의 변환 프로그램을 loader라는 형식으로 지원하고 있는데 지금은 babel-loader가 필요하다.
3-5-2 아래처럼 설치한다. webpack은 babel-loader를 통해서 babel을 사용한다.
3-5-3 이제 babel-loader를 설치했으니 webpack.config.js에 loader를 연결해야 한다.
3-5-4 loader를 연결하는 부분은 module이라는 속성으로 추가하고 rules라는 세부속성에 지정한다.
3-5-4-1 rules은 배열로 된 여러개의 설정정보를 가질 수 있다. 아래는 하나의 로더를 추가하는 경우이다.
3-5-4-2 test는 어떤 파일을 변환할지를 체크하기 위한 Regular Expression을 지정해야 한다.
3-5-4-2-1 여기에서는 .js로 끝나는 모든 파일을 변환하도록 되어 있다.
3-5-4-3 exclude는 어떤 패턴을 만났을 때 변환을 제외해야 하는지를 설정한다.
3-5-4-3-1 외부 라이브러리가 들어있는 node_modules 폴더는 제외되어야 한다.
3-5-4-4 use는 변환을 위한 로더에 대한 설정으로 여러 설정을 가지는 객체를 받는다.
3-5-4-4-1 loader는 어떤 로더가 실행되어야 할지, options은 이 로더가 가지는 옵션을 지정하는데 사용한다.
3-5-4-4-2 즉, babel을 command line에서 실행할 때 적었던 긴 내용들이 여기에서 설정할 수 있다.
3-5-4-4-3 여기는 지난 포스트에서 사용했던 react 변환을 위한 env, react가 presets에 추가되었다.
const path = require('path')
module.exports = {
entry: './src/app.js',
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react'
]
}
}
}
]
}
}
3-6. 참조 페이지들
3-6-1 로더 사용에 대한 가이드
3-6-2 지원하는 로더 리스트
4. webpack 설정이 끝났으니 이제 index.html을 수정해야 한다.
4-1 아래는 처음에 작성했던 코드이다. 여기서 react cdn은 더 이상 필요없고, bundle.js를 추가해야 한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Basic React</title>
</head>
<body>
<div id="app"></div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
4-2 수정 후
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Basic React</title>
</head>
<body>
<div id="app"></div>
<script src="bundle.js"></script>
</body>
</html>
5. 이젠 마지막으로 app.js를 수정해야 한다. 왜냐면 이젠 라이브러리가 로컬에 저장되어 있어 import를 해야 한다.
5-1 아래 소스에서 처음 2개 줄만 추가하면 된다. 두개의 라이브러리 모두 default로 export되어 있다.
import React from 'react'
import ReactDOM from 'react-dom'
class TodoApp extends React.Component {
constructor(props) {
super(props)
this.onRemoveAllClicked = this.onRemoveAllClicked.bind(this)
this.onNextTodoClicked = this.onNextTodoClicked.bind(this)
this.handleAddTodo = this.handleAddTodo.bind(this)
this.state = {
todos: [
"Take your mask",
"Wash your hands",
"Drink more water"
]
}
}
componentDidMount() {
try {
const todos = localStorage.getItem("todos")
if (todos) {
console.log(todos)
this.setState(() => ({ todos: JSON.parse(todos) }))
}
} catch (e) {
}
}
componentDidUpdate(prevProps, prevState) {
if (prevState.todos.length !== this.state.todos.length) {
localStorage.setItem("todos", JSON.stringify(this.state.todos))
}
}
onRemoveAllClicked() {
this.setState(() => {
return {
todos: []
}
})
}
onNextTodoClicked() {
const index = Math.floor(Math.random() * this.state.todos.length)
alert(this.state.todos[index])
}
handleAddTodo(todo) {
if (!todo) {
return 'Please type vaild item'
} else if (this.state.todos.indexOf(todo) > -1) {
return 'Duplicated item typed'
}
this.setState((prevState) => {
return {
todos: prevState.todos.concat(todo)
}
})
}
render() {
// const title = "TO DO List"
return (
<div>
{/* <Header title={title} /> */}
<Header />
<Action
hasTodos={this.state.todos.length > 0}
onNextTodoClicked={this.onNextTodoClicked}
/>
<TodoList
hasTodos={this.state.todos.length > 0}
todos={this.state.todos}
onRemoveAllClicked={this.onRemoveAllClicked}
/>
<AddTodo handleAddTodo={this.handleAddTodo} />
</div>
)
}
}
const Header = (props) => {
return (
<div>
<h1>{props.title}</h1>
</div>
)
}
Header.defaultProps = {
title: 'Your Todo List'
}
const Action = (props) => {
return (
<div>
<button
onClick={props.onNextTodoClicked}
disabled={!props.hasTodos}
>Next Todo?</button>
</div>
)
}
const TodoList = (props) => {
return (
<div>
<button
onClick={props.onRemoveAllClicked}
disabled={!props.hasTodos}
>Remove All</button>
{ props.todos.length === 0 && <p>No Item exists</p> }
{ props.todos.map(todo => <Todo key={todo} todoText={todo} />) }
</div>
)
}
const Todo = (props) => {
return (
<div>
<p>
{props.todoText}
</p>
</div>
)
}
class AddTodo extends React.Component {
constructor(props) {
super(props)
this.onFormSubmit = this.onFormSubmit.bind(this)
this.state = {
error: undefined
}
}
onFormSubmit(e) {
e.preventDefault()
const typedTodo = e.target.elements.newTodo.value
const error = this.props.handleAddTodo(typedTodo)
this.setState(() => {
return {
error
}
})
if (!error) {
e.target.elements.newTodo.value = ''
}
}
render() {
return (
<div>
{this.state.error && <p>{this.state.error}</p>}
<form onSubmit={this.onFormSubmit}>
<input type="text" name="newTodo" />
<button>Add</button>
</form>
</div>
)
}
}
ReactDOM.render(<TodoApp />, document.getElementById('app'))
6. 결과 화면
6-1 의미는 없지만 지난 번 마지막 결과와 동일하게 정상 동작한다.
7. 추가
7-1 .babelrc 라는 바벨 설정파일을 사용하여 preset 등을 설정할 수 있다.
7-2 webpack.config.js의 babel-loader의 options에 있는 presets를 부분을 삭제하고
7-2-1 .babelrc을 만들어 아래의 내용을 붙여 넣으면 동일한 결과를 얻을 수 있다.
7-2-2 babel 7.0부터는 .babelrc.json 이라는 이름을 사용하는데, 호환성을 위해서 .babelrc와 alias되어 있다.
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
7-3 옵션에 관해서는 아래를 참고 한다.
'Client Technologies > React' 카테고리의 다른 글
React : 각 컴포넌트를 각 파일에 분리하여 관리하기 (0) | 2020.10.28 |
---|---|
React : Webpack dev server 및 소스 맵 사용하기 (0) | 2020.10.28 |
React : node package.json scripts 속성 사용하기 (0) | 2020.10.28 |
React : 리액트 컴포넌트 라이프 사이클과 LocalStorage (0) | 2020.10.26 |
React : 함수 컴포넌트, 기본 props 값 설정하기 (0) | 2020.10.26 |
- Total
- Today
- Yesterday
- 도커 개발환경 참고
- AWS ARN 구조
- Immuability에 관한 설명
- 자바스크립트 멀티 비동기 함수 호출 참고
- WSDL 참고
- SOAP 컨슈머 참고
- MySql dump 사용법
- AWS Lambda with Addon
- NFC 드라이버 linux 설치
- electron IPC
- mifare classic 강의
- go module 관련 상세한 정보
- C 메모리 찍어보기
- C++ Addon 마이그레이션
- JAX WS Header 관련 stackoverflow
- SOAP Custom Header 설정 참고
- SOAP Custom Header
- SOAP BindingProvider
- dispatcher 사용하여 설정
- vagrant kvm으로 사용하기
- git fork, pull request to the …
- vagrant libvirt bridge network
- python, js의 async, await의 차이
- go JSON struct 생성
- Netflix Kinesis 활용 분석
- docker credential problem
- private subnet에서 outbound IP 확…
- 안드로이드 coroutine
- kotlin with, apply, also 등
- 안드로이드 초기로딩이 안되는 경우
- navigation 데이터 보내기
- 레이스 컨디션 navController
- raylib
- one-to-one
- one-to-many
- 외부파일
- XML
- Many-To-Many
- jsp
- crud
- Security
- Angular
- spring boot
- 설정하기
- 자바
- WebMvc
- 하이버네이트
- 상속
- hibernate
- form
- RestTemplate
- mapping
- Spring Security
- 매핑
- 로그인
- login
- MYSQL
- 스프링
- 스프링부트
- Spring
- Rest
- Validation
- 설정