[JavaScript] Babel, Webpack

wrld_worthy·2023년 2월 27일

JavaScript

목록 보기
13/21

#Webpack, Babel

  • 둘다 tool이다. Ex) nom install로 받을 수 있음.
  • 위와 같은 이유로 사용법이 간단하다. 대신 설정법이 좀 있다.

Babel

  • JavaScript 코드를 변환해주는 도구.
  • JavaScript를 컴파일 해주는 도구.
    이다.

왜 변환, 컴파일을 해주는가?
1) JavaScript 문법은 꾸준히 진화, 업데이트가 되어왔다.
JavaScript문법이 업데이트되면, 런타임이 따라와줘야하기 때문.

Ex)
of라는 예약어가 생긴다면? 실행하기 위해서는 브라우저(런타임)도 프로그램으로 이루어진 것이기 때문에 코드를 변경해줘야함.
ES6 -> ES5
Let const -> var

2) JavaScript를 실행하는 방법이 여러가지이기 때문.

* 브라우저
	- window : 브라우저 전역 객체

* NodeJS
	- Global : 노드 전역 객체
		- require
		- module/ exports

JavaScript는 import와 require, 모듈을 불러오는 방법은 두가지가 존재한다.
각각 런타임에 따라 사용 유무가 다른데, 왜 2개냐.. 불편할 수 있음.
-> babel을 통해서 require로 썼다가 NodeJS에서 사용할때는 그대로, 브라우저에서 실행할때는 require로 변환하여 실행할 수 있도록 한다.

Babel 기본 사용

####예제1)
1. 기본 구성 설치하기
Babel은 기본적으로 JS로 구성되어있고, npm을 통해 쉽게 설치가 가능하다.

$ npm init -y
$ npm install @babel/core @babel/cli @babel/preset-env

npm과 npx 차이
npm, npx 둘다 다운과 실행을 할 수 있지만
npm은 다운로드 후 실행까지 직접 경로를 설정해야한다.
npx는 node_modules에 있는 모듈들을 실행하기위해 나왔따. 실행할 패키지가 존재하지 않다면 다운로드 후 실행해준다.

  1. Babel 환경 구성
    rc가 붙는 파일들이 있다.
    Ex) zshrc, bashrc, prittiers, eslintrc …
    환경 파일이라는 뜻.

babel 환경 구성을 위해선
.babelrc라는 파일이 필요함. ( 생성 )

rc Run Commands Run Control
커맨드 명령어를 썼을 때 옵션 내용을 파일로 따로 빼서 관리하는 것.

  1. ES6 예제 문법 파일 만들기
const fn = (message) => {
    const arr = [1,2,3,4,5]
    const arr2 = [6,7,8,9,10]

    const arr3 = [...arr, ...arr2]
    console.log(...arr3, message)
}

fn("hello world!")
  1. Babel 실행
npx babel [바꿀파일] --out-file [보낼파일]

npx babel example.js --out-file dist/example.js

결과

"use strict";

function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
var fn = function fn(message) {
  var _console;
  var arr = [1, 2, 3, 4, 5];
  var arr2 = [6, 7, 8, 9, 10];
  var arr3 = [].concat(arr, arr2);
  (_console = console).log.apply(_console, _toConsumableArray(arr3).concat([message]));
};
fn("hello world!");

babel에 플러그와 프리셋이 있는데
플러그인들이 모여서 프리셋이 된다.
ex) Arrow함수를 function으로 바꿔는 플러그인이 있고, 그 외에 다른 여러개 플러그인들을 묶어서 프리셋이 된다.

####예제2)
1. 관련 패키지 설치

$ npm install @babel/core @babel/cli @babel/plugin-transform-modules-commonjs
  1. .babelrc 설정하기
{
    "plugins":["@babel/plugin-transform-modules-commonjs"]
}
  1. 예제문법
import express from'express'
const app = express()

app.listen(3000,()=>{
    console.log('Server Start')
})
  1. babel 실행
$ npx babel server

결과

"use strict";

