Process

1. user api request

2. enter middleware

3. need auth ( x => logger middleware )

4. session middleware ( iron-session )

5. auth middleware ( get access token or refresh token or response UnAuthorization)

6. logger middleware ( who , what log api request )

7. server axios response ( if error return error response from next api server to client )

8. client get response ( if error catch throw error to error boundary )

9. error boundary catch error 

 

728x90

Process basic

1. web open

2. cookie 내 server refresh token 확인

3. refresh token으로 서버용 access token 발급

4. server refresh api 호출시 kakao 토큰 갱신, 서버 토큰 갱신

5. 갱신된 토큰 받아 cookie 저장

728x90

'Structure > diagram' 카테고리의 다른 글

nextjs api error, axios error handling  (0) 2022.07.14

webpack - 개발서버,API,HMR,최적화

웹팩 개발 서버

배경

운영환경과 맞춤으로써 배포시 잠재적 문제를 미리 확인할 수 있다. 게다가 ajax 방식의 api 연동은 cors 정책 때문에 반드시 서버가 필요

프론트엔드 개발환경에서 이러한 개발용 서버를 제공해 주는 것이 webpack-dev-server다.

설치 및 사용

npm i -D webpack-dev-server

package.json

{
  "scripts": {
    "start": "webpack-dev-server"
  }
}

웹팩 서버는 파일 변화를 감지하면 웹팩 빌드를 다시 수행하고 브라우져를 리프레시하여 변경된 결과물을 보여준다.

기본 설정

webpack.config.js

module.exports = {
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    publicPath: "/",
    host: "dev.domain.com",
    overlay: true,
    port: 8081,
    stats: "errors-only",
    historyApiFallback: true,
  },
}

contentBase: 정적파일을 제공할 경로. 기본값은 웹팩 아웃풋이다.

publicPath: 브라우져를 통해 접근하는 경로. 기본값은 '/' 이다.

host: 개발환경에서 도메인을 맞추어야 하는 상황에서 사용한다. 예를들어 쿠기 기반의 인증은 인증 서버와 동일한 도메인으로 개발환경을 맞추어야 한다. 운영체제의 호스트 파일에 해당 도메인과 127.0.0.1 연결한 추가한 뒤 host 속성에 도메인을 설정해서 사용한다.

overlay: 빌드시 에러나 경고를 브라우져 화면에 표시한다.

port: 개발 서버 포트 번호를 설정한다. 기본값은 8080.

stats: 메시지 수준을 정할수 있다. 'none', 'errors-only', 'minimal', 'normal', 'verbose' 로 메세지 수준을 조절한다.

historyApiFallBack: 히스토리 API를 사용하는 SPA 개발시 설정한다. 404가 발생하면 index.html로 리다이렉트한다.

API 연동

목업 API 1 : devServer.before

webpack.config.js

module.exports = {
  devServer: {
    before: (app, server, compiler) => {
      app.get("/api/keywords", (req, res) => {
        res.json([
          { keyword: "이탈리아" },
          { keyword: "세프의요리" },
          { keyword: "제철" },
          { keyword: "홈파티" },
        ])
      })
    },
  },
}

before에 설정한 미들웨어는 익스프레스에 의해서 app 객체가 인자로 전달되는데 Express 인스턴스다. 이 객체에 라우트 컨트롤러를 추가할 수 있는데 app.get(url, controller) 형태로 함수를 작성한다. 컨트롤러에서는 요청 req과 응답 res 객체를 받는데 여기서는 res.json() 함수로 응답하는 코드를 만들었다.

목업 API 2 : connect-api-mocker

connect-api-mocker

특정 목업 폴더를 만들어 api 응답을 담은 파일을 저장한 뒤, 이 폴더를 api로 제공해 주는 기능을 한다

mocks / api / users / GET.json

[
  { "keyword": "이탈리아" },
  { "keyword": "세프의요리" },
  { "keyword": "제철" },
  { "keyword": "홈파티 " }
]

webpack.config.js

const apiMocker = require("connect-api-mocker")

