제로초님 강의들으면서 CRA없이 프로젝트 구성하는 부분과 보면서 궁금해진거 찾아보며 정리한 글입니당.

 

 

 

일단 npm init을 하고나서 package.json과 package-lock.json 차이가 뭔지 궁금해서 좀 찾아봤습니다. 

package.json은 전반적인 간략한 프로젝트 정보와 메타 데이터를 갖고 있고, package-lock.json은 라이브러리 간에 상호 종속하는 버젼같은게 적혀있고, 좀 더 package에 대한 좀 더 자세한 내용이 담겨있네요. 

 

https://www.geeksforgeeks.org/difference-between-package-json-and-package-lock-json-files/

 

Difference between package.json and package-lock.json files - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

 

package.json package.lock.json
프로젝트에 대한 기본적인 정보를 포함하고 있다. 이후 설치에서 동일한 트리를 가질 수 있도록 생성된 정확한 트리를 설명합니다.
모든 프로젝트에 의무적으로 있어야합니다. npm이 node_movuldes 트리 혹은 package.json을 수정하는 모든 작업에 자동으로 생성됩니다.

프로젝트에 관한 중요한 메타데이터를 기록합니다.
향후 개발자들이 프로젝트를 같은 종속성을 갖게끔 설치할 수 있도록 합니다.
이름, 설명, 저자, 스크립트, 디펜던시 같은 정보를 포함하고 있습니다. 이름, 종속성과 프로젝트의 locked version을 포함하고 있습니다.

 

그리고 완벽하진 않지만 세팅파일들에 대한 기본적인 설정값들 

 


 

본격적인 웹팩 패키지들 설치 

webpack을 위한 패키지 설치..

import path from 'path';
import webpack, { Configuration as WebpackConfiguration } from "webpack";

interface Configuration extends WebpackConfiguration {}

// 개발과 배포 환경에따라 다른 설정을 적용하기 위함
const isDevelopment = process.env.NODE_ENV !== 'production';

const config: Configuration = {
  name: 'sleact',
  mode: isDevelopment ? 'development' : 'production',
  devtool: !isDevelopment ? 'hidden-source-map' : 'eval',
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
    // 웹팩이 이 alias를 기준으로 import shortcut을 자바스크립트로 바꿔준다. tsconfig에서는 검사만한다고 보면 된다.  
    alias: {
      '@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',
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'babel-loader',
        options: {
          presets: [
            [
              // 아래 브라우저에 호환되게 바벨이 트랜스파일링을 해준다.
              '@babel/preset-env',
              {
                targets: { browsers: ['last 2 chrome versions'] },
                debug: isDevelopment,
              },
            ],
            '@babel/preset-react',
            '@babel/preset-typescript',
          ],
        },
        exclude: path.join(__dirname, 'node_modules'),
      },
      {
        test: /\.css?$/,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [
    // 리액트에서 NODE_ENV라는 변수를 사용할 수 있게 해준다. 
    new webpack.EnvironmentPlugin({ NODE_ENV: isDevelopment ? 'development' : 'production' }),
  ],
  // webpack의 빌드 결과물을 뱉는 위치
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
    publicPath: '/dist/',
  },
};

// 개발 환경에 사용할 플러그인
// if (isDevelopment && config.plugins) {}

// 배포 환경에 사용할 플러그인 
// if (!isDevelopment && config.plugins) {}

export default config;

 


 

Webpack에 Hot Re-Loading, devServer 추가하기 

 

webpack에 tsconfig compilerOptions를 적용하려면 두가지 방법이 있습니다.  하나는 아래처럼 tsconfig-for-webpack-config.json 라는 파일을 따로 만들어서 compilerOptions를 넣어주고 script를 아래 처럼 추가해주면 웹팩쪽에서 인식이 가능하고, 

 

 

아니면 tsconfig-json에 ts-node 설정을 추가해주고, compilerOptions을 추가해주면 webpack 에서 알아서 인식을 한다고하네요. 이 방법으로하면 위처럼 따로 파일을 안만들어주고 할 수 있어서 더 낫다고 생각됩니다 ! 

 

