Web webpack, babel config

4 분 소요

create-react-app (CRA)를 이용해 react 프로젝트를 만들고 yarn eject를 통해 추출한 config 폴더 및 webpack.config.js 파일을 이해해 보자.

$ npx create-react-app webpack-study
$ cd webpack-study
$ yarn eject 

Webpack

webpack

기존의 웹에서 javascript 개발 방식은 기능별/페이지별로 자바스크립트 파일을 분리하고 HTML의 <script> 태그로 로드하는 것이었다.

하지만 파일간의 변수 스코프 침범을 신경쓰며 개발해야하는 등의 단점이 있었는데, 이를 해결하기 위해 생긴 것이 모듈 개념이다. (AMD, CommonJS, ES6 모듈 등)

더욱이 현대의 프론트엔드는 역할과 기능이 다양해지며 react, angular 등의 프레임워크가 등장하였고, 이는 모두 모듈 개념을 이용하고 있다.

그러나 이러한 모듈 시스템을 아직 지원해주지 않는 브라우저도 있고 브라우저에서 여러 파일을 다운로드하며 치르는 과도한 네트워크 비용등의 비효율은 여전히 있었다.

이를 해결하기 위해 프로젝트 안에 포함된 js 모듈들 뿐만아니라 css, img 등의 다른 파일들을 모두 엮어 하나 또는 소수의 파일로 만들어 주는 모듈 번들러로서 webpack 이 등장하였다.

Loaders

webpack 은 javascript 뿐 아니라 이미지, 폰트, css 등 모든 파일을 모듈로 관리한다.

하지만 webpack은 javascript 밖에 알지 못하므로 다른 형태의 파일들을 이해할 수 있게끔 해주어야한다. 이 역할을 하는 것이 loader이다.

webpack.config.js

rules: [
        ...
        {
            test: /\.(scss|sass)$/,
            use: ['style-loader', 'css-loader', 'sass-loader'] 
        }
        ...
    ]

test에 로딩할 파일의 정규식을, use에 사용할 loader들을 지정하여 번들링한다.

use에 나열된 loader은 역순으로 적용 된다는 것이 중요.

sass-loader 적용 후 css-loader 적용 후 style-loader 적용.

use: [
        {
            loader: 'css-loader',
            options: cssOptions
        },
     ...
    ]

특정 loader에 option을 추가해 줄때는 이런 형태를 사용하면 된다.

babel-loader

우리는 기본적으로 ES6 이상의 문법을 이용하여 코드를 작성한다. 하지만 브라우저에 따라 높은 버전의 자바스크립트를 이해할 수 없는 경우가 있다.

이를 해결하기 위해 ES5 문법으로 변환해주는 것이 babel 이다.

preset

package.json

...
    "babel": {
      "preset": [
        "react-app"  
      ]
    }
...

ES6 문법의 각 구성요소를 ES5로 변환하려면 그에 해당되는 babel plugin을 설정해주어야 한다.

예를 들어 const arrow = () => {} 와 같은 화살표 함수를 변화해주려면 @babel/plugin-transform-arrow-functions 플러그인을 설치하고 설정해 주어야한다.

문법 하나하나에 대해 매번 설치하고 설정해주는 것이 귀찮으니 plugin들을 포함한 번들이 만들어졌는데 그것이 preset이다.

cra로 만들어진 프로젝트는 기본적으로 react에서 사용되는 plugin들을 담은 babel-preset-react-app을 포함하고 있다.

그 외에 babel 공식 preset으로는 @babel/preset-env,@babel/preset-flow,@babel/preset-react,@babel/preset-typescript 등이 있다.

babel은 package.json 파일 대신 .babelrc 파일을 별도로 생성하여 설정 할 수 있다.

설정하고자 하는 브라우저를 선택하도록 plugin을 선택하여 번들링된 js 코드의 양을 줄일 수 있다고도 한다. 링크

sass-loader, less-loader

sass(scss) 또는 less 파일을 css로 변환해준다.

css-loader

“css” loader resolves paths in CSS and adds assets as dependencies.

main.edc2fa9c.chunk.js

...
function (n, e, o) {
  (e = o(2)(!0)).push([
    n.i,
    "body {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n    sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n    monospace;\n}\n",
    "",
    {
      version: 3,
      sources: ["index.css"],
      names: [],
      mappings:
        "AAAA;EACE,SAAS;EACT;;cAEY;EACZ,mCAAmC;EACnC,kCAAkC;AACpC;;AAEA;EACE;aACW;AACb",
      file: "index.css",
      sourcesContent: [
        "body {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n    sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n    monospace;\n}\n",
      ],
    },
  ]),
    (n.exports = e);
},
...

