[Project] javaScript에 webpack 달기 ⭐

young_pallete·2021년 9월 1일
2

no#tation

목록 보기
4/11
post-thumbnail
post-custom-banner

시작하며 🌈

오늘은 웹팩 번들러를 달았어요!
사실 Parcel을 할까도 굉장히 고민이 많았어요.
결국 번들러도 상황에 맞는 선택이라 생각하는데, 현재 프로젝트가 작은데다, 굳이 엄~청 디테일한 옵션을 달 게 없어서, parcel만으로도 충분했기 때문이에요.

사실 웹팩을 달기 위한 이유는 다음과 같았어요.

  1. 언젠가 먼 미래에, 디테일한 설정을 위해 webpack과 친해질 일이 필요하겠다! (사실, 프로젝트의 목적이 제 실력을 증빙하기 위한 거니까요!)
  2. 따라서 설정해본 적은 있어도, 직접 욕심내며 설정해본 적은 없다! 이 참에 도전해보자!!
  3. 지금 당장 npm 패키지를 달고 싶은데, 라이브러리는 현재 module 타입으로 불러올 수 없다. 그렇다고 cjs, mjs로 모두 일간성 있게 통일시키기는 굳이...?라는 생각이 든다. 따라서 이를 모듈로 쉽게 불러오려면 번들러 사용이 적합하겠다!
  4. 빌드할 시, 성능도 빨라질 뿐더러 (모듈을 하나로 통합시키기 때문), HMR 기능도 충분히 잘 제공하고 있어서, 이를 개발 환경 서버로 이용하기 좋아보였다!

그래서 어떻게 보면 계륵인 이 친구랑, 이번에 친해지기로 마음을 먹었어요.

그렇다면, 어떻게 제가 이 친구를 사용할 수 있게 됐는지, 과정을 살펴보죠!

package.json

저는 다음과 같이 패키지를 설치했답니다. 꼭 참고해주세요!

{
  "type": "module",
  "name": "no-hesitation",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {
    "@babel/polyfill": "^7.12.1",
    "dotenv": "^10.0.0",
    "normalize.css": "^8.0.1"
  },
  "devDependencies": {
    "@babel/cli": "^7.14.8",
    "@babel/core": "^7.15.0",
    "@babel/plugin-proposal-class-properties": "^7.14.5",
    "@babel/preset-env": "^7.15.0",
    "babel-eslint": "^10.1.0",
    "babel-loader": "^8.2.2",
    "clean-webpack-plugin": "^4.0.0-alpha.0",
    "css-loader": "^6.2.0",
    "eslint": "^7.32.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^3.4.1",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^5.3.2",
    "mini-css-extract-plugin": "^2.2.1",
    "node-sass": "^6.0.1",
    "prettier": "^2.3.2",
    "sass-loader": "^12.1.0",
    "style-loader": "^3.2.1",
    "url-loader": "^4.1.1",
    "webpack": "^5.51.1",
    "webpack-cli": "^4.8.0",
    "webpack-dev-server": "^4.1.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "lint": "eslint src",
    "lint:fix": "eslint src --fix",
    "dev:webpack": "webpack-dev-server --mode development",
    "build": "webpack --mode production"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/JengYoung/No-Hesitation.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/JengYoung/No-Hesitation/issues"
  },
  "homepage": "https://github.com/JengYoung/No-Hesitation#readme"
}

이렇게 하면, 이제 저희가 필요할 웹팩 설정들이 완료가 돼요!

webpack.config.js

이제 여기서 우리는 꼭 알아야 할 친구들이 있어요. entry output module rules 등인데요!

정~말 간단히 짚고 넘어가볼까요?

  • entry 니 어데서 시작하나 ?!
  • output 니 결과물 어따 내뱉을래 ?!
  • module 니 모듈로 내뱉을 때 어떤 규칙으로 할낀대 !
  • plugin 이제 번들된 거 어떻게 처리할래?!
  • devServer 서버 어떻게 옵션 설정할낀대!

입니다. 생각보다 간단하죠?! 저도 이게 처음에는 정~말 당황스러웠어요.
하지만 다음과 같은 생각을 하니, 좀 간단해졌습니다.

이거 결국에는 module.export = {...} 잖아?
그럼 모듈로 내뱉어져서 일종의 객체처럼 쓸 건데, 그럼 결국에는 어떤 api쓸 때 옵션 쓰는거랑 비슷한 거 아냐?!

결국에 우리는 어떤 어려운 것들을 처리하기 위해, 웹팩이란 걸 썼을 뿐입니다. 그리고 그저 웹팩은 모듈인 파일들을 번들시켜줄 뿐이구요! 생각보다 겁 먹을 일이 없더라구요!

그럼, 내용물을 볼까요?

