본문 바로가기
react

Webpack이 뭔데!! (4)

by 새우하이 2021. 8. 4.

Package.json

package.json은 크게 2가지로 나눠집니다.

  1. 어플리케이션 내부에 직접 포함되는 모듈
    • 예를 들어 Jquery같은 모듈이 있습니다. DOM선택을 쉽게하기 위해 Jquery등을 NPM을 통해 설치하면 이 모듈은 애플리케이션 내부에서 직접 동작하는 모듈입니다.
  2. 개발 과정에 필요한 모듈
    • 개발 효율을 높이거나 코드 컨벤션을 검사하는 등등의 모듈, 즉 테스트 관련 모듈이나 트랜스 파일러 관련 모듈등이 있습니다.
  3. dependencies
  • 애플리케이션 내부에 직접 포함되는 모듈 정보를 담습니다. 의존성을 규정하는 것은 패키지 이름과 해당 패키지의 범위를 지정한 객체를 통해 이뤄집니다.
  • npm 을 통해 설치하는 모듈이 dependencies에 기록되어야할 때는 옵션으로 --save 를 사용합니다.
  1. devDependencies
    • 테스트 관련 모듈이나 트랜스 파일러 관련 모듈 등 개발 과정에 필요한 모듈등을 나타냅니다
    • npm 을 통해 설치하는 모듈이 devDependencies에 기록되어야할 때는 옵션으로 --save-dev 를 사용합니다.

다른 항목들에 대해서는 https://programmingsummaries.tistory.com/385 에서 참고

우리 프로젝트로 돌아와 package.json 파일을 열어 devDependencies 에 이전에 설치한 webpackwebpack-cli 가 잘 있는지 확인해 봅니다.

그리고 프로젝트 디렉터리중 node_modules 를 과감히 지워버립니다.

$ npm install

그리고 명령어로 npm install 만 쳐주면 node_modules 가 다시 생성되면서 내부에 webpackwebpack-cli가 정상적으로 다시 설치되는 것을 확인할 수 있습니다.

Loaders

webpack은 기본적으로 javascript와 json파일만 이해합니다. Loader를 사용하면 webpack이 다른 유형의 파일들을 처리하거나 그들을 유효한 모듈로 변환하여 애플리케이션에 사용하거나 dependency graph에 추가합니다. 파일을 import 하거나 'load' 할 때 전처리 할 수 있습니다. 즉 webpack이 dependency graph를 완성시키는 과정에서 의존관계를 갖는 다양한 타입의 모듈들을 입력받아 처리하는 역할을 수행합니다.

Loader에 대한 자세한 설명

앞서 설명했듯, webpack은 javascript 파일과 json 파일만 인식하기 때문에 다른 타입의 모듈들은 개별적으로 loader를 준비해서 webpack에 연결시켜줘야 합니다.

//webpack.config.js

const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js',
  },
  module: {
    rules: [test,use],
  },
};

Loader를 설정할 때는 module이라는 key를 webpack설정파일에 추가하는 것으로 시작합니다.

이어서 지원해야하는 모듈 타입들을 위해 필요한 loader들을 설정하는 rules라는 key를 가진 속성을 정의합니다. rules의 배열안에 loader 에 대한 정보를 넣을 때는 위의 configuration 예제처럼 loader내에 설정된 기본동작이 적용되도록 loader의 이름을 문자열로 넣는 방법과

//webpack.config.js

const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js',
  },
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
};

loader가 어떻게 동작할지 개발자가 자세하게 설정할 수 있는 객체형태로 넣는 방법이 있습니다. 위의 설정에서는 testuse 라는 두 가지 필수 속성을 가진 하나의 모듈을 위해 정의되어있습니다. 이 속성은 webpack 컴파일러에게 다음과 같이 말합니다.

webpack 컴파일러야 require() / import 문 내에서 '.txt' 파일로 확인되는 경로를 발견하면 번들에 추가하기전에 raw-loader를 사용해서 변환해줘


여기까지 왔다면 지금까지 새로운 프로젝트폴더를 만들어서

$ npm init -y 로 package.json 파일을 만들고 webpackwebpack-cli 를 package.json 의 devDependencies 에 추가되게 설치해봅니다.

index 페이지에 Hello Webpack 을 띄워줄 것입니다.

새프로젝트폴더이름
  |- package.json
