Webpack - dev-server

Jung taeWoong·2021년 10월 4일
0

개발환경

목록 보기
8/8
post-thumbnail

webpack-dev-server

  • 컴퓨터 메모리 상으로만 빌드한 결과물을 만들어서 브라우저 웹팩 빌드 결과물을 전달한다.
  • 개발하는 과정에서 매번 빌드하는 명령어를 입력하고, 빌드를 기다릴 필요없이 코드의 변경사항을 감지해서 브라우저의 변경된 점을 자동으로 반영해 준다.
  • 배포 할 경우에만 빌드를해서 결과물을 받아 서버에 넣으면 된다.

설치

$ npm i -D webpack-dev-server

기본 설정

  • 웹팩 설정 파일의 devServer 객체에 개발 서버 옵션 설정 가능
  • 관련문서

webpack.config.js

devServer 버전과 웹팩 버전이 올라가면서 설정옵션들도 변경되었다.
관련문서를 참고하자

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: 개발환경에서 특정 도메인을 맞추어야 하는 상황에서 사용
    • 쿠키 기반의 인증은 인증서버와 동일한 도메인으로 개발환경을 맞추어야 한다.
  • overlay: 빌드시 에러나 경고를 터미널창이 아닌 브라우저 화면에 표시
  • port: 개발 서버 포트번호를 설정. 기본값은 8080
  • stats: 메시지 수준을 정한다.
  • historyApiFallback: 히스토리 API를 사용하는 SPA 개발시 설정. 404가 발생하면 index.html로 리다이렉트 한다.

스크립트 작성

"scripts": {
  // --progress 옵션으로 빌드 진행상황을 퍼센트로 확인가능
  "start": "webpack-dev-server --progress"
}

API 서버 연동

mock api

  • webpack-dev-server는 Mock api를 제공하는 기능도 있다.

devServer.onBeforeSetupMiddleware

module.exports = {
  //...
  devServer: {
    onBeforeSetupMiddleware: function (devServer) {
      if (!devServer) {
        throw new Error('webpack-dev-server is not defined');
      }

      devServer.app.get('/some/path', function (req, res) {
        res.json({ custom: 'response' });
      });
    },
  },
};

devServer.proxy

  • mock api가 아닌 서버에 직접 api를 요청하는 방법

CORS란?

CORS(Cross Origin Resource Shaing) 브라우져와 서버간의 보안상의 정책인데 브라우저가 최초로 접속한 서버에서만 ajax 요청을 할 수 있다는 내용이다

  • 브라우저에서 실행되는 js는 자신이 다운로드 되었던 서버로 ajax 요청을 보낼 수 있다.
  • 서버를 식별하는 기준은 프로토콜, 도메인, 포트로 구성됨
  • js가 다운로드된 포트가 8080(최초 접속 서버 포트), ajax 요청하는 포트가 8081(api 서버 포트)이면 서버가 다르기 때문에 cors 정책에 막혀서 요청이 실패한다.

proxy란?

클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해 주는 컴퓨터 시스템
...
서버와 클라이언트 사이에 중계기로서 대리로 통신을 수행하는 것을 가리켜 '프록시', 그 중계 기능을 하는 것을 프록시 서버라고 부른다.

  • 서버간의 통신은 브라우저-서버 통신과 다르게 이러한 제약 정책이 없다.
  • 8080서버가 브라우저에서 ajax 요청을 받으면 이 요청을 8081로 보내고 받은 응답을 브라우저로 전달
  • 이러한 역할을 proxy라 한다.

CORS 해결방법 (FE)

  • 주소가 다른 api 서버를 proxy로 세팅해서 사용
  • 웹팩 개발 서버는 proxy 속성으로 이를 지원

webpack.config.js

module.exports = {
  devServer: {
    proxy: {
      /* 
       *개발서버에 들어오는 모든 http 요청중 /api로 시작되는것은 
       * https://localhost:8081로 요청하는 설정 
       */
      '/api': 'http://localhost:8081', 
    }
  }
}

Hot Module Replacement

  • 웹팩 개발 서버는 전체 화면을 갱신하기 때문에 갱신하면서 가지고 있던 데이터가 초기화 되어버린다.
  • 웹팩 개발 서버는 전체 화면을 갱신하지 않고 변경한 모듈만 갱신하는 기능으로 Hot Module Replacement를 제공한다

Hot Moudle 설정

webpack.config.js

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

Hot Module Interface 구현

  • 아래 코드와 같이 HMR(Hot Module Replacement) 인터페이스를 구현한 로더만이 핫 로딩을 지원한다. (ex: style-loader, react-hot-loader, file-loader 등)
