webpack - 1

Sming·2022년 3월 1일
10

Webpack이란

웹팩은 여러개 파일을 하나의 파일로 합쳐주는 번들러이다. 하나의 시작점(entry point)로 부터 의존적인 모듈을 모두 찾아내어 하나의 결과물을 만들어낸다.

기본 설정

$ npm install -D webpack webpack-cli

package.json의 script에 build: webpack로 설정을 한다.

이제 webpack.config.js 파일을 전역에 만들고 설정을 진행을 해준다.

const path = require("path");

module.exports = {
  mode: "development",
  entry: {
    home: "./src/app.js",
  },
};

이런식으로 module.exports안에 설정을 진행한다.

mode

mode에는 크게 3개의 옵션이 있으며 none, development, production으로 나누어 진다.

  • development

    development를 이용할시에는 DefinePlugin의 process.env.NODE_ENV를 development로 설정을 하며 번들링시에 난독화나 압축없이 빌드를 진행합니다.

  • production

    production을 이용시에는 DefinePlugin의 process.env.NODE_ENV를 production으로 설정을 하며 빌드할때 난독화와 압축을 하여 훨씬 작은 용량으로 번들링 된 파일이 빌드됩니다.

  • none

    아무런 설정을 하지않는것입니다. 번들링 크기 순서는 development > none > production 순입니다.

mode를 따로 설정하지 않으면 default값으로 production이 들어갑니다.

entry

앱이 번들 처리를 시작할 지점을 뜻합니다. 배열을 전달할 경우 배열의 모든 요소가 처리됩니다.

module.exports = {
  //...
  entry: {
    home: './home.js',
    about: './about.js',
    contact: './contact.js',
  },
};

entry내의 key는 나중에 output에서 filename을 받을때 name으로 주로 사용이 됩니다.

dependencies

기본적으로 모든 엔트리 청크는 모든 모듈들을 저장합니다. dependOn옵션을 이용하면 한 엔트리 청크내의 모듈을 서로 공유할수 있습니다.

module.exports = {
  //...
  entry: {
    app: { import: './app.js', dependOn: 'react-vendors' },
    'react-vendors': ['react', 'react-dom', 'prop-types'],
  },
};

dependOn에 react-vendors를 했기에 react-vendors의 모듈을 app안에 들어있지않고 react-vendors와 공유를 할수 있습니다.

output

output은 번들링하거나 로드하는 방법과 위치를 webpack에 명령하는 옵션이 있습니다.

path

절대경로로 출력디렉토리를 설정합니다.

const path = require('path');

module.exports = {
  //...
  output: {
    path: path.resolve(__dirname, 'dist'),
  },
};

주의
CleanWebpackPlugin과 함께 이용시 __dirname만 작성하고 뒤에 폴더를 작성하지 않는다면 루트 디렉토리에 모든걸 지우고 빌드된것을 덮기때문에 .git과 함께 모든것이 날라감으로 조심하자!

filename

출력번들 이름을 결정합니다.

module.exports = {
  //...
  output: {
    filename: '[name].bundle.js',
  },
};

entry에서 home으로 보내왔다면 home.bundle.js가 될것입니다.

template strings 공식 문서

publicPath

이것은 이미지, 파일등과 같은 외부 리소스들을 로드할때 사용하는 옵션입니다. 이 옵션의 경우 경로뒤에 / 를 붙혀 끝냅니다.

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

module.exports = {
  //...
  output: {
    path: path.resolve(__dirname, 'public/assets'),
    publicPath: '/assets/',
  },
};

//html
<link href="/assets/spinner.gif" />

publicPath는 prefix개념으로 사용자가 webpack.config.js에 설정한 주소가 실제 배포되는 주소 앞에 설정이 됩니다.

webpack에서 publicPath를 통한 img처리

로더

웹팩은 모든것을 모듈로 바라본다. 그래서 자바스크립트뿐만 아니라 스타일시트, 이미지, 폰트까지 전부 모듈로 바라보기 때문에 import 구문으로 자바스크립트 코드로 가져올수 있다.

css-loader

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

이렇게 작성시 css코드가 자바스크립트로 변환이 된다. 하지만 이상태로 빌드를 한다면 css는 똑바로 적용되지 않는다.

style-loader

스타일로더까지 추가해줘야 브라우저가 css를 해석할수 있도록 해준다. style-loader는 자바스크립트로 변경된 스타일을 동적으로 돔에 추가해주는 로더이다.