var _express = _interopRequireDefault(require("express"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const app = (0, _express.default)();
app.listen(3000, () => {
  console.log('Server Start');
});

예제3) Babel을 통해서 JSX 문법 컴파일 하기

JavaScript에서는 "<",">" 문법은 존재하지 않음.

  1. 관련 패키지 설치
$ npm init
$ npm install @babel/core @babel/cli @babel/preset-react
  1. .babelrc
{
    "presets":["@babel/preset-react"]
}

babel은 파일을 모듈화해서 가져올때는 문제가 생긴다. 이때 webpack을 사용한다 
3. 예제 코드
```js
const react = require('react')
const reactDOM = require('react-dom')

class App{
    render(){
        return (
            <div>
                Hello World!
            </div>
        )
    }
}

const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(<App/>)
  1. 결과
const react = require('react');
const reactDOM = require('react-dom');
class App {
  render() {
    return /*#__PURE__*/React.createElement("div", null, "Hello World!");
  }
}
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render( /*#__PURE__*/React.createElement(App, null));

Webpack

babel은 코드 자체를 변환할때, 단일 파일.
webpack은 모듈인 파일들을 하나에 다 불러 모아가지고 처리한다.

Webpack 모듈 번들러
웹 어플리케이션을 구성하는 다양한 자원들을 하나의 파일로 번들링하고, 이를 사용해서 웹 페이지 로딩하는데
필요한 최소한의 파일을 제공함.
이를 통해서 로딩 속도를 개선할 수 있다.

  • 모듈

    • 모듈이란 프로그램을 구성하는 구성요소로, 관련된 데이터와 함수를 하나로 묶은 단위
  • 번들러

    • 번들러는 의존성있는 모듈코드를 하나의 파일로 만들어주는 도구
<script src='./1.js'></script>
<script src='./2.js'></script>
<script src='./3.js'></script>
<script src='./4.js'></script>
<script src='./5.js'></script>

위 코드를 webpack으로 번들링을 한다면

<script src='./bundle.js'></script>

위와 같은 형식으로 자원을 줄일 수 있다.

Webpack 속성

babel 같은 경우
presets
plugins

  • entry : 웹 자원을 변환하기 위해 필요한 자바스크립트 파일 경로
  • output
    - filename: 번들파일 이름
    - path: 번들파일 생성 경로
  • loaders
  • plugins 바벨과 비슷함.

entry -> plugins -> output

Webpack 기본 실행

예제1)

  1. 관련 패키지 설치
$ npm install webpack webpack-cli
  1. 프로젝트 구성
    src 안에 있는 파일을 번들링 진행하려고 한다.

  2. webpack 설정 파일

  • project의 root 디렉토리에 만듬.
    webpack.config,js
const path = require('path')

module.exports = {
    entry:'./src/index.js',
    output:{
        filename:'bundle.js',
        path: path.join(__dirname, "dist"),
    },
}
  1. 예제 코드 작성하기
    index.js
const home = require('./pages/home.js')

console.log(home.name)

pages/home.js

module.exports = {
    name="web7722",
}
  1. Webpack을 실행
$ npx webpack --config webpack.config.js // config값을 수정했을 시.
$ npx webpack

예제2) Webpack Loaders 사용해보기

css도 javascript로 bundeling이 가능하다

Webpack 설정파일에 있는 Loaders 설정 내용은
다양한 유형의 파일을 모듈화 할 수 있따.

아마 우리가 자주사용하는 것들은
CSS, Image일 확률이 높다.

CSS 모듈을 번들링 해보도록 하겠습니다.

  1. 관련 패키지 설치
npm init -y
npm install webpack webpack-cli css-loader style-loader
  1. 프로젝트 구성
    src

src/index.js

import "./index.css"
console.log('hello world')

src/index.css

* {
    margin:0;
    padding:0;
    background:red;
}
  1. webpack.config.js
const path = require('path')

module.exports = {
    entry:'./src/index.js',
    module:{
        rules:[ // {}하나당 1개의 loader
            {
                test:/\.css$/,
                use:['style-loader', 'css-loader']
            }
        ]
    },
    output: {
        filename:'bundle.js',
        path: path.join(__dirname, "dist")
    }
}

Webpack의 결과는

(()=>{"use strict";var e,t,n,r,o,a,i,c,s,u,l,p,d,f,v={424:(e,t,n)=>{n.d(t,{Z:()=>c});var r=n(81),o=n.n(r),a=n(645),i=n.n(a)()(o());i.push([e.id,"* {\n    margin:0;\n    padding:0;\n    background:red;\n}",""]);const c=i},645:e=>{e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n="",r=void 0!==t[5];return t[4]&&(n+="@supports (".concat(t[4],") {")),t[2]&&(n+="@media ".concat(t[2]," {")),r&&(n+="@layer".concat(t[5].length>0?" ".concat(t[5]):""," {")),n+=e(t),r&&(n+="}"),t[2]&&(n+="}"),t[4]&&(n+="}"),n})).join("")},t.i=function(e,n,r,o,a){"string"==typeof e&&(e=[[null,e,void 0]]);var i={};if(r)for(var c=0;c<this.length;c++){var s=this[c][0];null!=s&&(i[s]=!0)}for(var u=0;u<e.length;u++){var l=[].concat(e[u]);r&&i[l[0]]||(void 0!==a&&(void 0===l[5]||(l[1]="@layer".concat(l[5].length>0?" ".concat(l[5]):""," {").concat(l[1],"}")),l[5]=a),n&&(l[2]?(l[1]="@media ".concat(l[2]," {").concat(l[1],"}"),l[2]=n):l[2]=n),o&&(l[4]?(l[1]="@supports (".concat(l[4],") {").concat(l[1],"}"),l[4]=o):l[4]="".concat(o)),t.push(l))}},t}},81:e=>{e.exports=function(e){return e[1]}},379:e=>{var t=[];function n(e){for(var n=-1,r=0;r<t.length;r++)if(t[r].identifier===e){n=r;break}return n}function r(e,r){for(var a={},i=[],c=0;c<e.length;c++){var s=e[c],u=r.base?s[0]+r.base:s[0],l=a[u]||0,p="".concat(u," ").concat(l);a[u]=l+1;var d=n(p),f={css:s[1],media:s[2],sourceMap:s[3],supports:s[4],layer:s[5]};if(-1!==d)t[d].references++,t[d].updater(f);else{var v=o(f,r);r.byIndex=c,t.splice(c,0,{identifier:p,updater:v,references:1})}i.push(p)}return i}function o(e,t){var n=t.domAPI(t);return n.update(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap&&t.supports===e.supports&&t.layer===e.layer)return;n.update(e=t)}else n.remove()}}e.exports=function(e,o){var a=r(e=e||[],o=o||{});return function(e){e=e||[];for(var i=0;i<a.length;i++){var c=n(a[i]);t[c].references--}for(var s=r(e,o),u=0;u<a.length;u++){var l=n(a[u]);0===t[l].references&&(t[l].updater(),t.splice(l,1))}a=s}}},569:e=>{var t={};e.exports=function(e,n){var r=function(e){if(void 0===t[e]){var n=document.querySelector(e);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}t[e]=n}return t[e]}(e);if(!r)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");r.appendChild(n)}},216:e=>{e.exports=function(e){var t=document.createElement("style");return e.setAttributes(t,e.attributes),e.insert(t,e.options),t}},565:(e,t,n)=>{e.exports=function(e){var t=n.nc;t&&e.setAttribute("nonce",t)}},795:e=>{e.exports=function(e){var t=e.insertStyleElement(e);return{update:function(n){!function(e,t,n){var r="";n.supports&&(r+="@supports (".concat(n.supports,") {")),n.media&&(r+="@media ".concat(n.media," {"));var o=void 0!==n.layer;o&&(r+="@layer".concat(n.layer.length>0?" ".concat(n.layer):""," {")),r+=n.css,o&&(r+="}"),n.media&&(r+="}"),n.supports&&(r+="}");var a=n.sourceMap;a&&"undefined"!=typeof btoa&&(r+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(a))))," */")),t.styleTagTransform(r,e,t.options)}(t,e,n)},remove:function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(t)}}}},589:e=>{e.exports=function(e,t){if(t.styleSheet)t.styleSheet.cssText=e;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(e))}}}},m={};function h(e){var t=m[e];if(void 0!==t)return t.exports;var n=m[e]={id:e,exports:{}};return v[e](n,n.exports,h),n.exports}h.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return h.d(t,{a:t}),t},h.d=(e,t)=>{for(var n in t)h.o(t,n)&&!h.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},h.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),h.nc=void 0,e=h(379),t=h.n(e),n=h(795),r=h.n(n),o=h(569),a=h.n(o),i=h(565),c=h.n(i),s=h(216),u=h.n(s),l=h(589),p=h.n(l),d=h(424),(f={}).styleTagTransform=p(),f.setAttributes=c(),f.insert=a().bind(null,"head"),f.domAPI=r(),f.insertStyleElement=u(),t()(d.Z,f),d.Z&&d.Z.locals&&d.Z.locals,console.log("hello world")})();

위와 같이 그냥 보기에는 알아보기가 힘들고 많은 코드들로 구성되어있다.

예시3) Webpack Plugin

HTML template 만드는 것을 해보자.

  1. 관련 패키지 설치
$ npm init -y
$ npm install webpack webpack-cli html-webpack-plugin
  1. 디렉토리 구성
    src/index.html

src/index.js

  1. webpack.config.js

  2. 실행

$ npx webpack

React 프로젝트 디렉토리를 구성

아주 간단한 내용. 실제로 사용하기에는 부족할 수 있음ㅇㅇ.

npm install react react-dom

babel

.babelrc

{
    "presets" :["@babel/preset-env","@babel/preset-react"]
}

관련패키지 설치

npm install @babel/preset-env @babel/preset-react
npm install @babel/core babel-loader

0개의 댓글