본문 바로가기

front_end/webpack

bun 환경에서 webpack + typescript 설정하기

bun init


bun project 생성

bun init

필요한 패키지


bun add -D webpack webpack-cli webpack-dev-server @types/webpack @types/webpack-dev-server

패키지 설명

  1. webpack, webpack-cli = webpack과 webpack을 cli환경에서 사용할 수 있게 해줌
  2. webpack-dev-server = 라이브 리로딩 등을 제공해 주는 개발 서버
    3 @types/webpack, @types/webpack-dev-server = 웹팩의 타입을 정의해놓은 패키지

Webpack 설정 해보기


프로젝트 루트 디렉터리에 webpack 폴더, webpack.config.ts 만들기

# root dir 에서
touch ./webpack.config.ts

index.html, src 디렉터리, src/index.ts 만들기

# root dir 에서
touch index.html; mkdir src; touch ./src/index.ts

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>WEBPACK!</title>
  </head>
  <body>
    <h1>HELLO!</h1>
  </body>

  <script src="./dist/bundle.js"></script>
</html>

src/index.ts

console.log("HELLO!");

/webpack.config.ts

해야 할 일!
엔트리 포인트 설정,
output 위치 설정,
타입스크립트 번들링을 위한 로더 설정
Mode(production, development)별 파일 분리

webpack 엔트리포인트 설정하기

기본값은 ./src/index.js로 설정되어 있으나, typescript를 사용해야 하기 때문에 ./src/index.ts로 명시해준다.

import { Configuration } from "webpack";    // webpack config 객체의 타입 선언 파일

const config: Configuration = {
  entry: "./src/index.ts",
};

export deafult config;

webpack output 설정

기본값(번들링된 자바스크립트 파일)은 ./dist/main.js로, 생성된 기타 파일 (css, 이미지 등)은 ./dist로 설정되어 있다.

import path from "path";
import { Configuration } from "webpack";

const config: Configuration = {
  entry: "./src/index.ts",
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "bundle.js",
  },
};

export deafult config;

이렇게 작성을 한 후에 bun webpack --config ./webpack.config.ts로 실행을 해 보면,

[webpack-cli] Unable load 'webpack.config.ts'
[webpack-cli] Unable to use specified module loaders for ".ts".
[webpack-cli] Cannot find module 'ts-node/register'
[webpack-cli] Cannot find module 'sucrase/register/ts'
[webpack-cli] Cannot find module '@babel/register'
[webpack-cli] Cannot find module 'esbuild-register/dist/node'
[webpack-cli] Cannot find module '@swc/register' 
[webpack-cli] Please install one of them

이런 에러가 뜨는데, 이를 해결해 주기 위해 esbuild, esbuild-register 패키지를 설치해 준다

bun add -D esbuild esbuild-register
bun webpack --config ./webpack.config.ts
asset bundle.js 22 bytes [emitted] [minimized] (name: main)
./src/index.ts 23 bytes [built] [code generated]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

webpack 5.88.2 compiled with 1 warning in 80 ms

mode 옵션을 설정하지 않았다는 워닝과 함께 번들링이 되는 모습을 볼 수 있다.

bun은 ts-node등과 다르게 webpack config 파일 상에서 따로 option을 주지 않아도 번들링이 되는 것을 볼 수 있다.

전체 코드 보기

Webpack Config 파일 mode에 따라 분리하기


먼저 webpack 폴더를 만든 후, webpack config을 세 종류로 분리한다. (webpack.common.config.ts, webpack.dev.config.ts, webpack.prod.config.ts)

mkdir webpack; touch ./webpack/webpack.common.config.ts; touch ./webpack/webpack.dev.
config.ts; touch ./webpack/webpack.prod.config.ts;

후에, webpack.common.config.ts에 이전에 써 놓았던 내용을 그대로 붙여넣기 한 다음, 객체 이름을 config에서 commonConfig으로 바꿔준다.
그리고, 디렉터리가 root dir에서 ./webpack 으로 바뀌었기 때문에 output의 path를 "./dist" 에서 "../dist"로 바꿔준다

import path from "path";
import { Configuration } from "webpack";

const commonConfig: Configuration = {
  entry: "./src/index.ts",
  output: {
    path: path.resolve(__dirname, "../dist"),
    filename: "main.js",
  },
};

export default commonConfig;