module.exports = {
  devServer: {
    before: (app, server, compiler) => {
      app.use(apiMocker("/api", "mocks/api")) // root url , mocks 파일 위치
    },
  },
}

proxy setting

webpack.config.js

module.exports = {
  devServer: {
    proxy: {
      "/api": "<http://localhost:8081>", // 프록시
    },
  },
}

핫 모듈 리플레이스먼트

전체화면을 갱신하지 않고 변경한 모듈만 바꿔치기하는 웹팩 개발서버의 한 기능

설정

webpack.config.js

module.exports = {
  devServer = {
    hot: true,
  },
}

app.js

view.js파일의 변경이 감지되면 그 부분만 모듈이 변경되어 랜더링됨

// module.hot 실행
if (module.hot) {
	// 변경 감지
  module.hot.accept("./view", async () => {
		// 리랜더링
    view.render(await model.get(), controller.el) // 변경된 모듈로 교체
  })
}

핫로딩을 지원하는 로더

이러한 핫 모듈 리플레이스먼트(HMR)인터페이스를 구현한 로더만이 핫 로딩을 지원함

지원하는 모듈

최적화

코드가 많아지면 번들링된 결과물도 커지기 마련 → 성능에 영향

production 모드

웹팩에 내장되어 있는 최적화 방법중 mode 값을 설정하는 방식이 가장 기본이다. 세 가지 값이 올 수 있는데 지금까지 설정한 "development"는 디버깅 편의를 위해 아래 두 개 플러그인을 사용한다.

  • NamedChunksPlugin
  • NamedModulesPlugin

DefinePlugin을 사용한다면 process.env.NODE_ENV 값이 "development"로 설정되어 어플리케이션에 전역변수로 주입된다.

반면 mode를 "production"으로 설정하면 자바스크립트 결과물을 최소화 하기 위해 다음 일곱 개 플러그인을 사용한다.

  • FlagDependencyUsagePlugin
  • FlagIncludedChunksPlugin
  • ModuleConcatenationPlugin
  • NoEmitOnErrorsPlugin
  • OccurrenceOrderPlugin
  • SideEffectsFlagPlugin
  • TerserPlugin

DefinePlugin을 사용한다면 process.env.NODE_ENV 값이 "production" 으로 설정되어 어플리케이션 전역변수로 들어간다.

환경변수 NODE_ENV 값에 따라 모드를 설정

webpack.config.js

const mode = process.env.NODE_ENV || "development" // 기본값을 development로 설정

module.exports = {
  mode,
}

빌드 시에 production 모드로 설정하여 실행하도록 npm script 추가

package.json

{
  "scripts": {
    "start": "webpack-dev-server --progress",
    "build": "NODE_ENV=production webpack --progress"
  }
}

optimazation 속성으로 최적화

빌드 과정을 커스터마지징할 수 있는 속성 ⇒  optimazation 속성

HtmlWebpackPlugin이 html 파일을 압축한것 처럼 css 파일도 빈칸을 없애는 압축 ⇒ assets-webpack-plugin

npm i -D optimize-css-assets-webpack-plugin

webpack.config.js

const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin")

module.exports = {
  optimization: {
    minimizer: mode === "production" ? [new OptimizeCSSAssetsPlugin()] : [],
  },
}

optimization.minimizer 는 웹팩이 결과물을 압축할때 사용할 플러그인을 넣는 배열

TerserWebpackPlugin은 자바스크립트 코드를 난독화하고 debugger 구문을 제거한다. 기본 설정 외에도 콘솔 로그를 제거하는 옵션도 있다

npm i -D terser-webpack-plugin

webpack.config.js

const TerserPlugin = require("terser-webpack-plugin")
module.exports = {
  optimization: {
    minimizer:
      mode === "production"
        ? [
            new TerserPlugin({
              terserOptions: {
                compress: {
                  drop_console: true, // 콘솔 로그를 제거한다
                },
              },
            }),
          ]
        : [],
  },
}

코드 스플리팅

코드를 압축하는 것 외에도 아예 결과물을 여러개로 쪼개면 좀 더 브라우져 다운로드 속도를 높일 수 있다.

