개발환경시리즈② webpack

김수정·2020년 6월 7일
0

webpack을 사용하는 이유

웹팩은 모듈 번들러 입니다. 모듈은 전역을 최대한 더럽히지 않고, 독립적인 코드를 작성하여 조합하여 개발하는 방식입니다. 모듈 방식의 개발은 scope관리를 편리하게 해줍니다. 번들러는 이런 모듈들의 의존관계를 파악하여 합쳐주는 패키지 같은 것입니다. 웹팩은 번들링을 통해 용량을 줄여줍니다.

install

webpack과 터미널에서 webpack을 사용할 수 있게 해주는 webpack-cli를 설치합니다.

$ npm install -D webpack webpack-cli

execution

webpack을 실행할 때는 최소 3개의 기본 옵션을 꼭 작성해야 합니다. mode, entry point, output point.

  1. 터미널 명령어로 죽 늘어서 실행할 수 있습니다.
$ node_modules/.bin/webpack --mode development --entry ./src/app.js --output dist/main.js
  1. webpack.config.js
    매번 터미널 명령어를 사용하여 만들긴 힘들기 때문에, webpack관련된 설정을 한 파일에 모아두고, package.json에서 npm명령어로 실행되도록 script를 작성합니다.
// package.json
...
"scripts": {
  "build": "webpack"
},
...

options

mode

development, production, none 중에 선택할 수 있습니다.
development - 개발하기 쉬운 환경으로 빌드합니다.
production - 압축, 난독화 진행하여 빌드합니다.
none - 아무 설정도 안함.

entry/output

진입점과 결과물을 정하는 옵션입니다. 진입점과 결과물이 여러 개일 수 있으므로 아래와 같이 작성합니다. [name]으로 작성하면 entry 키 값으로 계산되어 이름이 됩니다.

// webpack.config.js
const path = require('path');

module.exports = {
  mode: 'development',
  entry: {
    main: './src/app.js',
  },
  output: {
    path: path.resolve('./dist'),
    filename: '[name].js',
  },
};

loader

module객체에 추가해줍니다. test키는 파일명 혹은 정규표현식으로 해당하는 파일을 지정해주고, use는 사용하는 로더경로를 적어줍니다.
이러면 빌드할 때 오류는 나지 않지만 브라우저에 css명령이 먹히진 않습니다. 그래서 style loader를 설치합니다.

css loader
자바스크립트에서 css파일을 모듈로 불러올 수 있습니다.

$ npm install -D css-loader
// webpack.config.js
module.exports = {
  module: {
    rules: [{
      test: /\.css$/, // .css 확장자로 끝나는 모든 파일 
      use: ['css-loader'], // css-loader를 적용한다 
    }]
  }
}

style loader
돔에서 html에 스타일을 입히려면 css가 cssom으로 변환되어야 합니다. 그런데 css loader는 자바스크립트에 css를 모듈처럼 불러오게 해줄 뿐, om이 되진 않습니다. style-loader는 자바스크립트로 변경된 스타일을 동적으로 돔에 추가해 줍니다. style태그로 head안에 들어가 있는데 이 때문에 모든 css가 전역에 다 불러와지는 효과가 있습니다;;; use에 로더를 여러개를 사용하면 뒤에서부터 순차적으로 로더를 적용합니다.

$ npm install -D style-loader
// webpack.config.js
module.exports = {
  module: {
    rules: [{
      test: /\.css$/,
      use: ['style-loader', 'css-loader'], // style-loader를 앞에 추가한다 
    }]
  }
}

file loader
이미지 파일 등을 모듈화 시켜줍니다.

  • publicPath: 빌드 됐을 때 경로를 지정해 줍니다.
  • name: 파일이름
$ npm install -D file-loader
module.exports = {
  module: {
    rules: [
      ...
      {
        test: /\.png$/,
        loader: 'file-loader',
        options: {
          publicPath: './dist/',
          name: '[name].[ext]?[hash]',
        },
      },
    ],
  },
};

url-loader
이미지 리소스를 data64로 바꿔줍니다. 데이터 크기가 작은 이미지일 때 사용합니다. 이를 사용해놓으면 options에 기본 폴백이 file-loader로 되어있으므로 limit이 넘어가는 파일은 자동으로 file-loader로 처리됩니다. 뭔가 쓰지 않아도 설치는 되어 있어야 겠죠?

$ npm install -D url-loader
module.exports = {
  module: {
    rules: [
      ...
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'url-loader',
        options: {
          publicPath: './dist/',
          name: '[name].[ext]?[hash]',
          limit: 20000, // 20kb
        },
      },
    ],
  },
};

plugin

