웹/react

CRA없이 react typescript환경 구성하기

allblack 2021. 7. 25. 17:19
반응형

리액트는 UI 기능만 제공하는 라이브러리라서 개발자가 직접 설정해야 하는 것들이 많이 있습니다. 그런데 이렇게 개발자 마음대로 설정할 수 있는 점 때문에 처음 시작하는데 많은 어려움이 있습니다. 그래서 react에서 CRA를 만들었습니다.

CRA란?

리액트 프로젝트를 시작하는데 필요한 개발 환경을 세팅 해주는 툴입니다.

CRA의 장점

  • 초보자가 react에 접근하기 쉽다.
  • webpack, babel등 세부 설정을 자동으로 해줍니다.
  • ES6+문법, CSS 후처리같은 개발환경 자동으로 설정해줍니다.

cra 단점

  • webpack,babel설정을 변경하기 어렵다.
  • 작은 프로젝트를 진행할때에는 너무 파일이 무겁다

(물론 react-app-rewired나 eject를 이용해서 webpack설정을 수정할 수 있습니다.)

 

보통 리액트 프로젝트를 진행할때 CRA(Create React App)를 이용해서 쉽게 개발환경을 구축할 수 있습니다. 하지만 CRA에 의존하다 보면 Webpack, Babel에 추가적인 설정을 해야 할 때 어려움이 발생할 수 있습니다. 그래서 CRA 없이 리액트 프로젝트를 세팅해보려고 합니다!

 

react설치 하기

npm i -D typescript
npm i -D react react-dom @types/react @types/react-dom

 

tsconfig.json 설정하기

node_modules/.bin/tsc --init

tsconfig.json

{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es6", // 사용할 특정 ECMAScript 버전 설정 ex> es5, es6
    "lib": ["dom", "esnext"] /* 컴파일에 포함될 라이브러리 파일 목록 */,
    "allowJs": true /* 자바스크립트 파일 컴파일 허용 여부 */,
    "strict": true /* 모든 엄격한 타입-체킹 옵션 활성화 여부 */,
    "forceConsistentCasingInFileNames": true /* 같은 파일에 대한 일관되지 않은 참조를 허용하지 않을 지 여부 */,
    "esModuleInterop": true /* 모든 imports에 대한 namespace 생성을 통해 CommonJS와 ES Modules 간의 상호 운용성이 생기게할 지 여부, 'allowSyntheticDefaultImports'를 암시적으로 승인합니다. */,
    "module": "esnext" /* 모듈을 위한 코드 생성 설정: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    "isolatedModules": true,
    "jsx": "react", // JSX 코드 생성 설정: 'preserve', 'react-native', 혹은 'react'.
    "allowSyntheticDefaultImports": true,
    "baseUrl": "./" /* non-absolute한 모듈 이름을 처리할 기준 디렉토리 */,
    "outDir": "./dist",
    "moduleResolution": "node" /* 모듈 해석 방법 설정: 'node' (Node.js) 혹은 'classic' (TypeScript pre-1.6). */
  },
  "extends": "./tsconfig.paths.json",
  "exclude": ["node_modules"],
  "include": ["**/*.ts", "**/*.tsx"]
}

loader 설치

npm i -D ts-loader babel-loader

나중에 babel이 필요할지도 모르니 일단 같이 세팅하겠습니다.

module.exports = {
  presets: [
    "@babel/preset-react",
    "@babel/preset-env",
    "@babel/preset-typescript",
  ],
};

bable.config.js

 

webpack 설정

"use strict"; //js 문법 오류를 엄격하게 검사하겠다는 의미

const webpack = require("webpack");
const path = require("path");

const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/index.tsx",
  devServer: {
    historyApiFallback: true,
    contentBase: path.join(__dirname, "dist"),
    inline: true,
    port: 3000,
    hot: true,
    publicPath: "/",
  },

  mode: "development",
  output: {
    path: path.join(__dirname, "/dist"),
    filename: "bundle.js",
  },
  resolve: {
    extensions: [".ts", ".tsx", ".js"], //파일을 import시 확장자 해석 순서 (확장자 생략가능)
  },
  module: {
    rules: [
      {
        test: /\.html$/,
        use: "html-loader",
      },
      {
        test: /\.(ts|tsx)$/,
        exclude: /node_modules/,
        use: ["babel-loader", "ts-loader"],
      },
      {
        test: /\.(scss|css|sass)$/,
        use: [
          "style-loader", // creates style nodes from JS strings
          "css-loader", // translates CSS into CommonJS
          "sass-loader", // compiles Sass to CSS, using Node Sass by default
        ],
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [  
    new HtmlWebpackPlugin({
      title: "Apple",
      meta: {
        viewport: "width=device-width, initial-scale=1, shrink-to-fit=no",
      },
      template: "./src/public/index.html",
    }),
  ],
};

파일 구조 및 기본 파일 세팅

  • src
  • public
    • index.html
  • index.tsx
  • App.tsx
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
import React from "react";
import Router from "./router";
function App() {
  return <div>Hello React!</div>
}

export default App;
import React from "react";
import ReactDOM from "react-dom";

import App from "./App";

const rootElement = document.getElementById("root");

ReactDOM.render(<App />, rootElement);

package.json 수정

"scripts": {
    "dev": "webpack serve --config ./webpack.config.js",
    "build": "webpack ./src/index.tsx --output-path dist",
    "prestart": "npm run build",
    "start": "webpack --mode development"
  },
반응형