엔트리를 여러개로 분리

빌드하면 엔트리별로 js 파일이 생성됨 그러나 중복코드가 존재함

SplitChunksPlugin 이 플러그인을 사용해 중복 코드 제거 ⇒ 중복되어 사용되는 코드는 vendor.js 파일에 저장

webpack.config.js

module.exports = {
	entry: {
    main: "./src/app.js",
    controller: "./src/controller.js",
  },
  optimization: {
    splitChunks: {
      chunks: "all", // 중복 코드 제거
    },
  },
}

다이나믹 임포트

엔트리를 여러개로 자동으로 분리

app.js

import controller from "./controller"

document.addEventListener("DOMContentLoaded", () => {
  controller.init(document.querySelector("#app"))
})
// ----- dynamic import로 변경 ----
function getController() {
  return import(/* webpackChunkName: "controller" */ "./controller").then(m => {
    return m.default
  })
}

document.addEventListener("DOMContentLoaded", () => {
  getController().then(controller => {
    controller.init(document.querySelector("#app"))
  })
})

import() 함수로 가져올 컨트롤러 모듈 경로를 전달하는데 주석으로 webpackHunkName: "controller"를 전달했다. 이것은 웹펙이 이 파일을 처리할때 청크로 분리하는데 그 청그 이름을 설정한 것

이렇게 하면 webpack.config.js의 entry를 하나로 유지하면서 중복코드도 제거하며 코드를 분리할 수 있다.

externals

axios 같은 써드파티 라이브러리는 패키지로 제공될때 이미 빌드 과정을 거쳤기 때문에 빌드 프로세스에서 제외하는 것이 좋다.

webpack.config.js

module.exports = {
  externals: {
    axios: "axios",
  },
}

externals에 추가하면 웹팩은 코드에서 axios를 사용하더라도 번들에 포함하지 않고 빌드한다.

axios는 이미 node_modules에 위치해 있기 때문에 이를 웹팩 아웃풋 폴더에 옮기고 index.html에서 로딩해야한다. 파일을 복사하는 CopyWebpackPlugin을 설치한다.

npm i -D copy-webpack-plugin

webpack.config.js

const CopyPlugin = require("copy-webpack-plugin")

module.exports = {
  plugins: [
    new CopyPlugin([
      {
        from: "./node_modules/axios/dist/axios.min.js",
        to: "./axios.min.js", // 목적지 파일에 들어간다
      },
    ]),
  ],
}

마지막으로 index.html에서 axios를 로딩하는 코드를 추가한다.

 

※ 출저

https://www.inflearn.com/course/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD/dashboard

 

프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..) - 인프런 | 강의

이미 만들어 놓은 개발 환경을 이해할 수 있어요. 처음부터 직접 개발 환경을 만들 수 있어요., - 강의 소개 | 인프런...

www.inflearn.com

 

728x90

'Study > webpack' 카테고리의 다른 글

webpack@4 - lint,prettier  (0) 2022.06.04
webpack@4 - babel - basic  (0) 2022.06.04
webpack@4 - plugin  (0) 2022.06.04
webpack@4 - loader  (0) 2022.06.04
webpack@4 - 엔트리/아웃풋  (0) 2022.06.04

webpack - lint,prettier

배경

코드의 오류나 버그, 스타일 따위를 점검하는 것을 린트(Lint) 혹은 린터(Linter)

EsLint

개념

코드의 가독성을 높이고 잠재적인 오류와 버그를 제거

검사 항목

  • 포맷팅
    • 일관된 코드 스타일
  • 코드 품질
    • 어플리케이션의 잠재적인 오류나 버그 예방

설치 및 사용법

npm i -D eslint

Rules

문서의 Rules 메뉴에서 규칙 목록을 확인

규칙에 설정하는 값은 세 가지다. "off"나 0은 끔, "warn"이나 1은 경고, "error"나 2는 오류.

설정한 규칙에 어긋나는 코드를 발견하면 오류를 출력

.eslintrc.js