이제 common을 베이스로 하는 dev.config 파일과 prod.config 파일이 있는데, 두 가지 webpack config 파일을 merge 해 줄 방법이 필요하다. 이 때 사용되는 패키지가 webpack-merge로, common에서 작성했던 config을 다른 파일에서 사용가능하게 해 준다.

bun add -D webpack-merge

webpack.prod.config

import { Configuration } from "webpack";
import commonConfig from "./webpack.common.config";
import { merge } from "webpack-merge";

const prodConfig: Configuration = merge(commonConfig, {
  mode: "production",
});

export default prodConfig;

webpack.dev.config

import { Configuration } from "webpack";
import commonConfig from "./webpack.common.config";
import { merge } from "webpack-merge";

const prodConfig: Configuration = merge(commonConfig, {
  mode: "development",
});

export default prodConfig;

prod 모드에서 실행하려면 bun webpack --config ./webpack/webpack.prod.config.ts 를 이용해 주면 되고, dev 모드에서 실행하려먼 bun webpack --config ./webpack/webpack.dev.config.ts를 사용 해 주면 되는 데, 번거롭기 때문에 package.json에 script를 작성해준다

package.json

"scripts": {
    "build": "webpack --config webpack/webpack.prod.config.ts",
    "dev": "webpack --config webpack/webpack.dev.config.ts"
  }

이렇게 작성 한 이후에 bun run build, bun run dev 또는 bun dev 명령어로 실행할 수 있다.

전체 코드 보기

webpack dev server 세팅하기


live reload 등을 사용하기 위해서는 webpack-dev-server을 이용해야 한다.

webpack.dev.config.ts

import path from "path";
import { Configuration as WebpackConfiguration } from "webpack";
import { Configuration as WebpackDevServerConfiguration } from "webpack-dev-server";
import commonConfig from "./webpack.common.config";
import { merge } from "webpack-merge";

// webpack에 들어있는 Configuration 에는 devServer property가 없으므로 새로 만들어준다
interface Configuration extends WebpackConfiguration {
  devServer?: WebpackDevServerConfiguration;
}

const prodConfig: Configuration = merge(commonConfig, {
  mode: "development",
  devServer: {
    port: 9000,
    static: {
      directory: path.resolve(__dirname, ".."),
    },
    devMiddleware: {
      index: "index.html", // root url 에서 표시할 html 파일
      writeToDisk: true, // webpack config에 지정된 디렉터리에 (dist) 파일을 쓰겠다는 뜻
    },
    client: {
      overlay: true, // 오류가 생겼을 때, 화면 위에 에러를 표시해준다.
    },
    liveReload: true, // false로 지정 후 webpack serve 에 --hot 플래그를 넣어줘도 된다.
  },
});

export default prodConfig;

hot reloading을 포함하는 dev-server를 사용하려면, 기존의 webpack ~ 명령이 아닌 webpack serve 명령을 사용해줘야 한다. 기존 bun run dev 스크립트를 webpack serve로 수정해준다

"dev": "webpack serve --config webpack/webpack.dev.config.ts"

dev 환경일 때 source-map 설정


웹팩은 번들링하는 툴이기 때문에 작성해놓은 모든 js 파일이 하나로 합쳐져 나오게 된다. 이 때문에 디버깅 할 때 어디서 오류가 발생했는지 알기가 쉽지 않기 때문에 source-map을 이용해 오류가 발생한 파일의 source를 알아야할 필요가 있다.

wepback source map 공식 도큐먼트

각 source-map 별로 장단이 있으나, 지금은 eval-cheap-module-source-map을 사용하기로 한다

import path from "path";
import { Configuration as WebpackConfiguration } from "webpack";
import { Configuration as WebpackDevServerConfiguration } from "webpack-dev-server";
import commonConfig from "./webpack.common.config";
import { merge } from "webpack-merge";

interface Configuration extends WebpackConfiguration {
  devServer?: WebpackDevServerConfiguration;
}

const prodConfig: Configuration = merge(commonConfig, {
  mode: "development",
  devtool: "eval-cheap-module-source-map",
  devServer: {
    port: 9000,
    static: {
      directory: path.resolve(__dirname, ".."),
    },
    devMiddleware: {
      index: "index.html",
      writeToDisk: true,
    },
    client: {
      overlay: true,
    },
    liveReload: true,
  },
});

export default prodConfig;

전체 코드 보기