로더는 파일 단위로 처리하는 반면 플러그인은 번들된 결과물을 처리합니다.

BannerPlugin
빌드된 파일 최상단에 주석 달아주는 플러그인

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.BannerPlugin({
      banner: '이것은 배너 입니다',
    })
  ]

DefinePlugin
빌드 타임에 결정되는 환경 변수를 어플리케이션에 주입하기 위함.
빈 객체를 넘겨도 process.env.NODE_ENV는 웹팩의 mode로 들어감.

const webpack = require('webpack');

export default {
  plugins: [
    new webpack.DefinePlugin({}),
  ]
}

HtmlTemplatePlugin
html도 빌드 파일에 넣을 수 있게 됨. 웹팩 내장 플러그인이 아니라서 다운 받아야 합니다.

$ npm install -D html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html', // 템플릿 경로를 지정 
      templateParameters: { // 템플릿에 주입할 파라매터 변수 지정
        env: process.env.NODE_ENV === 'development' ? '(개발용)' : '', 
      },
    })
  ]
}

빌드 할 때 env를 따지기 때문에 build명령을 할 때 환경을 설정해주어야 합니다.

NODE_ENV=development npm run build

CleanWebpackPlugin
빌드할 때마다 output폴더를 삭제하고 재로드함

$ npm install -D clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  plugins: [
    new CleanWebpackPlugin(),
  ]
}

MiniCssExtractPlugin
빌드된 js파일에서 css파일만 떼어내주는 플러그인. 파일이 커지는 걸 방지해주고 효율적인 관리를 도와줍니다.

$ npm install -D mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    ...(
      process.env.NODE_ENV === 'production' 
      ? [ new MiniCssExtractPlugin({filename: `[name].css`}) ]
      : []
    ),
  ],
}

이 플러그인은 로더도 같이 세팅해주어야 합니다.

module.exports = {
  module: {
    rules: [{
      test: /\.css$/,
      use: [
        process.env.NODE_ENV === 'production' 
        ? MiniCssExtractPlugin.loader  // 프로덕션 환경
        : 'style-loader',  // 개발 환경
        'css-loader'
      ],
    }]
  }
}

webpack-dev-server

프론트엔드 환경에서 개발 서버를 제공해 주는 것입니다.
axios호출이나 실시간 로딩 등에 필요합니다.

$ npm i -D webpack-dev-server
// package.json
{
  "scripts": {
    "start": "webpack-dev-server"
  }
}
$ npm start

웹팩 개발 서버가 실행되고 터미널에 있는 주소로 포트까지 복사해서 브라우저에 실행해봅니다.
코드를 수정하면 바로바로 수정된 코드가 반영되는 것을 볼 수있습니다.

옵션들을 조금 더 봅시다.

// webpack.config.js:
module.exports = {
  devServer: {
    contentBase: path.join(__dirname, "dist"), 
    publicPath: "/", 
    host: "dev.domain.com",
    overlay: true,
    port: 8081,
    stats: "errors-only",
    historyApiFallback: true,
  }
}

contentBase: 정적파일을 제공할 경로. 기본값은 웹팩 아웃풋입니다.
publicPath: 브라우저를 통해 접근하는 경로. 기본값은 ‘/’ 입니다.
host: 개발환경에서 도메인을 맞추어야 하는 상황에서 사용합니다. 예를들어 쿠기 기반의 인증은 인증 서버와 동일한 도메인으로 개발환경을 맞추어야합니다. 운영체제의 호스트 파일에 해당 도메인과 127.0.0.1 연결한 추가한 뒤 host 속성에 도메인을 설정해서 사용합니다.
overlay: 빌드시 에러나 경고를 브라우저 화면에 표시합니다.
port: 개발 서버 포트 번호를 설정합니다. 기본값은 8080.
stats: 서버 실행 시 터미널에 뿌려지는 메시지 수준을 정합니다. ‘none’, ‘errors-only’, ‘minimal’, ‘normal’, ‘verbose’ 로 메세지 수준을 조절합니다.
historyApiFallBack: 히스토리 API를 사용하는 SPA 개발시 설정합니다. 404가 발생하면 index.html로 리다이렉트합니다.


핫모듈은 전체화면을 갱신하는 것이 아니라 변경한 컴포넌트만 갱신해주는 기능입니다.

// webpack.config.js:
module.exports = {
  devServer = {
    hot: true,
  },
}

참고문헌
1. https://jeonghwan-kim.github.io/series/2020/01/02/frontend-dev-env-webpack-intermediate.html#1-%EC%9B%B9%ED%8C%A9-%EA%B0%9C%EB%B0%9C-%EC%84%9C%EB%B2%84

profile
정리하는 개발자

0개의 댓글