React + TypeScript의 webpack 설정

이소라·2022년 5월 28일
0

TypeScript

목록 보기
2/28

Webpack 설정

npm i -D webpack webpack-cli webpack-dev-server
  • webpack : 웹팩 코어
  • webpack-cli : 터미널의 커맨드라인에서 웹팩 사용
  • webpack-dev-server : 웹팩을 메모리 상으로만 빌드한 결과물을 개발 서버에 구동

webpack config 파일 설정

webpack devServer 설정

  • open: 서버가 시작될 때 default 브라우저 창을 자동으로 띄워줌

  • historyApiFallback : History API 또는 react-router 등을 사용하는 경우 새로고침 시 404 에러를 해결해줌

  • client의 overlay 옵션 : 컴파일러 오류 또는 경고가 있는 경우 브라우저에 전체 화면 오버레이를 표시해줌

module.exports = {
  ...
  devServer: {
      open: true,
      historyApiFallback: true,
      static: {
        directory: path.join(__dirname, 'public'),
      },
      hot: true,
      client: {
        overlay: {
          errors: true,
          warnings: false,
        },
      },
    },
}

webpack plugin 설정

npm i -D @pmmmwh/react-refresh-webpack-plugin react-refresh
  • react-refresh-webpack-plugin : 앱 전체를 다시 다운로드 하지 않고, 수정된 React 구성 요소만 리렌더링해줌
npm i -D html-webpack-plugin
  • html-webpack-plugin : script 태그를 사용하여 body에 모든 webpack 번들을 포함하는 HTML 파일을 생성해줌
npm i -D mini-css-extract-plugin
  • mini-css-extract-plugin : 번들링 파일에서 CSS 파일을 별도로 추출해줌

  • webpack.ProvidePlugin : 모듈을 import 또는 require 할 필요 없이 자동으로 로드

  • webpack.DefinePlugin : 모든 JS 파일에서 접근 가능한 전역 변수를 선언하기 위해서 사용

const definePlugin = new webpack.DefinePlugin({
    BASE_URL: JSON.stringify(BASE_URL),
  }); //배포할 때 필요한 기본 URL을 저장해둠

module.exports = {
  ...
    plugins: [
      new webpack.ProvidePlugin({
        React: 'react',
      }),
      definePlugin,
      miniCssExtractPlugin,
      new HtmlWebpackPlugin({
        template: path.join(__dirname, 'public', 'index.html'),
      }),
      refreshWebpackPlugin,
    ],
}

webpack 기타 설정

  • resolve.alias : importrequire로 불러오는 특정한 module의 별칭을 정할 수 있음

  • resolve.fallback : 정상적인 확인이 실패하면 module 요청을 redirect해줌

  • preset.useBuiltIns

    • entry : target 환경에서 요구되는 특정한 module만 import됨
    • usage : target 환경에서 지원하지 않는 feature를 사용할 때 자동으로 polyfill이 더해짐
    • false : 추가적인 polyfill이 자동으로 더해지지 않는 기본적인 값

webpack.config.js 전체 파일

const path = require('path');

const RefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');

module.exports = (env) => {
  const { NODE_ENV } = env;
  console.log(`[NODE_ENV] >>> ${NODE_ENV}`);
  if (!['production', 'development'].includes(NODE_ENV))
    throw Error('[NODE_ENV] must be production or development');

  const DEV = NODE_ENV === 'development';
  const mode = DEV ? 'development' : 'production';
  const devtool = DEV ? 'eval-source-map' : false;
  const lastCssLoader = DEV ? 'style-loader' : MiniCssExtractPlugin.loader;
  const miniCssExtractPlugin = DEV
    ? { apply: () => {} }
    : new MiniCssExtractPlugin({ filename: 'css/style.css' });
  const refreshWebpackPlugin = DEV ? new RefreshWebpackPlugin() : { apply: () => {} };
  const refreshBabel = DEV ? 'react-refresh/babel' : {};
  const BASE_URL = DEV ? '' : 'fe-vm';
  const definePlugin = new webpack.DefinePlugin({
    BASE_URL: JSON.stringify(BASE_URL),
  });

  return {
    mode,
    devtool,
    resolve: {
      fallback: { fs: false, path: false },
      alias: {
        '@': path.resolve(__dirname, 'src'),
        '@Utils': path.resolve(__dirname, 'src/utils'),
      },
      extensions: ['.js', '.ts', '.jsx', '.tsx'],
    },
    entry: {
      main: './src/index.tsx',
    },
    module: {
      rules: [
        {
          test: /\.(ts|tsx|js|jsx)$/,
          loader: 'babel-loader',
          exclude: /node_modules/,
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  targets: {
                    browsers: ['> 0.5% in KR, not dead'],
                  },
                  useBuiltIns: 'usage',
                  corejs: { version: 3, proposals: true },
                  debug: true,
                },
              ],
              '@babel/preset-react',
              '@babel/preset-typescript',
            ],
            plugins: [refreshBabel, 'styled-components'],
          },
        },
        {
          test: /\.(sc|c|sa)ss$/,
          use: [lastCssLoader, 'css-loader'],
        },
      ],
    },
    plugins: [
      new webpack.ProvidePlugin({
        React: 'react',
      }),
      definePlugin,
      miniCssExtractPlugin,
      new HtmlWebpackPlugin({
        template: path.join(__dirname, 'public', 'index.html'),
      }),
      refreshWebpackPlugin,
    ],
    devServer: {
      open: true,
      historyApiFallback: true,
      static: {
        directory: path.join(__dirname, 'public'),
      },
      hot: true,
      client: {
        overlay: {
          errors: true,
          warnings: false,
        },
      },
    },
    output: {
      clean: true,
      path: path.resolve(__dirname, 'dist'),
    },
  };
};

0개의 댓글