+ |- index.html
+ |- /src
+   |- index.js

index.html/src/index.js 를 하나 만들어 줍니다.

//index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Getting Started</title>
  </head>
  <body>
    <script src="./src/index.js"></script>
  </body>
</html>
//src > index.js
function component(){
    const element = document.createElement('div');
    element.innerHTML = 'Hello Webpack';
    return element;
}

document.body.appendChild(component());

이제 mode가 none인 webpack의 configuration 파일을 만들어봅시다.

webpack.config.js

를 생성해줍니다. entryoutputfilename, path 를 상기하며 만들어봅니다.

const path = require('path');

module.exports={
    entry: './src/index.js',
    output: {
        filename : 'bundle.js',
        path : path.resolve(__dirname, 'dist'),
    },
}

이제 $ npx webpack 을 통해 번들링해주면 dist 디렉터리 아래에 bundle.js 가 정상적으로 생성될 것입니다.

mode를 지정하지 않아 warning이 뜨지만 잠깐 무시해주세요.

그리고 /dist/index.html 을 생성해보세요.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Getting Started</title>
    </head>
    <body>
        <script src="./bundle.js"></script>
    </body>
</html>

./src/index.js 말고 dist 디렉터리에 새로 생성된 bundle.js를 연결해주고 /dist/index.html을 켜서 똑같이 잘 동작하는지 확인해 줍니다.

이제 Javascript, JSON이 아닌 이미지나 css같은 애셋들을 통합하고 어떻게 처리되는지 살펴봅니다.

이제 loader를 통해 css를 모듈로 읽어올 것입니다. 사용할 loader는 style-loadercss-loader 입니다. css-loader는 css를 모듈로 다루기위해 사용되는 loader이고 style-loadercss-loader를 통해 가져온 css내용을 style태그로 생성해서 head태그 안에 삽입해줍니다.

두 모듈을 설치하고 devDependencies 에 추가해줍니다.

$ npm install style-loader css-loader --save-dev

설치를 완료했으면 package.jsondevDependencies 에 잘 추가되었는지 확인해주세요.

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

module.exports={
    entry: './src/index.js',
    output: {
        filename : 'bundle.js',
        path : path.resolve(__dirname, 'dist'),
    },
    module:{
        rules:[
            {
                test:/\.css$/i,
                use:['style-loader', 'css-loader'],
            }
        ]
    }
}

webpack.config.js 도 수정해야합니다. 모듈 로더는 체인으로 연결할 수 있습니다. 체인의 각 로더는 리소스에 변형을 적용합니다. 그리고 체인은 역순으로 실행되기 때문에 style-loader 가 먼저오고 그 뒤에 css-loader 가 따라옵니다.

역순이기 때문에 css-loader가 리소스에 변형을 적용하고 → style-loader 에 그 값을 전달합니다.

test 에서는 어떤 파일들이 loader의 대상이 되는지 정규표현식의 패턴매칭으로 사용할 수 있습니다.

우선 Normalize.css 를 설치하는 방법입니다. css파일도 npm에 공개되어 있다면 설치가 가능합니다. Normalize.css는 HTML 요소의 기본 스타일을 브라우저 간 일관성을 유지하도록 돕는 CSS파일 입니다. user agent style을 표준화 시키는 것에는 2가지가 있습니다.

우선 많은 html tag 들이 기본적으로 가지고 있는 스타일이 있다는 것을 알고 계셔야합니다.

 

Reset.css

Reset.css는 브라우저간의 차이를 최대한 없애서, 스타일이 0인 상태에서 디자인을 만들어 나가기 위해 생겨난 것입니다.

ex) 모든 margin 값 0으로 리셋

Normalize.css

Normalize.css 는 브라우저 간 User Agent Style의 오차를 줄이고 버그를 줄이는 방향으로 재지정 되어있습니다.

ex) h1 tag의 font-size:28px 로 통일