그래서 항상 css-loader와 style-loader는 같이 이용한다.항상 style-loader가 css-loader앞에 작동되도록 해야한다.

$ npm install -D style-loader
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"], 
    ],
  },
}

file-loader

npm i -D file-loader

사진같은 파일을 불러올때 사용하는 로더이다. 모든 파일을 모듈화하여 이용할수 있다.

module.exports = {
  module: {
    rules: [
      {
        test: /\.png$/, // .png 확장자로 마치는 모든 파일
        loader: "file-loader",
        options: {
          publicPath: "./", //
          name: "[name].[ext]"
        },
      },
    ],
  },
}

url-loader

원래는 파일을 사용할때 file-loader라는 로더를 이용하지만 url-loader를 이용할시 일정 용량이하의 파일은 base64로 인코딩하고 일정용량이상이면 file-loader를 작동하게 할수 있다.
주로 작은 이미지를 많이 사용할때 이용하며 네트워크 리소스와 사이트 성능을 향상시킬수 있다.

$ npm install -D url-loader
{
  test:  /\.(jpg|png|gif|swg)$/,
  use: {
    loader: 'url-loader', // url 로더를 설정한다
    options: {
      publicPath: './dist/', //배포해도 변하지않도록 prefix설정
      name: '[name].[ext]?[hash]',// image.jpg?20qfrqh0rq...
      limit: 5000//5kb이상일 경우 file-loader, 이하일 경우 url-loader 실행
    }
  }
}

플러그인

로더가 파일단위로 처리한다면 플러그인은 번들된 결과물을 처리한다. 번들된 자바스크립트를 난독화, 텍스트 추출하는 용도로 사용한다.

BannerPlugin

번들된 결과물에 빌드정보 혹은 커밋버전등등 원하는 텍스트를 추가할수 있다.

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.BannerPlugin({
      banner:  () => `빌드 날짜: ${new Date().toLocaleString()}`,
    })
  ]

이것을 번들하면 번들된 파일의 가장위에 주석으로 텍스트가 추가된다.

DefinePlugin

컴파일 타임에 구성할수 있는 전역 상수를 만들수 있다. 주로 개발의 빌드와 배포의 빌드간에 다른 동작을 하고싶을때 유용합니다.

new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
});

HTMLWebpackPlugin

이번엔 써드 파티 패키지이다. webpack에 있는것이 아니라 npm혹은 yarn을 이용하여 다운받아야한다.

이번에 사용하는 HTMLWebpackPlugin 플러그인은 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' ? '(개발용)' : '',
      }, // template에 인자를 전해줄수 있다. index.html내에서 ejs문법인 <%= env %>를 이용하여 받을수 있다.
      minify: process.env.NODE_ENV === 'production' ? {
    	collapseWhitespace: true, // 빈칸 제거
    	removeComments: true, // 주석 제거
  	} : false,
    })
  ]
}

CleanWebpackPlugin

CleanWebpackPlugin은 빌드 이전 결과물을 제거를 하는 플러그인이다. dist안에 이미 빌드된 결과물이 있는 상태로 다시 빌드를 하면 모든 파일내용이 같다면 덮어씌워지겠지만 filename을 바꾸거나 파일이 달라지는 일이 생긴다면 과거 파일에 그대로 쌓이게 될것이다. 그래서 이 플러그인을 이용하여 지울수 있다.

역시 써드파티 플러그인이기에 npm 으로 다운을 해줘야한다.

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

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

빌드할때마다 dist 폴더를 지우고 다시 번들된 파일을 넣어준다.

MiniCssExtractPlugin

하나의 큰 css파일을 내려받는것보다는 여러개의 작은 css파일을 동시에 다운로드 하는것이 더 빠르다.

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


module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          process.env.NODE_ENV === "production"
            ? MiniCssExtractPlugin.loader // MiniCssExtract에서 제공하는 loader를 이용해야함
            : "style-loader",
          "css-loader",
        ],
      },
  },
  plugins: [
    ...(process.env.NODE_ENV === "production"
      ? [new MiniCssExtractPlugin({ filename: "[name].css" })]
      : []),// filename으로 설정한값으로 아웃풋 경로에 css파일이 생성된다. 안적어도 default가 [name].css이다.
  ],
}
profile
딩구르르

2개의 댓글

comment-user-thumbnail
2022년 3월 4일

webpack이 필요할때 자스민에게 달려가겠습니다 😎

1개의 답글