module.exports = {
  rules: {
    "no-unexpected-multiline": "error",
    "no-extra-semi": "error",
  },
};
  • 추천 옵션 적용

.eslintrc.js

module.exports = {
  extends: [
    "eslint:recommended", // 미리 설정된 규칙 세트을 사용한다
  ],
};

초기화

npx eslint --init

Prettier

설치 및 사용법

npm i -D prettier

prettier 검사

  • —write 옵션은 파일을 재작성
npx prettier app.js --write

통합방법

npm i -D eslint-config-prettier

.eslintrc.js

module.exports = {
  extends: [
    "eslint:recommended", // 미리 설정된 규칙 세트을 사용한다
    "eslint-config-prettier", // prettier와 충돌하는 옵션 끄기
  ],
};

eslint-plugin-prettier는 프리티어 규칙을 ESLint 규칙으로 추가하는 플러그인이다. 프리티어의 모든 규칙이 ESLint로 들어오기 때문에 ESLint만 실행

npm i -D eslint-plugin-prettier

.eslintrc.js

module.exports = {
  extends: [
    "eslint:recommended", // 미리 설정된 규칙 세트을 사용한다
    "eslint-config-prettier",
  ],
  plugins: ["prettier"], // 플러그인 추가
  rules: {
    "prettier/prettier": "error",
  },
};

.eslintrc.js

module.exports = {
  extends: [
    "eslint:recommended", // 미리 설정된 규칙 세트을 사용한다
    "plugin:prettier/recommended", // prettier 단순 설정
  ],
};

자동화

husky

커밋 전, 푸시 전 등 깃 커맨드 실행 시점에 끼여들수 있는 훅을 제공한다.

husky는 깃 훅을 쉽게 사용할 수 있는 도구이다.

npm i -D husky

package.json

{
  "husky": {
    "hooks": {
      "pre-commit": "eslint app.js --fix"
    }
  }
}

스테이징된 파일만 린트 수행

npm i -D lint-staged

package.json

{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.js": "eslint --fix"
  }
}

※ 출저

https://www.inflearn.com/course/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD/dashboard

 

프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..) - 인프런 | 강의

이미 만들어 놓은 개발 환경을 이해할 수 있어요. 처음부터 직접 개발 환경을 만들 수 있어요., - 강의 소개 | 인프런...

www.inflearn.com

 

728x90

'Study > webpack' 카테고리의 다른 글

webpack@4 - 개발서버,API,HMR,최적화  (0) 2022.06.05
webpack@4 - babel - basic  (0) 2022.06.04
webpack@4 - plugin  (0) 2022.06.04
webpack@4 - loader  (0) 2022.06.04
webpack@4 - 엔트리/아웃풋  (0) 2022.06.04

babel - basic

배경

크로스 브라우징

브라우저 마다 사용하는 언어가 달라 프론트엔트 코드는 일관적이지 못할 때가 많다.

바벨은 ECMAScript2015+로 작성한 코드를 모든 브라우저에서 동작하도록 호환성을 지켜준다.

트랜스 파일과 빌드

변환 전후의 추상화 수준이 다른 빌드와는 달리 트랜스파일은 추상화 수준을 유지한 상태로 코드를 변환한다. 타입스크립트 → 자바스크립트, JSX → 자바스크립트처럼 트랜스파일 후에도 여전히 코드를 읽을 수 있다.

바벨의 기본 동작

npm install -D @babel/core  @babel/cli

바벨은 세 단계로 빌드를 진행한다.

  1. 파싱(Parsing)
    1. 코드를 읽고 추상 구문 트리로 변환하는 단계
    2. 코드를 받아 토큰 별로 분해
  2. 변환(Transforming)
    1. 바벨의 플러그인이 담당
  3. 출력 (Printing)

플러그인

커스텀 플러그인

바벨 홈페이지 예제

// my-babel-plugin.js:
module.exports = function myBabelPlugin() {
  return {
    visitor: {
      Identifier(path) {
        const name = path.node.name

        // 바벨이 만든 AST 노드를 출력한다
        console.log("Identifier() name:", name)

        // 변환작업: 코드 문자열을 역순으로 변환한다
        path.node.name = name.split("").reverse().join("")
      },
    },
  }
}

