본문 바로가기

웹/Nest

[Nest] nest의 핫 리로딩

🟩 핫 리로딩이란?

애플리케이션의 코드를 수정하거나 업데이트할 때, 애플리케이션을 다시 시작하지 않고도 변경 사항을 즉시 적용할 수 있는 기능입니다.

일반적으로 소프트웨어 개발 중에는 코드를 수정하고 변경 사항을 적용하기 위해 애플리케이션을 다시 빌드하고 재시작해야 합니다. 이는 개발 프로세스를 느리게 만들 수 있고, 잦은 빌드 및 재시작으로 인해 개발자의 생산성을 저하시킬 수 있습니다.

핫 리로딩은 이러한 문제를 해결하기 위해 도입된 개발 기법이며, 개발 중인 애플리케이션을 다시 시작하지 않고도 코드 변경 사항을 적용할 수 있습니다. 이는 개발자가 수정한 코드를 실시간으로 반영하여 개발 중인 애플리케이션을 새로고침하거나 재시작하지 않고도 변경 사항을 확인할 수 있게 해줍니다.

핫 리로딩은 개발자들 사이에서 생산성을 향상시키고 개발 시간을 단축시키는 데 도움을 줍니다. 또한 애플리케이션의 재시작 없이 변경 사항을 적용할 수 있으므로, 실시간으로 코드를 테스트하고 디버깅하는 데 유용합니다. 이를 통해 애플리케이션의 개발 및 디버깅 프로세스를 효율적으로 진행할 수 있습니다.

 

🟩 nest의 watch가 있는데도 핫 리로딩을 사용하는 이유가 뭘까요?

watch는 프로젝트 전체 재시작합니다. 작은규모라면 상관없는데 큰 프로젝트라면 병목현상이 생길 수 있습니다.

변경된 파일만 bundle하여 변경사항을 적용시키는 방법이 핫 리로딩입니다.

 

🟩 Nest의 핫 리로딩 적용하는법

👉 1번.

프로젝트에

npm i --save-dev webpack-node-externals run-script-webpack-plugin webpack

패키지들을 설치합니다. 

 

👉 2번.

루트폴더에 webpack-hms.config.js 라는 파일을 생성해 줍니다.

 

webpack-hms.config.js

const nodeExternals = require('webpack-node-externals');
const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin');

module.exports = function (options, webpack) {
  return {
    ...options,
    entry: ['webpack/hot/poll?100', options.entry],
    externals: [
      nodeExternals({
        allowlist: ['webpack/hot/poll?100'],
      }),
    ],
    plugins: [
      ...options.plugins,
      new webpack.HotModuleReplacementPlugin(),
      new webpack.WatchIgnorePlugin({
        paths: [/\\.js$/, /\\.d\\.ts$/],
      }),
      new RunScriptWebpackPlugin({
        name: options.output.filename,
        autoRestart: false,
      }),
    ],
  };
};

위 파일 require 부분에 에러가 난다면 tsconfig.json 파일을 수정해야 합니다.

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "esModuleInterop": true, // import * as React from React 해야하는것을 => import react from React 해도 되게 만듬
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false
  }
}

esModuleInterop를 true로 만들어줍니다.

 

👉 3번

main.ts 파일에 핫 리로딩을 적용해줍니다.

 

main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

declare const module: any;

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const port = process.env.PORT || 3000;
  await app.listen(port);
  console.log(`listening on port ${port}`);

  // 핫 리로딩 적용
  if (module.hot) {
    module.hot.accept();
    module.hot.dispose(() => app.close());
  }
}
bootstrap();

이 함수는 기본 웹팩 구성이 포함된 원본 객체를 첫 번째 인수로, Nest CLI에서 사용하는 기본 웹팩 패키지에 대한 참조를 두 번째 인수로 받습니다. 

이 함수는 HotModuleReplacementPlugin, WatchIgnorePlugin 및 RunScriptWebpackPlugin 플러그인을 사용하여 수정된 웹팩 구성을 반환합니다.

 

 

👉 4번

package.json의 start:dev를 webpack을 통해 빌드하도록 다시 바꿔줍니다.

"start:dev-backup": "nest start --watch",
"start:dev": "nest build --webpack --webpackPath webpack-hmr.config.js --watch",

공식문서에 나와있는대로 했습니다.

 

 

🟩 Nest Cli 없이 핫 리로딩 적용하는법

👉 1번.

프로젝트에

npm i --save-dev webpack webpack-cli webpack-node-externals ts-loader run-script-webpack-plugin

패키지들을 설치합니다. 

 

👉 2번.

루트폴더에 webpack.config.js 라는 파일을 생성해 줍니다.

 

webpack.config.js

const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin');

module.exports = {
  entry: ['webpack/hot/poll?100', './src/main.ts'],
  target: 'node',
  externals: [
    nodeExternals({
      allowlist: ['webpack/hot/poll?100'],
    }),
  ],
  module: {
    rules: [
      {
        test: /.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  mode: 'development',
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new RunScriptWebpackPlugin({ name: 'server.js', autoRestart: false }),
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'server.js',
  },
};

 

👉 3번

main.ts 파일에 핫 리로딩을 적용해줍니다.

 

main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

declare const module: any;

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const port = process.env.PORT || 3000;
  await app.listen(port);
  console.log(`listening on port ${port}`);

  // 핫 리로딩 적용
  if (module.hot) {
    module.hot.accept();
    module.hot.dispose(() => app.close());
  }
}
bootstrap();

이 설정은 엔트리 파일의 위치, 컴파일된 파일을 저장하는 데 사용할 디렉토리, 소스 파일을 컴파일하는 데 사용할 로더의 종류 등 애플리케이션에 대한 몇 가지 필수 사항을 웹팩에 알려줍니다. 

 

 

👉 4번

package.json의 start:dev를 webpack을 통해 빌드하도록 다시 바꿔줍니다.

 

"start:dev-backup": "nest start --watch",
"start:dev": "webpack --config webpack.config.js --watch"

 

728x90