View

반응형

애증의 밴딩머신 타입스크립트로 마이그레이션 진행기

바닐라 자바스크립트에 타입스크립트?

처음엔 단순히 타입스크립트를 설치하고 파일 확장자를 .ts로 바꿔주면 되겠지? 라고 생각했다.
당연하게도 그렇게 쉽게 언어가 컴파일되지 않는다 ^^...ㅎ

리액트에서는 cra를 사용했기때문에 자동적으로 웹팩환경이 구성된 상황에서 개발을 했었다.
그래서 내가 작성한 코드가 어떻게 빌드되고, 어떻게 컴파일되는지 자세히 알지 못했다.
하지만 바닐라 자바스크립트에서는 cra같은 손쉬운 셋팅이 없다. 모두 직접 구성을 해야만 했다.

그렇게 웹팩공부를 하게 되는데...🫠

바닐라 자바스크립트에서 타입스크립트를 사용하기 위한 웹팩 환경 구성하기 🦾

우선 타입스크립트를 자바스크립트 언어로 컴파일하기 위한 환경을 셋팅해야했다.
웹팩 시리즈 내용은 여기 > 웹팩 알아보기 시리즈

어느정도 웹팩에 대해 알았다면 이제 차근차근 순서대로 셋팅을 해보자.

1. 프로젝트 버전관리 시작하기.

npm init -y

2. .gitignore 설정하기

//.gitignore

# dependencies
/node_modules

# production
/dist

# etc
.DS_Store
.vscode

3. 패키지들을 설치.

프로젝트에 사용된 패키지 리스트
  • Webpack
    • webpack : 웹팩을 사용하기 위함.
    • webpack-cli : CLI환경에서 웹팩을 사용하기 위함.
    • webpack-dev-server : 웹팩에서 개발환경을 띄우기 위함. (dev-server에서 변경되는 소스코드들은 오직 메모리상에서만 존재한다.)
  • Webpack plugin
    • copy-webpack-plugin : static요소를 dist 디렉토리로 복사해주는 패키지.
    • html-webpack-plugin : html 기본 템플릿을 만들어주는 패키지.
    • json-minimizer-webpack-plugin : json 파일을 경량화해주는 패키지.
    • mini-css-extract-plugin : css파일을 별도로 추출해주는 패키지.
    • tsconfig-paths-webpack-plugin : tsconfig-path경로를 설정해주는 패키지.
  • Babel
    • @babel/core : babel을 사용하기 위해 설치.
    • @babel/plugin-proposal-class-properties : class속성에 대한 폴리필.
    • @babel/preset-env : 예전 브라우저들을 지원.
    • @babel/preset-typescript : 타입스크립트파일을 컴파일하기 위함.
    • core-js : 전역 오염성이있는 pollyfill 대신 사용하는 폴리필.
    • whatwg-fetch : Web API인 fetch 호환을 위해 사용하는 폴리필.
  • scss
    • sass : css 전처리기.
    • sass-loader : sass파일을 css로 변환.
    • css-loader : css파일을 html문서 head영역에 인라인방식으로 스타일코드를 추가해주기 위함.
  • TypeScript
    • typescript
    • ts-loader : typescript파일을 컴파일 하기 위해 설치 (webpack)
  • Prettier
    • prettier
    • eslint-config-prettier : eslint가 prettier과 충돌되는 부분을 비활성화.
    • eslint-plugin-prettier : prettier에서 인식하는 코드상의 포맷 오류를 eslint로 출력.
  • ES Lint
    • eslint
    • eslint-plugin-import-helpers : export / import 구문을 사용할수 있고, 경로 및 파일이름의 린트설정.
    • @typescript-eslint/parser : 타입스크립트용 eslint파서.
    • @typescript-eslint/eslint-plugin : 타입스크립트 관련 linting 규칙을 처리하는 플러그인.

3.1 webpack 설정

npm i -D webpack webpack-cli webpack-dev-server

개발환경에서만 사용될 것이기 때문에 -D 로 추가해준다.

  • webpack : 웹팩을 사용하기 위함.
  • webpack-cli : CLI환경에서 웹팩을 사용하기 위함.
  • webpack-dev-server : 웹팩에서 개발환경을 띄우기 위함. (dev-server에서 변경되는 소스코드들은 오직 메모리상에서만 존재한다.)

package.json 설정

  • 스크립트 안에 build, dev, start 명령어를 추가한다.
// package.json
{
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack-dev-server --mode development --open",
    "start": "webpack-dev-server --mode production --open"
  }
}
  • build : webpack.config 파일에서 설정한 내용으로 파일을 빌드해주는 명령어
  • dev : 웹팩 개발서버를 여는 명령어
  • start : 프로덕션 모드를 여는 명령어 (빌드후 파일 체크)

webpack.config.js 설정

// webpack.config.js
const path = require('path')
const HtmlPlugin = require('html-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')

module.exports = {
  entry: ['./src/main.ts', './src/scss/index.scss'],
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/[name].bundle.js',
    clean: true
  },
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif|svg)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'assets/images/[name][ext]'
        }
      }
    ]
  },
  devtool: 'inline-source-map',
  devServer: {
    client: {
      logging: 'none'
    }
  },
  plugins: [
    new HtmlPlugin({
      template: './public/index.html',
      favicon: path.resolve(__dirname, 'public/favicon.ico')
    }),
    new CopyPlugin({
      patterns: [{ from: 'public/favicon.ico' }]
    })
  ]
}

3.2 TypeScrip + webpack 관련 설정

npm i -D typescript ts-loader tsconfig-paths-webpack-plugin

tsconfig.json 설정