사용법

npx babel --help

  --plugins [list]                            A comma-separated list of plugin names.

활용

const 코드를 var로 변경하는 플러그인

module.exports = function myBabelPlugin() {
  return {
    visitor: {
      VariableDeclaration(path) {
        console.log("VariableDeclaration() kind:", path.node.kind); // const

        if (path.node.kind === "const") {
          path.node.kind = "var";
        }
      },
    },
  };
};

결과

$ npx babel app.js --plugins './my-babel-plugin.js'
// VariableDeclaration() kind: const
// var alert = msg => window.alert(msg);

실제 플러그인 사용하기

plugin-transform-block-scoping

npm install -D @babel/plugin-transform-block-scoping

결과

$ npx babel app.js --plugins @babel/plugin-transform-block-scoping
var alert = msg => window.alert(msg);

화살표 함수

npm install -D @babel/plugin-transform-arrow-functions

결과

$ npx babel app.js --plugins @babel/plugin-transform-block-scoping --plugins @babel/plugin-transform-arrow-functions
var alert = function (msg) {
  return window.alert(msg);
};

엄격모드 “use strict”

npm install -D @babel/plugin-transform-strict-mode

결과

$ npx babel app.js --plugins @babel/plugin-transform-block-scoping --plugins @babel/plugin-transform-arrow-functions --plugins @babel/plugin-transform-strict-mode
"use strict";

var alert = function (msg) {
  return window.alert(msg);
};

babel.config.js

module.exports = {
  plugins: [
    "@babel/plugin-transform-block-scoping ",
    "@babel/plugin-transform-arrow-functions ",
    "@babel/plugin-transform-strict-mode",
  ],
};

결과

$ npx babel app.js
"use strict";

var alert = function (msg) {
  return window.alert(msg);
};

프리셋

ECMAScript2015+으로 코딩할 때 필요한 플러그인을 일일이 설정하는 일은 무척 비효율적인 일이다.

목적에 맞게 여러가지 플러그인을 세트로 모아놓은 것을 "프리셋"이라고 한다.

커스텀 프리셋

my-babel-preset.js

module.exports = function myBabelPreset() {
  return {
    plugins: [
      "@babel/plugin-transform-block-scoping",
      "@babel/plugin-transform-arrow-functions",
      "@babel/plugin-transform-strict-mode",
    ],
  };
};

babel.config.js

module.exports = {
  presets: ["./my-babel-preset.js"],
};

프리셋 사용하기

프리셋 docs

  • preset-env
  • preset-flow
  • preset-react
  • preset-typescript

preset-env

npm install -D @babel/preset-env

babel.config.js

module.exports = {
  presets: ["@babel/preset-env"],
};

결과

$ npx babel app.js                
"use strict";

var alert = function alert(msg) {
  return window.alert(msg);
};

env 프리셋 설정과 폴리필

타켓 브라우저

브라우저 호환에 맞게끔 변환

module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        targets: {
          chrome: "79",
          ie: "11", // ie 11까지 지원하는 코드를 만든다
        },
      },
    ],
  ],
};

폴리필

바벨은 ECMAScript2015+를 ECMAScript5 버전으로 변환할 수 있는 것만 빌드한다.

그렇지 못한 것들은 "폴리필"이라고부르는 코드조각을 추가해서 해결

app.js

new Promise();

babel.config.js

useBuiltIns는 어떤 방식으로 폴리필을 사용할지 설정하는 옵션이다. "usage" , "entry", false 세 가지 값을 사용

바벨 문서의 useBuiltIns와 corejs 섹션을 참고

module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        useBuiltIns: "usage", // 폴리필 사용 방식 지정
        corejs: {
          // 폴리필 버전 지정
          version: 2,
        },
      },
    ],
  ],
}

결과

$ npx babel app.js
"use strict";

require("core-js/modules/es.object.to-string.js");

require("core-js/modules/es.promise.js");