index.css에 대해 css-loader 적용 한 모습.

css 파일을 js 형태로 모듈화 해준다. @import, url() 등을 해석하여 import/require 와 같은 모듈로 만든다.

이 형태로는 html 파일에서 사용할 수 없어 추출이 필요하다.

style-loader

“style” loader turns CSS into JS modules that inject <style> tags.

css-loader를 통해 묶인 css 파일을 추출하여 DOM에 <style> 태그 형태로 삽입해준다.

style-loader 대신 mini-css-extract-plugin plugin을 사용하면 <style> 태그 대신 <link> 태그로 삽입할수 있다.

cra 기본 webpack에서는 dev 환경에서는 style-loader를, prd 환경에서는 mini-css-extract-plugin을 default로 사용한다.

postcss-loader

“postcss” loader applies autoprefixer to our CSS.

.box-wrap {
    box-sizing: border-box;
    -webkit-box-sizing: border-box;  // chrome, safari prefix
    -moz-box-sizing: border-box;     // firefox
    -o-box-sizing: border-box;       // old opera versions
    -ms-box-sizing: border-box;      // IE, Microsoft Edge
}

js plugin 들을 적용하여 css로의 변환을 도와준다. js를 변환해주는 babel과 개념이 비슷하다.

autoprefixer 플러그인을 사용하면 기존에 크로스 브라우저 호완을 위해 붙여야 했던 접두사를 자동으로 붙여준다.

그외에 color() modifier, 변수사용, @import, nesting, for loop 사용등을 가능하게 하는 plugin 등이 있다.

sass, less 등은 css 로 변환되는 스타일시트 언어 또는 css preprocessor 이지만 PostCSS는 js기반의 플러그인을 이용하여 css로 변환은 자동화하는 개발 도구에 가깝다.

resolve-url-loader

A webpack loader that rewrites relative paths in url() statements based on the original source file.

cra에서 default로 sass-loader 등록시 바로 앞쪽에 포함된다.
npm document 에 따르면 sass 에포함된 url()의 상대경로를 인식하여 알맞게 수정해주는 일을 한다.

url-loader

“url” loader works like “file” loader except that it embeds assets smaller than specified limit in bytes as data URLs to avoid requests.

작은 이미지나 글꼴 파일은 복사하지 않고 문자열 형태로 변환하여 번들 파일에 넣어준다. limit 사이즈를 설정할 수 있다.

file-loader

“file” loader makes sure those assets get served by WebpackDevServer. When you import an asset, you get its (virtual) filename. In production, they would get copied to the build folder. This loader doesn’t use a “test” so it will catch all modules that fall through the other loaders.

다른 loader들에 적용 받지 않는 나머지 파일들을 build 폴더로 옮겨 import 되도록 준다.

Plugins

html-webpack-plugin

html 파일을 읽어와 build 폴더에 index.html 파일을 생성하고 번들된 js 파일을 <script> 형태로 inject 해준다.

  • template: 읽어올 html 파일 경로. src/index.html

webpack-manifest-plugin

번들링 시 생성되는 코드에 대한 정보를 json 파일로 저장하여 관리해주는 플러그인.

workbox-webpack-plugin.GenerateSW

The GenerateSW plugin will create a service worker file for you and add it to the webpack asset pipeline. 링크

terser-webpack-plugin

terser를 사용하여 javascript를 minify 해주는 플러그인.

optimize-css-assets-webpack-plugin

css파일을 optimize, minimize 해주는 플러그인. terser-webpack-plugin과 함께 optimization의 minimizer 로 사용된다.

webpack.HotModuleReplacementPlugin

변경된 모둘을 실시간으로 번들 파일에 적용하고 업데이트해 주는 플러그인.

Etc

webpack-dev-server

$ yarn start

yarn start 명령을 입력하면 script/start.js 파일이 실행되는데 이파 일에는 WebpackDevServer 설정이 포함되어있다.

개발자의 로컬 pc에서 서버를 띄우고, 브라우저에서 직접 번들 파일을 확인할 수 있는 기능을 제공한다.

build/

$ yarn build

build/ 디렉토리에 webpack이 만든 파일들이 생성된다.

2.chunk.js 파일에는 react, react-dom 등 node_modules 관련 코드들이, main.chunk.js 파일에는 내가 작성한 컴포넌트 코드들이 들어간다.

sourcemap

loader의 옵션으로 sourceMap: boolean 설정을 할수 있다. webpack이 압축/난독화 한 코드를 실제 코드로 풀어주는 기능이다.

대부분의 브라우저에서 지원하여 디버깅을 위해 유용하게 사용된다. false 일 때 브라우저에서 실제 코드 형태로 확인할 수 없게 된다.

Reference