if (module.hot) {
  console.log('hot module on');
  
  module.hot.accept('./result' /*감지할 모듈 경로*/, () => {
    console.log('감지할 모듈 변경됨');
    // 모듈이 변경되면 감지하고 등록한 콜백 실행
    // 이 모듈을 사용하는 코드를 콜백에 등록
  });
}

최적화

  • 많은 파일과 코드로 인해 번들링된 결과물이 커지면서 브라우저 성능에 영향을 줄 수 있다. (ex: 파일을 다운로드 하는 시간이 오래걸림)

production 모드

  • 최적화 방법중 가장 기본
  • 웹팩 기본설정 파일의 mode 옵션을 production으로 설정

webpack.config.js

module.exports = {
  mode: 'production'
  ...
}
  • production 모드로 설정하면 자바스크립트 결과물을 최소화 하기 위해 다음 일곱개 플러그인을 사용한다.
    • FlagDependencyUsagePlugin
    • FlagIncludedChunksPlugin
    • ModuleConcatenationPlugin
    • NoEmitOnErrosPlugin
    • OccurrenceOrderPlugin
    • SideEffectsFlagPlugin
    • TerserPlugin

외부 환경변수에 따라(NODE_ENV 값) 모드를 설정하는 방법

  • DefinePlugin을 사용하면 process.env.NODE_ENV 값을 설정하여 어플리케이션 전역변수로 들어간다.
  • 또는 NODE_ENV=production webpack 실행하여 환경변수 설정
// webpack.config.js
// 기본 값을 development로 설정
const mode = process.env.NODE_ENV || 'development'; 
module.exports = {
  mode,
}

optimazation 속성

  • 빌드 과정을 커스터마이징하는데 사용하는 속성

사용되는 플러그인

설치

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

webpack.config.js

const OptimizeCSSAssertPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
// optimization.minimizer => 웹팩이 결과물을 압축할때 사용할 플러그인을 넣는 배열
  optimization: {
    minimizer: mode === 'production' 
    ? [
      new OptimizeCSSAssetsPlugin(),
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true, // 콘솔 로그 제거
          }
        }
      })
    ] 
    : []
  }
}

코드 스플리팅

  • 코드를 압축하는 것 외에도 결과물을 여러개로 분할하면 브라우저 다운로드 속도를 높일 수 있다.
    • 큰 파일 하나를 다운받는 것보다 작은 파일 여러개 다운받는 것이 더 빠르다.

1. entry 분리

  • 개발자가 직접 나누어야 하므로 손이 많이가는 방법
module.exports = {
  // entry 파일을 여러개로 분리
  entry: {
    main: './src/app.js',
    result: './src/result.js
  },
  optimization: {
    // entry 파일을 나누면 코드가 중복되는데 중복된 코드를 제거하는 설정을 추가
    splitChunks: {
      chunks: "all"
    }
  }
}

2. dynamic import

  • 단일 엔트리를 유지하면서 코드를 분리하는 방법.
  • 대부분의 코드들은 사용자가 보는 첫 페이지에는 필요하지 않다.
  • 첫 페이지 진입시에 필요한 최소한의 코드만 다운받고 특정 페이지를 진입할때 코드를 로드한다면 초기 성능을 올릴 수 있다.
  • Dynamic Import 는 일반적인 정적인 Module Import 를 필요한 시점 에 로드 할 수 있도록 도와준다.
// Promise 를 반환 하며, export 하는 값들을 가진 객체를 반환한다.
import("module.js").then(module => {
  const { default: Component, a, b} = module;
});

Externals

  • 써드파티 라이브러리같이 이미 빌드 과정을 거친 파일들은 빌드 프로세스에서 제외시키는 설정

webpack.config.js

module.exports = {
  externals:{
    axios: 'axios'
  }
}

copy-webpack-plugin

  • 설치받은 써드파티 라이브러리들은 node_modules/library명/dist에 압축된 파일이 존재
  • 웹팩이 실행될 때 이 파일을 복사하여 dist 폴더로 옮기고 index.html에서 로딩시키면된다.
  • 파일을 복사하는 플러그인이 바로 copy-webpack-plugin

설치

npm i -D copy-webpack-plugin

webpack.config.js

module.exports = {
  plugins: [
     new CopyPlugin({
      patterns: [
        // 가져올 파일과 복사할 경로를 옵션으로 설정
        {
          from: './node_modules/axios/dist/axios.min.js',
          to: './axios.min.js'
        },
      ],
    })
  ]
}

index.html

  • index.html 파일에 복사한 파일 로딩
<script type="text/javascript" src="axios.min.js"><script>
profile
Front-End 😲

0개의 댓글