var alert = function alert(msg) {
  return window.alert(msg);
};

new Promise();

웹팩으로 통합

npm install -D babel-loader

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader", // 바벨 로더를 추가한다
      },
    ],
  },
}

※ 출저

https://www.inflearn.com/course/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD/dashboard

 

프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..) - 인프런 | 강의

이미 만들어 놓은 개발 환경을 이해할 수 있어요. 처음부터 직접 개발 환경을 만들 수 있어요., - 강의 소개 | 인프런...

www.inflearn.com

 

728x90

'Study > webpack' 카테고리의 다른 글

webpack@4 - 개발서버,API,HMR,최적화  (0) 2022.06.05
webpack@4 - lint,prettier  (0) 2022.06.04
webpack@4 - plugin  (0) 2022.06.04
webpack@4 - loader  (0) 2022.06.04
webpack@4 - 엔트리/아웃풋  (0) 2022.06.04

webpack - plugin

플러그인

플러그인 역할

플러그인은 번들된 결과물을 처리 ( ↔  로더는 파일 단위로 처리)

ex) 자바스크립트 난독화 , 특정 텍스트 추출

커스텀 플러그인

만들기

웹팩 문서의 Writing a plugin을 보면 클래스로 플러그인을 정의

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

module.exports = MyPlugin

webpack.config.js

const MyPlugin = require("./myplugin")

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

플러그인은 하나로 번들링된 결과물을 대상으로 동작하기 때문에 로그가 한번 찍힘

플러그인이 번들 결과에 접근하는 방법

웹팩 내장 플러그인 BannerPlugin 코드를 참고

→ compilation 객체를 이용해서 접근

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

    // compiler.plugin() 함수로 후처리한다
    compiler.plugin("emit", (compilation, callback) => {
      const source = compilation.assets["main.js"].source()
      console.log(source)
      callback()
    })
  }
}

webpack 번들링된 결과물에 banner 추가해보기

myplugin.js

class MyPlugin {
  apply(compiler) {
    compiler.plugin("emit", (compilation, callback) => {
      const source = compilation.assets["main.js"].source();
      compilation.assets["main.js"].source = () => {
        const banner = [
          "/**",
          " * 이것은 BannerPlugin이 처리한 결과입니다.",
          " * Build Date 2022-06-04",
          " */",
        ].join("\\n");
        return banner + "\\n\\n" + source;
      };
      callback();
    });
  }
}
module.exports = MyPlugin;

자주 사용하는 플러그인

BannerPlugin

결과물에 빌드 정보나 커밋 버전 등 추가

빌드하고 배포했을때 정적파일들이 잘 배포되었는지 확인

webpack.config.js

const webpack = require("webpack");
const childProcess = require("child_process");
module.exports = {
...
  plugins: [
    new webpack.BannerPlugin({
      banner: `
      Build Date: ${new Date().toLocaleString()}
      Commit Version: ${childProcess.execSync("git rev-parse --short HEAD")}
      Author: ${childProcess.execSync("git config user.name")}
      `,
    }),
  ],
};

DefinePlugin

어플리케이션은 개발환경과 운영환경으로 나눠서 운영한다. 가령 환경에 따라 API 서버 주소가 다를 수 있다. 같은 소스 코드를 두 환경에 배포하기 위해서는 이러한 환경 의존적인 정보를 소스가 아닌 곳에서 관리하는 것이 좋다

웹팩은 이러한 환경 정보를 제공하기 위해 DefinePlugin을 제공

webpack.config.js

const webpack = require("webpack")

export default {
  plugins: [
		new webpack.DefinePlugin({
      TWO: "1+1",
      THREE: JSON.stringify("1+1"),
      "api.domain": JSON.stringify("<http://dev.api.domain.com>"),
    }),
	],
}

app.js

console.log(process.env.NODE_ENV); // development
console.log(TWO); // 2
console.log(THREE); // 1+1
console.log(api.domain); // <http://dev.api.domain.com>

HtmlWebpackPlugin

