EtoC

webpack 본문

FrontEnd/CSS

webpack

게리드 2023. 7. 29. 23:42

webpack은 웹에서 사용되는 자원(asset)들을 번들링해주는 도구이다.
번들링은 여러파일의 종속성이 존재하는경우 그파일들을 모아서 압축,변형시켜 최소화하고 필요한 과정을 거쳐 정리한 코드를 결과물로 반환한다.
쉽게말해 그 종속성이 존재하는 파일을 하나의 파일로 묶어주는 패키징과정을 말한다.
js를 구버번의 js로 바꾸거나 Sass를 CSS로 변경할 수 있는 등 많은 것을 할 수 있다.

보통 React난 Next.js 같은 것에는 webpack이 기본적을 포함되어있다.
모든 webpack.config.js파일들은 동일한 구조를 갖는데, entry, output, rules, 변형할 파일을 설정하는 방법은 기억해두자.


Webpack 설치과정

webpack documentation

npm i webpack webpack-cli -D

webpack을 설정하기 위해서는 webpack.config.js라는 파일을 만들어야 한다.

요구사항1. entry가 필요히다.

이 파일은 오래된 자바스크립트 코드만 이해할 수 있다.

그래서 지금까지써온 import나 export를 쓸 수 없고 module.export를 사용해야한다.

module.exports ={
    //entry 불러오기
  entry: './path/to/my/entry/file.js',
  //결과물을 저장할 경로와 결과물 파일설정
  output: {
     path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js',
}

entry는 우리가 처리하고자 하는 파일이다.
서버가 아닌 브라우저에서 실행되게할 폴더 client를 만들고, 안에 js폴더를, 그안에 main.js를 만들었다.
main.js 를 webpack에 전달하는는것이 목적이다.
왜냐하면 내가 만든 코드가 모든 브라우저에서 작동하리 않을 수 있는데, 웹팩은 이 파일을 받으면 모든 브라우저가 이해할 수 있는 코드로 반환해준다.

간편하게 실행하기위해 package.json의 scripts에 assets라는 스크립트를 하나 만들자.

"scripts": {
    "start": "node index.js",
    "dev": "nodemon --exec babel-node src/init.js",
    "assets": "webpack --config webpack.config.js"
  },

그러고 npm run assets를 치면..!

빠밤! 에러 발생

webpack은 절대경로를 요구하는데 나는 상대경로를 입력해서 그렇다.

./assets/라고써두었는데, desktop/myProject/wetube/src/assets/js 이런식으로 전체경로를 써야한다.

이런 복잡한 문제를 해결하기 위해 path.resolve()__dirname을 사용한다.

__dirname(directroy name)은 자바스크립트가 제공하는 상수로 파일까지의 정체 경로를 말한다.

console.log(__dirname)을 쳐보면 아래와 같이 뜬다.

console.log(__dirname);

path.resolve()는 내가 입력하는 여러 폴더들을 모아서 전체경로로 만들어준다.

const path = require("path");
console.log(path.resolve(__dirname, "assets", "js"));

굳이 /를 넣지 않아도 path.resolve()가 다 해준다.

경로에 path.resolve(__dirname, "assets", "js"를 써서 전체경로로 설정해준뒤 다시 실행해보면 잘 실행된다.

경로 폴더가 존재하지 않을경우 새로운 폴더까지 생성해서 연결해준다.

const hello = async () => {
  alert("hi! its working!");
  const x = await fetch("");
};
hello();

기존의 위처럼 적었던 entry파일의 코드를 지정해둔 절대경로에 아래의 코드로 압축해서 저장해준다.

(async () => {
  alert("hi! its working!"), await fetch("");
})();

와 코드 너무 신기하다..
이제 이 코드에 호환성을 추가해야한다.

빨간글씨로 mode옵션이 설정되어있지 않다고하는데 이건 나중에..

이제 rules라는 것을 설정해야한다.

const path = require("path");

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

rules는 각각의 파일 종류에따라 어떻게 전활할지를 경정한다.
test에 적혀있는 타입의 파일을 use에 적힌 스타일로 변형시킬것이다.
이것을 loader라고 한다. webpack은 이 loader을 통해서 전환을 한다.
BABEL loader

하지만 아직 babel loader가 없으니 설치하자.

npm install -D babel-loader

이제 프론트와 백엔드 모두 babel/core와 babell/preset-env를 사용할 수 있다.

module: {
  rules: [
    {
      test: /\.m?js$/, //자바스크립트 파일들을 변형시킨다.
      exclude: /node_modules/,
      use: {
        loader: "babel-loader", //loader를 사용해서 파일들을 처리하고
        options: {
          presets: [
            ["@babel/preset-env", { targets: "defaults" }],
            //loader시 옵션을 설정한다.
          ],
          plugins: ["@babel/plugin-proposal-class-properties"],
        },
      },
    },
  ];
}

위처럼 설정하면 webpack은 node-module에서 babel-loader를 찾고 몇가지 옵션을 받는다.
npm run assets를 실행하면 webpack은 압축된 신기한 코드와 mode 옵션이 설정되어있지않다고 빨간 글씨로 알려주는데, 개발중인지 완성된건지 설정해주어야한다.
개발중이라고 설정하면 아래의 이미지처럼 뜬다.

module.exports = {
  entry: "./src/client/js/main.js",
  mode: "development",
  ...
}

주석으로 설명도 해주며 완성된 결과물이 보고싶다면 mode를 production으로 바꾸면 된다고한다.

이제 asets안의 파일들은 webppack이 처리한 후 브라우저가, client안의 파일들은 webpack이 처리하기전의 파일들이다.

Express에게 assets/js/main.js를 알려주기

기본적으로 폴더들은 비공개이기때문에 어떤 폴더를 공개할지 정해줘야한다.
app.use를 쓴 js파일에 static파일을 설정한다.

static파일은 express에게 사람들이 이 폴더 안에 있는 파일을 볼수 있게해달라고 요청하는것이다.

app.use("/브라우저에 표시될 url명", express.static("공개할 폴더 명");

브라우저에서 설정한 경로로 접속해보면 압축된 코드가 브라우저에 뜨게된다.

이제 이 js파일을 base.pug에 연결하면..

scripts(src="/static/js/main.js")


추가사항
package.json 의 "type"이 module로 되어 있는 경우, webpack.config.js는 확장자가 .js가 아니라 .cjs 여야한다.
어떤분이 nodejs 13버전부터 type이 module로 되어 있어야 import/export를 사용할 수 있다고 해서 package.json 에 type:module을 추가로 작성해줬는데, 이번엔 이것 때문에 또 에러가 계속 났다고하며 방법은 type을 commonjs로 바꿔주던가 아니면 확장자를 바꿔주던가 둘중 하나라고 한다.