// tsconfig.json
{
  "extends": "./tsconfig.path.json",
  "module": "ESNext",
  "include": ["src/**/*", "src/custom.d.ts"],
  "outDir": "./dist/js",
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "ESNext"],
    "allowJs": true,
    "checkJs": true,
    "sourceMap": true,
    "esModuleInterop": true,
    "noImplicitAny": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "isolatedModules": true
  }
}

tsconfig.path.json 설정

  • 파일 경로를 지정해주기 위해 추가적으로 설정
  • 이 파일은 설정하고나면 개발서버를 열었을때 src진입점 아래에 ts파일이 무조건 하나라도 있어야 오류를 뿜지않는다.
// tsconfig.path.json
{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@assets": ["./assets"],
      "@assets/*": ["./assets/*"],
      "@api": ["./api"],
      "@api/*": ["./api/*"],
      "@utils": ["./utils"],
      "@utils/*": ["./utils/*"],
      "@constants": ["./constants"],
      "@constants/*": ["./constants/*"],
      "@components": ["./components"],
      "@components/*": ["./components/*"]
    }
  }
}

webpack.config.js 추가 설정

//webpack.config.js
...
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin')
const tsConfigPath = path.resolve(__dirname, './tsconfig.json')

module.exports = {
  ...
  resolve: {
    extensions: ['.ts', '.js'],
    plugins: [
      new TsconfigPathsPlugin({
        configFile: tsConfigPath
      })
    ]
  },
  module: {
    rules: [
  ...
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/
      },
  ]
}

3.3 SCSS + Webpack 관련 설정

npm i -D sass sass-loader css-loader mini-css-extract-plugin

webpack.config.js 추가 설정

// webpack.config.js
...
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
...
  module: {
    rules: [
  ...
      {
        test: /\.s[ac]ss$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
        exclude: /node_modules/
      },
  ...
  plugins: [
  ...
    new MiniCssExtractPlugin({
      filename: 'assets/css/style.[contenthash].css'
    }),
  ],
}

3.4 Bable 설정

npm i -D @babel/core @babel/preset-env @babel/preset-typescript @babel/plugin-proposal-class-properties
npm i core-js whatwg-fetch

webpack.config.js 추가 설정

// webpack.config.js
module.exports = {
...
  module: {
    rules: [
  ...
      {
        test: /\.m?js$/,
        include: [path.resolve(__dirname, 'src')],
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  useBuiltIns: 'usage',
                  corejs: 3
                }
              ],
              '@babel/preset-typescript'
            ],
            plugins: ['@babel/plugin-proposal-class-properties']
          }
        }
      }
   ]
}
...

3.5 ES Lint 설정

npm i -D eslint eslint-plugin-import-helpers @typescript-eslint/parser @typescript-eslint/eslint-plugin

.eslintrc.js 설정

// .eslintrc.js
module.exports = {
  root: true,
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: './tsconfig.json'
  },
  plugins: ['@typescript-eslint', 'eslint-plugin-import-helpers'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended'
  ],
  ignorePatterns: ['webpack.config.js', '**/*.config.js', '.eslintrc.js'],
  rules: {
    'import-helpers/order-imports': [
      'error',
      {
        newlinesBetween: 'never',
        groups: [
          'absolute',
          'module',
          ['parent', 'sibling', 'index'],
          '/^@shared/'
        ],
        alphabetize: { order: 'asc', ignoreCase: true }
      }
    ],
    'no-prototype-builtins': 0,
    '@typescript-eslint/array-type': ['error', { default: 'array' }],
    '@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
    '@typescript-eslint/consistent-type-imports': 'error',
    '@typescript-eslint/explicit-function-return-type': 'error',
    '@typescript-eslint/member-ordering': 'error',
    '@typescript-eslint/method-signature-style': ['error', 'method'],
    '@typescript-eslint/no-confusing-void-expression': 'error',
    '@typescript-eslint/no-duplicate-imports': 'error',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/type-annotation-spacing': 'error'
  }
}

package.json 추가 설정

// package.json
"scripts": {
  ...
  "lint": "eslint ./src/**/*.ts",
  "lint:fix": "tsc --noEmit && eslint --fix ./src/**/*.ts"
},

3.6 Prettier 설정

npm i -D prettier eslint-plugin-prettier eslint-config-prettier
// .prettierrc.json
{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": false,
  "singleQuote": true,
  "quoteProps": "as-needed",
  "jsxSingleQuote": false,
  "trailingComma": "none",
  "bracketSpacing": true,
  "bracketSameLine": true,
  "arrowParens": "avoid",
  "endOfLine": "auto"
}

3.7 json 파일 추출 플러그인 설정 (json파일을 사용할 경우에 셋팅)

npm i -D json-minimizer-webpack-plugin

webpack.config.js 추가 설정

// webpack.config.js
...
const JsonMinimizerPlugin = require('json-minimizer-webpack-plugin')

module.exports = {
...
  module: {
    rules: [
    ...
      {
        test: /\.json$/i,
        type: 'asset/resource'
      },
    ...
  plugins: [
  ...
    new CopyPlugin({
      patterns: [
        {
          context: path.resolve(__dirname, 'src'),
          from: './data/*.json'
        }
      ]
    })
  ],
  optimization: {
    minimize: true,
    minimizer: [new JsonMinimizerPlugin()]
  }
}

이렇게 해주면 바닐라 타입스크립트 웹팩 설정이 끝이난다.
이 과정을 마치고 나서야! 드디어! 타입스크립트로 변환을 할 수 있게된다.

반응형

'FRONT-END > TypeScript' 카테고리의 다른 글

내가 보려고 기록하는 tsconfig.json 설정  (0) 2022.09.08
Share Link
댓글
반응형
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31