$npm install normalize.css --css
//src > index.js
import 'normalize.css';
function component(){
    const element = document.createElement('div');

설치가 완료되었으면 index.js 에서 import 시켜줍니다.

/* src > index.css */
div{
    color:red;
}

이어서 createElement로 만든 div 내에 있는 text에 color 값이 적용될 수 있도록 css 파일을 만들어 불러와 봅시다. src 디렉터리 아래에 index.css를 생성해줍니다.

//src > index.js
import 'normalize.css';
import './index.css';
function component(){

마찬가지로 만든 index.css를 import 시켜줍니다.

그리고 번들링된 결과물을 살펴봅시다.

$ npx webpack
or
$ npm run build

직접 dist 디렉터리에 접근해서 index.html 파일을 열어도 되고 vscode를 사용하시는 분이면 [live server](https://boheeee.tistory.com/20)를 사용하셔도 됩니다.

dist > index.html 은 여기 (이전 예제) 에서 만들었습니다.

만약 npm run build 에서 에러가 난다면

package.json 에서

  | "scripts": {
  |    "test": "echo \"Error: no test specified\" && exit 1",
+ |    "build": "webpack"
  |  },

build 부분을 추가해주세요.

결과물의 소스를 보면 index.css와 normalize.css 가 head태그 사이에 잘 적용된 것을 볼 수 있습니다.

loader의 자세한 내용들은 google 검색에서 github로 배포되어있는 내용의 README 파일을 읽어보면 됩니다.

css module 이라는 설정을 해볼 것입니다. [css-loader의 저장소](https://github.com/webpack-contrib/css-loader) 에서 README의 보시면 Options 에서 modules 를 찾을 수 있습니다. 여기서 CSS Modules 를 설정에 대한 정보를 확인할 수 있습니다. css-loader에서 options 키를 추가하고 그 안에 modules라는 키를 true로 지정해주면 됩니다.

//webpack.config.js
const path = require('path');
                    .
                    .
                    .
                test:/\.css$/i,
                use:[
                    'style-loader',
                    {
                        loader : 'css-loader',
                        options:{
                            modules:true
                        }  
                    }
                ],
            }
        ]
    }
} 
/* src > index.css */
div{
    color:red;
}

.hellowebpack{
    color:blue;
}
//src > index.js
import 'normalize.css';
import styles from './index.css';
function component(){
    const element = document.createElement('div');
    element.innerHTML = 'Hello Webpack';

    console.log(styles);
    element.classList = styles.hellowebpack;
    return element;
}

document.body.appendChild(component());

css는 선택자의 이름이 전역환경으로 적용되기 때문에 어플리케이션의 규모가 커졌을 때 선택자 이름에 충돌이 없도록 신경을 써줘야합니다. css modules라는 설정을 해주면 css파일을 module로 불러오고 class 이름을 javascript에 불러와서 사용할 수 있어 css 파일별로 classname이 아도 겹치지 않는 장점이 있습니다.

브라우저에서 console.log를 살펴보면

{hellowebpack: "ITvqO_MZTGan44lkQuGC"} 객체가 보이고

div의 class에 이 hellowebpack라는 key를 가진 value가 적용되어있는 것이 보일 것입니다.

즉 이 css module을 사용하면 css파일별로 class이름이 겹쳐서 생기는 문제를 방지해 줍니다.

이번에는 style-loader 에 대한 option 설정을 해봅시다.

style-loader 는 처리하는 css 파일 별로 style 태그를 만드는데 하나의 style 태그에서 한번에 읽어올 수 있도록 option을 적용 해볼 것입니다.

option 에서 injectType 이라는 키에 여러 값들중 singletonStyleTag 을 적용 시켜줍니다.

injectType 이란? style이 DOM에 삽입되는 방식을 설정합니다.

//webpack.config.js
    use:[
                    {   
                        loader : 'style-loader',
                        options:{
                            injectType : 'singletonStyleTag'
                        }
                    },
                    {
                        loader : 'css-loader',
                        options:{
                            modules:true
                        }  
                    }
                ],
            }
        ]

singletonStyleTag 가 적용되기 전의 모습입니다.

각 style 태그에는 normalize.css 와 index.css 가 있습니다.

이제 번들링한 후의 모습을 살펴보면

하나의 style태그로 합쳐진 모습을 확인하실 수 있습니다.

'react' 카테고리의 다른 글

TestDome React Change Username  (0) 2021.08.20
Webpack이 뭔데!!(5)  (0) 2021.08.06
Webpack이 뭔데!!(3)  (0) 2021.08.02
Webpack이 뭔데!!(2)  (0) 2021.08.01
Webpack 이 뭔데!!(1)  (0) 2021.07.30

댓글