const path = require('path');
const HtmlPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: ['@babel/polyfill', './src/index.js', './src/sass/main.scss'],
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  devServer: {
    static: './dist',
    hot: true, // 이게 HMR을 가능하게 해줘요!!
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [path.resolve(__dirname, 'src')],
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            plugins: ['@babel/plugin-proposal-class-properties'],
          },
        },
      },
      {
        test: /\.png$/, // .png 확장자로 마치는 모든 파일
        loader: 'file-loader',
        options: {
          publicPath: './dist/', // prefix를 아웃풋 경로로 지정
          name: '[name].[ext]?[hash]', // 파일명 형식
        },
      },
      {
        test: /\.png$/,
        use: {
          loader: 'url-loader', // url 로더를 설정한다
          options: {
            publicPath: './dist/', // file-loader와 동일
            name: '[name].[ext]?[hash]', // file-loader와 동일
            limit: 10000, // 10kb 미만 파일만 data url로 처리
          },
        },
      },
      {
        test: /\.s?css$/,
        use: [
          'style-loader', // creates style nodes from JS strings
          'css-loader', // translates CSS into CommonJS
          'sass-loader', // compiles Sass to CSS, using Node Sass by default
        ],
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new HtmlPlugin({
      template: './index.html',
      hash: true,
    }),
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({ filename: 'css/style.css' }),
  ],
  devtool: 'source-map',
  mode: 'development',
};

네, 저는 다음과 같이 빌드할 옵션들을 설정해줬어요.

솔직히 저도 거의 다 참고하면서 작성했지만 일부 핵심들만 살펴보자면 다음과 같아요.

babel-loader

바벨, 참 고마운 친구에요! 이 친구 없으면 우리는 정말 🐶고생을 해야 한답니다...!
이 친구가 이제 js 파일에 대해서 잘~처리해줄 건데요, presetplugin이 필요해요.
일단 저런 것들을 설정해준다면, 자바스크립트의 최신 문법을 지원하지 않는 브라우저에서도 쓸 수 있도록 해줍니다!

조만간 이는 바벨 포스팅으로 다뤄볼게요 😝

style-loader

js와 호환되어 만들어진 css를 style 태그로 만들어 직접 붙여주는 (역할을 해요! 말이 좀 어렵긴 한데, 저는 다음과 같이 이해했답니다)

결과적으로는 다음과 같죠!

어때요! 잘 붙여졌죠?!

그리고 플러그인의 경우에는 조심해야 할 게, 저 순서에 유의해서 붙여줘야 한답니다!!! 제가 알기로는 뒤에서부터? 처리되는 걸로 알고 있어요!

html-webpack-plugin

제 일차적인 목적은 결국 index.html을 빌드해서 서버 환경으로 띄워놓는 거였어요. 따라서 저와같이 html의 형태로 만들어야 하실 분들은 이 플러그인이 반드시 필요하답니다.

  • template
    대상 html을 지정하면 돼요! 대부분이 index.html이겠지만요!
  • hash
    페이지를 왔다갔다할 때, 이 파일이 과거의 파일인지, 지금의 파일인지가 구분이 안 갈 수 있는데, 이를 파일 제목 뒤에 해시값을 넣음으로써 해결해주는 좋은 옵션입니다!

clean-webpack-plugin

빌드를 한 다음에, 이전에 했던 결과물이 남아 있으면 딱히 좋을 게 없죠? 이를 처리해주는 고마운 친구에요~~

mini-css-extract-plugin

css도 결국 번들되면, 하나의 파일로 남는데요!
그렇게 되면 큰 파일을 다운로드 받기가 꽤나 부담일 수 있어요.
차라리 일단 번들하되, 역할에 따라 css파일을 잘게 나눠서 속도를 높이자!는 취지에서 설정한 플러그인입니다!

네, 결과적으로 잘 되나 볼까요?!

네, 성공했읍니다!!!

마치며 👏

솔직히 이 글이 제가 지금 프로젝트하면서 급하게 쓴 거라, 헷갈릴 수 있는데요!
만약 처음이시라면 꼭 저 5가지만 살~짝씩만 공부하셔도, 무난히 가능할 거에요!

  • module(loader, rules)
  • entry
  • output
  • devServer
  • plugin

결국 이 친구들이 핵심이고, 나머지는 더욱 설정해준다! 라고 생각하시면 되겠습니다.

그래도 헷갈리면, 우리가 map을 쓸 때, 3번째 인자가 있음에도 쓰지 않죠?!
결국 디테일한 설정들은 취사선택이고,
저 5가지 애들이 map 메서드에서 keyindex 번호에 대한 매개변수 정도의 중요한 애들이라고 보면 돼요!
그렇다고, 나머지 친구들을 과소평가하는 건 절대 금물!! ❌❌

그럼, 다들 즐거운 프로젝트하세유!!

profile
People are scared of falling to the bottom but born from there. What they've lost is nth. 😉
post-custom-banner

0개의 댓글