[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"