CRA...?

이서현·2023년 6월 10일
0

우연히 CRA로 프로젝트를 생성하고 작업을 하려고 하는데
'과연 실무에서도 CRA를 사용할까?'라는 생각이 들었다.
CRA없이 리액트 설정을 해보잡

package.json 생성

왜 필요?

  1. 의존성 관리
    프로젝트가 의존하는 외부 패키지의 정보를 일관되게 관리 가능
  2. 스트립트 정의
    npm start 같은 거 정의해서 쉽게 사용 가능
  3. 프로젝트 정보
    프로젝트의 이름, 버전, 저작권 정보 등과 같은 정보를 포함

🦖 작성해두면 나중에 어느 곳에서도 동일한 개발 환경을 만들 수 있다 🦖

npm init -y

초기 설정이 포함된 package.json을 만들어준다

{
  "name": "without-cra",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

그러면 내가 많이 본 package.json이 나온다

react랑 react-dom 설치

npm i react react-dom

react-dom : 가상 DOM을 실제 DOM에 렌더링 하는 역할

{
  "name": "without-cra",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": { // 여기는 애플리케이션이랑 직접적으로 연관된 애들 
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}
// devDependencies는 개발할 때 필요한 애들만 설치 (typescript처럼)

일단 뭘 어떻게 해야 할지 모르겠으니께 모양새만 만들기

without-cra
 ┣ public
 ┃ ┗ index.html
 ┗ src
 	┣ App.jsx
 	┗ index.jsx

src/index.jsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

src/App.jsx

const App = () => {
	return <div>안녕</div>
}

export default App

public/index.html

<!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>without-cra</title>
  </head>
  <body>
    <div id="root"></div> 
  </body>
</html>

webpack

왜 필요?

일단 다른 블로그로 대체

npm install -D webpack webpack-dev-server webpack-cli

webpack-cli: 웹팩 명령어 사용 가능
webpack-dev-server: 실시간 개발 서버 환경

packge.json scripts 설정

  "scripts": {
    "build": "webpack",
    "start": "webpack serve",
  },

webpack.config.js

기본적으로 webpack은 설정 파일을 사용할 필요가 없습니다. webpack은 프로젝트의 엔트리 포인트를 src/index.js으로 가정하고, 프로덕션을 위해 압축하고 최적화된 결과를 dist/main.js로 내보냅니다.
(설정 파일이 없으면 기본 설정으로 번들링을 함)

필요가 없다고 하니 npm run build

모드를 알려달라 하고, jsx를 모른다고 한다

기본적으로 webpack은 JavaScript 및 JSON 파일만 이해한다

그렇다면 나중에 추가되거나 변경되는 부분이 있으면 에러를 보낼 것이기 때문에
미리 진입점, 결과물 위치, 플러그인, loader 등등 알려주는 것
이 설정 파일도 작성해 두면 동일한 개발 환경 구축 가능
(이래서 설정 파일이 중요한가 보다)

// Node.js에서 제공하는 내장 모듈인 path 모듈을 가져오는 것, 파일 경로를 조작하고 다룰 수 있도록 도와줌
const path = require('path') 

module.exports = {
  // 진입점
  entry: './src/index.jsx',
  // webpack을 실행한 후의 결과물
  output: 
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
    // __dirname : 절대 경로로 표현되며, 파일의 전체 경로에서 파일 이름을 제외한 디렉토리 경로를 나타냄
  },
}

아까 jsx모른다고 했으니까 알아들을 수 있게 해줘야 하는데 그 기능을 하는 게

Babel

자바스크립트의 코드를 구버전에 맞게끔 변환시켜 주는 역할을 한다 = 트랜스파일링

npm i -D @babel/core @babel/cli @babel/preset-env @babel/preset-react

@babel/cli : 바벨 명령어 사용 가능
@babel/core : 이름은 core인데 하는 일은 파싱이랑 출력 담당
변환은 프리셋들이 한다
@babel/preset-env : 대상 환경에 필요한 구문 변환(및 선택적으로 브라우저 폴리필)
@babel/preset-react : jsx 문법을 변환하고 React의 추가 기능을 지원

npx babel --presets @babel/preset-react src/index.jsx --out-file result.js

"바벨아 preset-react를 이용해 index.jsx를 트랜스파일링 해서 result.js파일로 만들어줘"

// result.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render( /*#__PURE__*/React.createElement(React.StrictMode, null, /*#__PURE__*/React.createElement(App, null)));

이제 jsx가 뭔지 알려줬으니까 webpack build를 해보면?

Module not found: Error: Can't resolve './App.jsx'

아앗

Module parse failed: Unexpected token (2:9)
You may need an appropriate loader to handle this file type,
currently no loaders are configured to process this file.
See https://webpack.js.org/concepts#loaders
| const App = () => {
>   return <div>안녕</div>
| }

jsx확장자, App.jsx안에 있는 jsx문법을 이해하지 못한다
그렇다면 일일이 파일마다 트랜스파일링 하고 난 뒤에 webpack을 돌려야 한다는 말이 자네?
이 과정을 손쉽게 하기 위해서
Webpack이 Babel을 사용할 수 있게 해주는
babel-loader를 설치하는 것이다

npm i -D babel-loader

webpack설정 파일에서 프리셋 설정을 해두면 따로 babel설정 파일 없어도 된다

module.exports = {

  module: {
    rules: [
      {
        test: /\.(js|jsx)?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              '@babel/preset-react',
            ],
          },
        },
      },
    ],
  }
}

"웹팩아 번들링 할 때 test에다가 지정한 파일 형식을 만나면
use에 지정한 loader로 변환해 줘야 돼, 그리고 node_modules 폴더는 빼줘"

눈으로 확인을 해봐야지 : webpack-dev-server

설정을 안 해도 데브 서버 시작 가능

npm run start

아아아아아 너무 빨게 아아아아아아아아아아아아아아

React17부터는 import React from 'react'를 쓰지 않아도 되는데
{ runtime: 'automatic' } 이렇게 설정을 해줘야
React의 JSX에서 React를 실제로 import 해오지 않더라도 자동으로 해석해준다
babel-preset-react#options
아니면 일일이 React를 import하는 방법도 있다 ㅎㅎ

  module: {
    rules: [
      {
        test: /\.(js|jsx)?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              ['@babel/preset-react', { runtime: 'automatic' }],
            ],
          },
        },
      },
    ],
  },  

이제는 나오겠지...ㅠ

사랑해요 stackoverflow

  output: {
    publicPath: '/dist',
  },

설명 조금 더 붙이자면 publicPath를 설정하면
웹팩은 해당 경로를 사용하여 번들된 파일에 대한 URL을 생성하고
이 URL은 웹 애플리케이션에서 번들된 파일을 로드할 때 사용된다고 한다

드디어 에러 없이 화면이 나온다!!
















번외
다른분 글인데 이것 저것 유용한 내용이 많았다.
[CodeStates-Section4]U3.React-번들링과 웹팩

profile
🌿💻💪🧠👍✨🎉

0개의 댓글