HtmlWebpackPlugin은 HTML 파일을 후처리하는데 사용한다. 빌드 타임의 값을 넣거나 코드를 압축할수 있다.

이 플러그인으로 빌드하면 HTML파일로 아웃풋에 생성된다.

→ 유동적으로 HTML 파일을 생성가능

$ npm install -D html-webpack-plugin

src/index.html

<!DOCTYPE html>
<html>
  <head>
    <title>타이틀<%= env %></title>
  </head>
  <body>
    <!-- 로딩 스크립트 제거 -->
    <!-- <script src="dist/main.js"></script> -->
  </body>
</html>

<%= env %> 는 전달받은 env 변수 값을 출력한다. HtmlWebpackPlugin은 이 변수에 데이터를 주입시켜 동적으로 HTML 코드를 생성한다.

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html', // 템플릿 경로를 지정
      templateParameters: { // 템플릿에 주입할 파라매터 변수 지정
        env: process.env.NODE_ENV === 'development' ? '(개발용)' : '',
      },
			// 파일 압축
			minify: process.env.NODE_ENV === 'production' ? {
			    collapseWhitespace: true, // 빈칸 제거
			    removeComments: true, // 주석 제거
			  } : false,
	    }),
			// 정적파일 배포할때 캐쉬때문에 브라우저에 바로 반영되지 않는 경우
			hash: true, // 정적 파일을 불러올때 쿼리문자열에 웹팩 해쉬값을 추가한다
  ]
}

CleanWebpackPlugin

빌드 이전 결과물을 제거하는 플러그인 ( dist폴더 삭제 후 재생성)

npm install -D clean-webpack-plugin

webpack.config.js

const { CleanWebpackPlugin } = require("clean-webpack-plugin")

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

MiniCssExtractPlugin

번들 결과에서 스타일시트 코드만 뽑아서 별도의 CSS파일로 만들어줌

$ npm install -D mini-css-extract-plugin

webpack.config.js

  • production 환경일 경우만 이 플러그인을 추가 filename 에 설정한 값으로 아웃풋 경로에 생성
  • 프로덕션 환경에서는 별도의 CSS 파일으로 추출하는 플러그인을 적용했으므로 다른 로더가 필요

webpack - plugin

플러그인

플러그인 역할

플러그인은 번들된 결과물을 처리 ( ↔  로더는 파일 단위로 처리)

ex) 자바스크립트 난독화 , 특정 텍스트 추출

커스텀 플러그인

만들기

웹팩 문서의 Writing a plugin을 보면 클래스로 플러그인을 정의

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

module.exports = MyPlugin

webpack.config.js

const MyPlugin = require("./myplugin")

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

플러그인은 하나로 번들링된 결과물을 대상으로 동작하기 때문에 로그가 한번 찍힘

플러그인이 번들 결과에 접근하는 방법

웹팩 내장 플러그인 BannerPlugin 코드를 참고

→ compilation 객체를 이용해서 접근

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

    // compiler.plugin() 함수로 후처리한다
    compiler.plugin("emit", (compilation, callback) => {
      const source = compilation.assets["main.js"].source()
      console.log(source)
      callback()
    })
  }
}

webpack 번들링된 결과물에 banner 추가해보기

myplugin.js

class MyPlugin {
  apply(compiler) {
    compiler.plugin("emit", (compilation, callback) => {
      const source = compilation.assets["main.js"].source();
      compilation.assets["main.js"].source = () => {
        const banner = [
          "/**",
          " * 이것은 BannerPlugin이 처리한 결과입니다.",
          " * Build Date 2022-06-04",
          " */",
        ].join("\\n");
        return banner + "\\n\\n" + source;
      };
      callback();
    });
  }
}
module.exports = MyPlugin;

자주 사용하는 플러그인

BannerPlugin

결과물에 빌드 정보나 커밋 버전 등 추가

빌드하고 배포했을때 정적파일들이 잘 배포되었는지 확인

webpack.config.js

