[VANILA JS NINJA] MEAL FINDER Web pack (2) (21/05/13)

rat8397·2021년 5월 13일
0

[VANILA JS NINJA]

목록 보기
7/10

타입이 모듈인 스크립트 태그는 HEAD에 있어도 된다. 페이지가 모두 로드된 후에 스크립트 태그를 실행하기 때문에..

적용 이유

<script type="module" src="app.js"></script>

다음과 같은 라인으로 모듈시스템을 적용할 수 있었다. 하지만 모든 브라우져에서 이를 적용하지 않기에 웹팩( 모듈 번들러 )을 통해 모듈 시스템을 적용하려고 한다.

컴파일하는 방법

webpack ./entry.js bundle.js  

엔트리와 아웃풋

웹팩은 여러개 파일을 하나의 파일로 합쳐주는 번들러(bundler)다. 하나의 시작점(entry point)으로부터 의존적인 모듈을 전부 찾아내서 하나의 결과물을 만들어 낸다. app.js부터 시작해 math.js 파일을 찾은 뒤 하나의 파일로 만드는 방식이다.

  • mode는 'development' 문자열을 사용했다.

  • entry는 어플리케이션 진입점인 src/app.js로 설정한다.

  • ouput에 설정한 '[name]'은 entry에 추가한 main이 문자열로 들어오는 방식이다.

output.path는 절대 경로를 사용하기 때문에 path 모듈의 resolve() 함수를 사용해서 계산했다. (path는 노드 코어 모듈 중 하나로 경로를 처리하는 기능을 제공한다)

로더

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

이것이 가능한 이유는 웹팩의 로더 덕분이다. 로더는 타입스크립트 같은 다른 언어를 자바스크립트 문법으로 변환해 주거나 이미지를 data URL 형식의 문자열로 변환한다. 뿐만아니라 CSS 파일을 자바스크립트에서 직접 로딩할수 있도록 해준다.

웹팩의 로더덕분에 모든 파일 스타일시트 폰트 이미지 들을 모듈로 보고 import, export 가능해지는 것이다.

webpack.config.js

const path = require("path");

module.exports = {
  mode: "development",
  entry: {
    main: "./src/app.js",
  },
  output: {
    filename: "[name].js",
    path: path.resolve("./dist"),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [path.resolve("./myloader.js")],
      },
    ],
  },
};

npm run build 로 실행하면 modules.rules[0].use의 로더들을 실행한다.

module.exports = function myloader(content) {
  console.log("myloader가 동작함");
  return content.replace("console.log(", "alert(");
};

다음의 로더를

 module: {
    rules: [
      {
        test: /\.js$/,
        use: [path.resolve("./myloader.js")],
      },
    ],
  },

에 넣으면

다음과 같이 모든 콘솔로그 들이 alert로 바뀐다.

use[loader1,loader2,loader3] 순서대로 실행

플러그인

  • 로더가 파일 단위로 처리하는 반면

  • 플러그인은 번들된 결과물을 처리한다. 번들된 자바스크립트를 난독화한다거나, 특정 텍스트를 추출하는 용도로 사용된다.

커스텀 플러그인

웹팩 문서의 Writing a plugin을 보면 클래스로 플러그인을 정의 하도록 한다. 헬로월드 코드를 가져다 그대로 실행 붙여보자. 기본코드

로더와 다르게 플러그인은 클래슬 제작한다. apply 함수를 구현하면되고 , 이 코드에서는 인자로 받은 compiler 객체 안에 있는 tap함수를 사용하는 코드이다. 플러그인 작업이 완료되는 시점에 콘솔 찍는것.

class MyPlugin {
  apply(compiler) {
    compiler.hooks.done.tap("My Plugin", stats => {
      console.log("MyPlugin: done")
    })
  }
}

module.exports = MyPlugin
const MyPlugin = require("./myplugin")

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

웹팩 설정 객체의 plugins 배열에 설정한다. 클래스로 제공되는 플러그인의 생성자 함수를 실행해서(객체 만들어서) 넘기는 방식이다.

바벨 로더 & 플러그인

특정 버전 이상에서만 실행되는 코드가 있고 특정 브라우저에서는 실행되지 않는 코드도 있다. 그렇기 때문에 모든 자바스크립트 실행 환경에서 정상적으로 동작할 수 있도록 하려면 바벨이 필요하다.


{
  "presets": [
    [
      "@babel/env",
      {
        "targets": "> 2%, not dead"
      }
    ]
  ],
  "plugins": ["@babel/plugin-proposal-optional-chaining"]
}

다음과 같이 babel.config.json파일을 생성해 적용하면 된다. presets에는 바벨에 대한 설정을 넣을 수 있는데 다음 코드는 전세계 2%이상의 점유율을 가진 브라우저에서 동작 가능하도록 설정한 옵션이다. 이런식으로 브라우저 점유율을 통해 설정을 할 수도 있고 각 브라우저(크롬, 사파리 등)마다 버전을 지정해 설정해줄 수 도 있다.

    module: {
      rules: [
        {
          // 처리할 모듈 형식 결정
          test: /.js$/,
          // 이 모듈에 사용할 loader
          use: "babel-loader",
          // 제외할 파일들
          exclude: /node_modules/,
        },
      ],
    },
  • webpack: 웹팩 모듈

  • webpack-cli: 터미널에서 웹팩 명령어를 사용할 수 있게 도와줌

  • webpack-dev-server: nodemon과 같이 웹팩 환경에서 개발서버를 생성

  • babel-loader: 웹팩과 바벨을 연동

모듈의 스코프

컴파일 과정에서 각 모듈은 함수로 감싸진다. 예를 들어 다음 코드에서 greeting 변수는 전역 변수지만 webpack으로 모듈이 컴파일된 뒤에는 지역 변수가 된다.

var greeting = require('./hello') + require('./world');

module.exports = greeting;  

다음은 위의 모듈을 컴파일해서 생성된 번들 파일의 내용이다. 모듈을 작성할 때 모듈의 변수가 전역 변수가 되는 것을 피하려 함수로 변수를 감쌀 필요가 없다.



...
/* 1 */
/***/ function(module, exports, __webpack_require__) {
    var greeting = __webpack_require__(2) + __webpack_require__(3);
    module.exports = greeting;

/***/ },
...

웹팩 정리

  • 편리한 모듈 의존성 관리

  • 로더를 활용한 다양한 리소스의 효율적인 활용

  • 빠른 컴파일 속도

  • 잘 정리된 문서(http://webpack.github.io/docs/)

  • webpack --watch (변경사항 적용 가능)

Reference

profile
Frontend Ninja

0개의 댓글