https://webpack.js.org/configuration/configuration-languages/

 

Configuration Languages | webpack

webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

webpack.js.org

import path from 'path';
import ReactRefreshWebpackPlugin  from '@pmmmwh/react-refresh-webpack-plugin';
import webpack, { Configuration as WebpackConfiguration } from "webpack";
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
import { Configuration as WebpackDevServerConfiguration } from "webpack-dev-server";

interface Configuration extends WebpackConfiguration {
  devServer?: WebpackDevServerConfiguration;
}

// 개발과 배포 환경에따라 다른 설정을 적용하기 위함
const isDevelopment = process.env.NODE_ENV !== 'production';

const config: Configuration = {
  name: 'sleact',
  mode: isDevelopment ? 'development' : 'production',
  devtool: !isDevelopment ? 'hidden-source-map' : 'eval',
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
    // 웹팩이 이 alias를 기준으로 import shortcut을 자바스크립트로 바꿔준다. tsconfig에서는 검사만한다고 보면 된다.  
    alias: {
      '@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',
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'babel-loader',
        options: {
          presets: [
            [
              // 아래 브라우저에 호환되게 바벨이 트랜스파일링을 해준다.
              '@babel/preset-env',
              {
                targets: { browsers: ['last 2 chrome versions'] },
                debug: isDevelopment,
              },
            ],
            '@babel/preset-react',
            '@babel/preset-typescript',
          ],
          env: {
            development: {
              plugins: [require.resolve('react-refresh/babel')],
            },
          },
        },
        exclude: path.join(__dirname, 'node_modules'),
      },
      {
        test: /\.css?$/,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [
    // 타입 체크와 웹팩 실행이 동시에 돌아가게끔 만들어준다.
    new ForkTsCheckerWebpackPlugin({
      async: false,
      // eslint: {
      //   files: "./src/**/*",
      // },
    }),
    // 리액트에서 NODE_ENV라는 변수를 사용할 수 있게 해준다. 
    new webpack.EnvironmentPlugin({ NODE_ENV: isDevelopment ? 'development' : 'production' }),
  ],
  // webpack의 빌드 결과물을 뱉는 위치
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
    publicPath: '/dist/',
  },
  devServer: {
    // 리액트 라우터를 위한 설정
    historyApiFallback: true, // react router
    port: 3090,
    // 웹팩에서 빌드한 파일에 대한 경로
    devMiddleware: { publicPath: '/dist/' },
    // index.html같은 정적 파일의 경로
    static: { directory: path.resolve(__dirname) },
  },
};

// 개발 환경에 사용할 플러그인
if (isDevelopment && config.plugins) {
  config.plugins.push(new webpack.HotModuleReplacementPlugin());
  config.plugins.push(new ReactRefreshWebpackPlugin());
}


// 배포 환경에 사용할 플러그인 
if (!isDevelopment && config.plugins) {
}

export default config;

 

historyApiFallback 이 뭐임 ? 

좌 false 우 true

그리고 devServer에 historyApiFallback 이라는 옵션이 true로 되어있습니다. 
주석으로는 간단한 라우팅을 위하다고 적혀있지만, SPA 특성상 URL은 index.html 주소 한가지만 갖고 있습니다. 그래서 react-router-dom을 통한 라우팅으로 url을 통한 해당 컴포넌트는 처음에 보여주지만 새로고침이나 다른 페이지로 넘어갈때 에러가 발생합니다. 웹의 history API를 사용해 URL이 여러개인 것 처럼 보여줄 수 있게끔 해준다고합니다.

해당 옵션을 켜줌으로써 해당 프로젝트는 404 응답대신 index.html 페이지제공되게되면서 프론트단에 react-router가 그를 인지하고 계속 해당 URL에 맞는 컴포넌트 잘 보여주는 것을 확인할 수 있네요.