프론트엔드 환경설정 (cra사용x)

Lee Soyeon·2022년 4월 2일
0

프로젝트

목록 보기
2/6

npm init
npm i react react-dom
npm i typescript
npm i @types/react @types/react-dom
npm i -D eslint
npm i -D prettier eslint-plugin-prettier eslint-config-prettier

_cf) eslint는 코드검사도구(에러잡거나 오타 잡아주는 도구),
prettier는 정렬해주는 도구

.eslintrc 생성

{
  // prettier가 추천(recommended)하는대로 따르겠다는 의미
  "extends": ["plugin:prettier/recommended", "react-app"]
}

.prettierrc 생성

{
  "printWidth": 120, // 한 줄당 최대 글자수 (보편적으로 80~120많이 함)
  "tabWidth": 2, // 탭너비
  "singleQuote": true, // 홑따음표 ('')
  "trailingComma": "all", // 항상 콤마(,)를 뒤에 붙이기
  "semi": true // 세미콜론 항상 붙이기
}

tsconfig.json 생성

{
  "compilerOptions": {
    "esModuleInterop": true, // import * as React from 'react'; > import React from 'react';로 가져올 수 있음
    "sourceMap": true, // 에러난위치 찾아가기 편함
    "lib": ["ES2020", "DOM"],
    "jsx": "react", // jsx가 여러군데에서 쓸 수 있기 때문에 react라고 명시
    "module": "esnext", // 최신모듈 쓴다는 의미
    "moduleResolution": "Node", // import export도 node가 해석할 수 있게 하는것
    "target": "es5", // "lib"에 써있는 버전으로 작성하더라도 "es5"로 변환
    "strict": true, // 타입체크를 엄격하게 하겠다는 의미
    "resolveJsonModule": true, // json파일을 import로 가져오는것을 허용
    "baseUrl": ".",
    "paths": { // 경로지정시 ../../../ 이런거를 빼고 절대경로처럼 작성가능하게 해줌
      "@hooks/*": ["hooks/*"],
      "@components/*": ["components/*"],
      "@layouts/*": ["layouts/*"],
      "@pages/*": ["pages/*"],
      "@utils/*": ["utils/*"],
      "@typings/*": ["typings/*"]
    }
  }
}

cf) webpack5는 아직 지원안되는것들이 많아서 에러가 잘 날 수 있음. 안정화 될 때까진 webpack4로 개발하는 것이 좋음.

webpack.config.ts 생성

import path from 'path';
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
import webpack from 'webpack';
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';

const isDevelopment = process.env.NODE_ENV !== 'production'; // production은 배포용, development는 개발용

const config: webpack.Configuration = {
  name: 'sleact',
  mode: isDevelopment ? 'development' : 'production',
  devtool: !isDevelopment ? 'hidden-source-map' 또는 'cheap-module-source-map' : 'eval',
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], // 확장자 생략(바벨이 처리할 확장자 목록)
    alias: { // ../../ 이런거 없애주는 설정, tsconfig에서 설정해줘도 웹펙이 js로 바꿀땐 webpack.config파일을 토대로 바꾸기 때문에 여기서도 설정해줘야 함.
      '@hooks': path.resolve(__dirname, 'hooks'),
      '@components': path.resolve(__dirname, 'components'),
      '@layouts': path.resolve(__dirname, 'layouts'),
      '@pages': path.resolve(__dirname, 'pages'),
      '@utils': path.resolve(__dirname, 'utils'),
      '@typings': path.resolve(__dirname, 'typings'),
    },
  },
  entry: { // 파일 읽어들이기 시작하는 진입점
    app: './client', // app은 진입점에 해당하는 파일의 별명
  },
  module: { // 모듈 처리 방식을 설정, 웹팩의 처리과정, tsx/css/js등 확장자를 만나면 각각의 로더를 돌려달라는 내용.
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'babel-loader',
        options: {
          presets: [ // 바벨로더가 js로 바꿔줄 때, 바벨에 대한 설정
            [
              '@babel/preset-env',
              {
                targets: { browsers: ['last 2 chrome versions'] }, // targets에 설정한 브라우저에서 지원하게끔 알아서 바꿔준다
                debug: isDevelopment,
              },
            ],
            '@babel/preset-react',
            '@babel/preset-typescript',
          ],
          env: {
            development: {
              plugins: [['@emotion', { sourceMap: true }], require.resolve('react-refresh/babel')],
            },
            production: {
              plugins: ['@emotion'],
            },
          },
        },
        exclude: path.join(__dirname, 'node_modules'), // node_modules안의 파일들은 바벨로 해석안해도 됨
      },
      {
        test: /\.css?$/,
        use: ['style-loader', 'css-loader'],// 복수라서 use사용, 배열로 넣기. 한개라도 loader가 아니라 use로 적어도 됨.
      },
    ],
  },
  // 번들링 후 결과물의 처리 방식 등 다양한 플러그인들을 설정
  plugins: [// 웹팩의 처리과정, 모듈이 처리된 후에 추후에 어떤 작업을 더 진행해야 하는지 배열로 명시
    new ForkTsCheckerWebpackPlugin({ // typescript 사용하는 경우에 입력, typescript와 webpack이 동시에 실행되도록 해주는 기능
      async: false,
      // eslint: {
      //   files: "./src/**/*",
      // },
    }),
    // 리액트에서 'process.env.NODE_ENV'라는 변수를 사용할 수 있게 해줌(원래는 백엔드에서만 사용가능)
    new webpack.EnvironmentPlugin({ NODE_ENV: isDevelopment ? 'development' : 'production' }),
  ],
  output: { // 결과물(번들)을 반환하는 설정
    path: path.join(__dirname, 'dist'),// `__dirname`은 현재 파일의 위치를 알려주는 NodeJS 전역 변수
    filename: '[name].js',// `[name]`은 `entry`의 Key 이름, `app`
    publicPath: '/dist/',
  },
  devServer: {
    historyApiFallback: true, // react router
    port: 3090,
    publicPath: '/dist/',
    proxy: {
      '/api/': {
        target: 'http://localhost:3095',
        changeOrigin: true,
      },
    },
  },
};

