-->

[Webpack] Loader

 

 

Webpack은 기본적으로 Javascript ES6문법의 module 구성을 통해 각 소스들을 Bundling 해주는 도구라는 것을 저번에 배웠다.

Webpack Bundling의 대상은 비단 Javascript 파일뿐만이 아니다.

Webpack enables use of loaders to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js.
Loaders are activated by using loadername! prefixes in require() statements, or are automatically applied via regex from your webpack configuration 

공식 문서에서는 loader를 통해 javascript 너머 정적 리소스들을 번들링 해준다고 한다. 또한 정규식을 이용해 손쉽게 나만의 Loader를 작성할 수 있다.

예를 들어, css 파일을 만들어두고 css-loader를 이용하면 bundling 되어 나온 결과에 css파일도 포함되어 하나의 js파일로 출력된다. 

css뿐만 아니라 file이나 image도 가능하다.

 

package.json

{
  "name": "webpack-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "css-loader": "^6.7.1",
    "file-loader": "^6.2.0",
    "react": "^18.2.0",
    "style-loader": "^3.3.1",
    "url-loader": "^4.1.1"
  },
  "devDependencies": {
    "webpack": "^5.73.0",
    "webpack-cli": "^4.10.0"
  }
}

 

 

1. css-loader & style-loader

$ npm install css-loader style-loader

 

webpack.config.js

const path = require('path');

module.exports = {
	mode: 'development',
    entry: {
    	main: './src/app.js',
    },
    output: {
    	path: path.resolve('./dist'),
        filename: '[name].js'
    },
    module: {
    	rules: [
        	{
            	test: /\.css$/, //css라는 확장자를 가진 모든 파일은 아래의 Loader를 적용시키겠다.
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
}

style-loader를 먼저 적어야 한다. 순서가 뒤에서 앞으로 적용되기 때문에.

 

app.css

body {
	background-color: green;
}

 

app.js

import './app.css';

 

단순히 css-loader만을 적용시키면 Webpack의 번들링 결과에 app.css의 소스 내용이 js안에 들어가지만 실제로 적용이 되지 않는데, style-loader가 해당 부분을 inline style로 넣어 만들어준다. 그래서 두 개의 loader가 세트라고 할 수 있다.

 

확인

$ npm run build

> webpack-sample@1.0.0 build
> webpack

asset main.js 23.5 KiB [emitted] (name: main)
runtime modules 972 bytes 5 modules
cacheable modules 9.96 KiB
  modules by path ./node_modules/ 8.07 KiB
    modules by path ./node_modules/style-loader/dist/runtime/*.js 5.75 KiB
      ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 2.44 KiB [built] [code generated]
      ./node_modules/style-loader/dist/runtime/styleDomAPI.js 1.38 KiB [built] [code generated]
      ./node_modules/style-loader/dist/runtime/insertBySelector.js 1010 bytes [built] [code generated]
      + 3 modules
    modules by path ./node_modules/css-loader/dist/runtime/*.js 2.33 KiB
      ./node_modules/css-loader/dist/runtime/noSourceMaps.js 64 bytes [built] [code generated]
      ./node_modules/css-loader/dist/runtime/api.js 2.26 KiB [built] [code generated]
  modules by path ./src/ 1.89 KiB
    ./src/app.js 282 bytes [built] [code generated]
    ./src/app.css 1.11 KiB [built] [code generated]
    ./node_modules/css-loader/dist/cjs.js!./src/app.css 515 bytes [built] [code generated]
webpack 5.73.0 compiled successfully in 334 ms

$ npx lite-server

 

 

2. file-loader

$ npm install file-loader

 

webpack.config.js

...
    module: {
    	rules: [
            {
                test: /\.(png|jpg|gif|svg)$/, //처리할 패턴을 명시
                loader: 'file-loader',
                options: {
                    publicPath: './dist/',
                    name: '[name].[ext]?[hash]'
                }
                // use: [ 'file-loader' ]
            },
...

 

app.css

body {
    /*background-color: green;*/
    background-image: url(minggu.jpg);
}

 

아무 그림 파일을 src폴더에 넣어두자.

현재는 options값을 주지 않고 use만 해도 자동으로 해시처리 되는 것 같긴 한데...

내가 minggu.jpg라는 파일을 번들링 한다고 하면 나오는 파일명은 해시 처리되어 나온다.

이는 같은 파일명을 사용할 때 브라우져가 캐시 된 이미지를 가져올 수 있어서 매번 브라우저에게 새로 이미지를 다운로드하으라고 알려주는 용도이다. 

그러나 매번 페이지를 로드 할 때마다 이미지를 다운로드하는 것은 비효율 적인 것 같아..

 

3. url-loader

npm install url-loader

 

webpack.config.js

const path = require('path');

module.exports = {
    mode: 'development',
    entry:{
        main: './src/app.js',
    },
    output: {
        path: path.resolve('./dist'),
    filename: '[name].js'
    },
    module: {
        rules: [
            {
                test:/\.css$/,
                    // /\.js$/, //js확장자를 가진 모든파일은 Loader로 돌리겠다. 처리할 패턴을 명시
                use: [
                    // path.resolve('./my-webpack-loader.js') //걸리는 녀석들은 이 파일 동작
                    'style-loader',
                    'css-loader' //순서는 뒤에서부터 앞으로
                ]
            },
            // {
            //     test: /\.(png|jpg|gif|svg)$/,
            //     loader: 'file-loader',
            //     options: {
            //         publicPath: './dist/',
            //         name: '[name].[ext]?[hash]'
            //     }
            //     // use: [ 'file-loader' ]
            // },
            {
                test: /\.(png|jpg|gif|svg)$/,
                loader: 'url-loader',
                options: {
                    publicPath: './dist/',
                    name: '[name].[ext]?[hash]',
                    limit: 20000, // 20kb 미만이면 url-loader가 base64로 인코딩, 그 이상은 file-loader가 처리
                }
            }
        ]
    }

}

 

app.js

import './app.css';
import minggu from './minggu.jpg';

document.addEventListener('DOMContentLoaded', () => { 
    document.body.innerHTML = `
        <img src="${minggu}" />
    `
})

 

그래서 url-loader를 이용하여 특정 용량을 limit 걸어두면, 그 이하의 파일은 base64로 인코딩 되어 나온다.

자주 쓰는 이런 loader를 통해 데이터를 효율적으로 관리 할 수 있다!

 

https://github.com/minha9012/webpack-sample

 

GitHub - minha9012/webpack-sample

Contribute to minha9012/webpack-sample development by creating an account on GitHub.

github.com

 

 

<참조>

https://webpack.js.org/loaders/

 

Loaders | webpack

webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

webpack.js.org

 

+ Recent posts