const webpack = require("webpack");
const childProcess = require("child_process");
module.exports = {
...
  plugins: [
    new webpack.BannerPlugin({
      banner: `
      Build Date: ${new Date().toLocaleString()}
      Commit Version: ${childProcess.execSync("git rev-parse --short HEAD")}
      Author: ${childProcess.execSync("git config user.name")}
      `,
    }),
  ],
};

DefinePlugin

어플리케이션은 개발환경과 운영환경으로 나눠서 운영한다. 가령 환경에 따라 API 서버 주소가 다를 수 있다. 같은 소스 코드를 두 환경에 배포하기 위해서는 이러한 환경 의존적인 정보를 소스가 아닌 곳에서 관리하는 것이 좋다

웹팩은 이러한 환경 정보를 제공하기 위해 DefinePlugin을 제공

webpack.config.js

const webpack = require("webpack")

export default {
  plugins: [
		new webpack.DefinePlugin({
      TWO: "1+1",
      THREE: JSON.stringify("1+1"),
      "api.domain": JSON.stringify("<http://dev.api.domain.com>"),
    }),
	],
}

app.js

console.log(process.env.NODE_ENV); // development
console.log(TWO); // 2
console.log(THREE); // 1+1
console.log(api.domain); // <http://dev.api.domain.com>

HtmlWebpackPlugin

HtmlWebpackPlugin은 HTML 파일을 후처리하는데 사용한다. 빌드 타임의 값을 넣거나 코드를 압축할수 있다.

이 플러그인으로 빌드하면 HTML파일로 아웃풋에 생성된다.

→ 유동적으로 HTML 파일을 생성가능

$ npm install -D html-webpack-plugin

src/index.html

<!DOCTYPE html>
<html>
  <head>
    <title>타이틀<%= env %></title>
  </head>
  <body>
    <!-- 로딩 스크립트 제거 -->
    <!-- <script src="dist/main.js"></script> -->
  </body>
</html>

<%= env %> 는 전달받은 env 변수 값을 출력한다. HtmlWebpackPlugin은 이 변수에 데이터를 주입시켜 동적으로 HTML 코드를 생성한다.

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html', // 템플릿 경로를 지정
      templateParameters: { // 템플릿에 주입할 파라매터 변수 지정
        env: process.env.NODE_ENV === 'development' ? '(개발용)' : '',
      },
			// 파일 압축
			minify: process.env.NODE_ENV === 'production' ? {
			    collapseWhitespace: true, // 빈칸 제거
			    removeComments: true, // 주석 제거
			  } : false,
	    }),
			// 정적파일 배포할때 캐쉬때문에 브라우저에 바로 반영되지 않는 경우
			hash: true, // 정적 파일을 불러올때 쿼리문자열에 웹팩 해쉬값을 추가한다
  ]
}

CleanWebpackPlugin

빌드 이전 결과물을 제거하는 플러그인 ( dist폴더 삭제 후 재생성)

npm install -D clean-webpack-plugin

webpack.config.js

const { CleanWebpackPlugin } = require("clean-webpack-plugin")

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

MiniCssExtractPlugin

번들 결과에서 스타일시트 코드만 뽑아서 별도의 CSS파일로 만들어줌

$ npm install -D mini-css-extract-plugin

webpack.config.js

  • production 환경일 경우만 이 플러그인을 추가 filename 에 설정한 값으로 아웃풋 경로에 생성
  • 프로덕션 환경에서는 별도의 CSS 파일으로 추출하는 플러그인을 적용했으므로 다른 로더가 필요

 

※ 출저

https://www.inflearn.com/course/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD/dashboard

 

프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..) - 인프런 | 강의

이미 만들어 놓은 개발 환경을 이해할 수 있어요. 처음부터 직접 개발 환경을 만들 수 있어요., - 강의 소개 | 인프런...

www.inflearn.com

 

728x90

'Study > webpack' 카테고리의 다른 글

webpack@4 - lint,prettier  (0) 2022.06.04
webpack@4 - babel - basic  (0) 2022.06.04
webpack@4 - loader  (0) 2022.06.04
webpack@4 - 엔트리/아웃풋  (0) 2022.06.04
webpack@4 - basic  (0) 2022.06.04

+ Recent posts