if (isDevelopment && config.plugins) { // 개발환경일때 쓸 플러그인
  config.plugins.push(new webpack.HotModuleReplacementPlugin());
  config.plugins.push(new ReactRefreshWebpackPlugin());
  config.plugins.push(new BundleAnalyzerPlugin({ analyzerMode: 'server', openAnalyzer: true }));
}
if (!isDevelopment && config.plugins) {// 개발환경이 아닐때(배포환경일때) 쓸 플러그인
  config.plugins.push(new webpack.LoaderOptionsPlugin({ minimize: true }));
  config.plugins.push(new BundleAnalyzerPlugin({ analyzerMode: 'static' }));
}

export default config;

npm i -D webpack @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/preset-typescript

npm i -D @types/webpack @types/node
npm i stype-loader css-loader

index.html 생성

웹팩 실행명령
npx webpack 또는 npm i webpack 후, npx webpack
> 에러날 경우, webpack.config.ts파일을 웹팩이 인식을 못하기 때문
->tsconfig-for-webpack-config.json 생성
(웹팩이 webpack.config.ts파일을 인식하게 만들어줌)

// tsconfig-for-webpack-config.json
{
  "compilerOptions": {
    "module": "commonjs",
    "moduleResolution": "Node",
    "target": "es5",
    "esModuleInterop": true
  }
}

TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack
->명령이 길기 때문에 package.json파일의 "scripts"
"build": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack"
추가해서 간단하게 명령어 쓸 수 있게 하기

npm i ts-node
npm i cross-env
npm i run build

자동으로 수정된 코드를 반영해주기 위해서 Hot reloading 해주는 프로그램을 설치해야 함 (cra는 내장되어 있음)
npm i webpack-dev-server -D
(webpack-dev-server는 hot-reloading기능 + proxy서버역할, cors에러 해결해줌)

npm i webpack-cli
npm i -D @types/webpack-dev-server

hot-reloading해주기 위해서 아래 설치
npm i @pmmmwh/react-refresh-webpack-plugin
npm i react-refresh

typescript와 webpack이 동시에 실행되도록 해주는 기능
npm i fork-ts-checker-webpack-plugin -D

package.json파일의 "scripts"
"dev": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack serve --env development"

npm run dev

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


+@

* 코드 스플리팅

: 사용자경험을 위해(빠른 렌더링) 필요한 페이지들(컴포넌트들)만 불러오도록 하는 것.
- 분리기준
1) 페이지 단위로 분리
2) 서버사이드렌더링 필요없는것들
이렇게 코드 스플리팅 해주면 좋음

npm i @loadable/component
npm i -D @types/loadable__component

// App.tsx

// 아래코드 추가
// @로 가져오는건 웹팩설정해줬기 때문
import loadable from '@loadable/component';

// 아래코드 변경
// 기존
import Login from '@pages/Login'; 
import SignUp from '@pages/SignUp';
// 변경 후
const Login = loadable(() => import('@pages/Login'));
const SignUp = loadable(() => import('@pages/SignUp'));
  • 추가
    eslint 설정하기(설치) (에러가 났을 때, 조금 더 수월하게 찾을 수 있게해줌, dependency빠져있는 것들 알 수 있게 해줌)
// npm i -D eslint-config-react-app eslint-plugin-flowtype eslint-plugin-import eslint-plugin-jsx-ally

// 설치 후,
// .eslintrc에서 "react-app"추가
{
  "extends": ["plugin:prettier/recommended", "react-app"]
}
profile
프론트엔드 개발자가 되기 위해 공부하고 있습니다.

0개의 댓글