레이블이 JavaScript인 게시물을 표시합니다. 모든 게시물 표시
레이블이 JavaScript인 게시물을 표시합니다. 모든 게시물 표시

20210523

Vite 2 번들러 교체

CRA 기반 앱을 Vite 2로 교체했다. 2월에 2.0 나오고 지금은 2.3 정도. webpack 대비 체감은 "시동이 빠르다" 정도가 아니라 "이게 왜 가능하지" 수준.

왜 빠른가

dev 서버가 번들링을 안 한다. 브라우저가 ESM을 직접 요청하고 Vite는 요청된 파일을 온더플라이로 트랜스폼. 결과: 초기 dev server 구동이 1초 안쪽으로 떨어짐. 우리 프로젝트 기준 웹팩 CRA는 약 28초 걸림.

설정

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: { port: 3000, proxy: { '/api': 'http://localhost:8080' } },
  build: { outDir: 'build', sourcemap: true }
})

마이그레이션 시 걸린 것

  • process.env.REACT_APP_*import.meta.env.VITE_*. 변수 이름 전부 리네임.
  • webpack alias — resolve.alias로 그대로 옮기면 됨.
  • CommonJS 전용 라이브러리 몇 개가 import로 안 풀림. optimizeDeps.include에 넣어서 pre-bundle 유도.
  • svg import — @svgr/plugin-*로 플러그인 세팅 따로.
dev는 ESM이지만 prod build는 Rollup 기반. 런타임 차이가 생길 수 있다. 프로덕션 빌드로 E2E 한 번 꼭 돌려봐야 함.

결과

  • dev start: 28s → 0.9s
  • HMR: 평균 1.5s → 50ms 수준
  • prod build: 1m 40s → 55s

지금까진 만족. 단 generic한 CLI 경험은 webpack이 훨씬 레거시 친화적이라서, 오래된 앱이면 바로 옮기진 말고 PoC 먼저 하는 게 낫다.

20160114

Webpack 1에서 2 마이그레이션 노트

Webpack 2 베타로 마이그 시도. 프로젝트 하나를 2 베타에 올려봤다. 아직 GA 아니라 레퍼런스가 많진 않아서 정리.

가장 큰 변화는 ES6 모듈 네이티브 지원. import / export를 webpack이 이해하고 tree shaking 가능하게 됨. 그리고 System.import (다이나믹 임포트) 문법 도입. 라우트 기반 코드 스플리팅에 유용.

기존 1.x config에서 가장 자주 걸리는 수정:

// 1.x
module.exports = {
  module: {
    loaders: [
      { test: /\.js$/, loader: 'babel', query: { presets: ['es2015'] } }
    ]
  },
  resolve: { extensions: ['', '.js', '.jsx'] }
};

// 2.x
module.exports = {
  module: {
    rules: [
      { test: /\.js$/, use: {
          loader: 'babel-loader',
          options: { presets: ['es2015'] }
      }}
    ]
  },
  resolve: { extensions: ['.js', '.jsx'] }  // '' 빠짐
};

체크포인트:

  • loadersrules. 용어 정리됨
  • loader: 'babel' 축약표기 제거. 풀네임 babel-loader 써야함
  • queryoptions
  • resolve.extensions에서 빈 문자열 제거
  • DedupePlugin 제거. tree shaking + UglifyJS로 대체

tree shaking은 아직 효과가 제한적. Babel이 import를 require로 바꿔버리면 webpack이 해석을 못 해서 dead code 못 찾음. .babelrc"modules": false 명시 필요:

{ "presets": [["es2015", { "modules": false }]] }

베타라 문서가 안 따라오고 커뮤니티 지식도 적어서 삽질 꽤 함. 정식 나오려면 좀 더 기다려야 할듯. 그래도 dynamic import 쪽은 미리 적용하고 싶어서 계속 테스트 진행중.

20131214

jQuery 1.10 vs 1.11 호환성 체크

서비스 jQuery 1.10.2 → 1.11.0 올려도 되나 싶어 체크한 기록. 결론부터: 거의 문제없음. 다만 자체 플러그인 두 개를 손봐야 했다.

먼저 라인 선택 배경. 2.x로 못 가는 이유는 IE8. 회사 고객 중 공공/대기업 쪽에 IE8이 아직 6% 남아있어서 1.x 유지는 강제. 1.11은 bugfix 중심이고 API 브레이킹이 없다고 공식 changelog에 박혀 있다. 2.1은 기능적으로는 1.11과 같지만 IE<9 지원 코드가 제거된 버전. 같은 릴리스 사이클로 번호만 다르게 간다고 보면 됨.

실제 체크한 항목.

  • $.ajaxstatusCode 콜백 분기 — 동일
  • $.Deferred + .then 체이닝 — 동일. 1.8에 있던 then 리턴값 체이닝 버그는 이미 고쳐진 상태
  • 이벤트 delegation .on("click", "a.btn", fn) — OK
  • 오래된 $.browser 사용 플러그인(slimScroll 0.4) — 여전히 미동작. 1.9부터 제거된 API라 그대로
  • $.live / $.die — 1.9에서 이미 제거. 영향 없음
  • .attr("checked") vs .prop("checked") — 폼 체크박스 상태는 반드시 prop. 1.6 이후 고정인데 코드 리뷰하다 아직 attr 쓰는 부분 발견해서 같이 정리

걸린 건 자체 제작한 IE7 호환 플러그인 두 개. 하나가 $.support.boxModel을 참조했는데 이게 1.8에서 이미 deprecated, 1.9부터 빠진 프로퍼티다. 어쩌다 아직 살아있었는지 모르겠는데 1.10에서는 undefined라 기본값 true로 동작하다가 1.11 올리고 minify된 번들에서 조건문 분기가 꼬였다.

// 예전
if (!$.support.boxModel) {
    el.width(el.width() + padLR + borderLR);
}

// 요즘은 document.compatMode로
// Quirks 모드일 때만 IE5 식 box-sizing이 적용됨
if (document.compatMode !== "CSS1Compat") {
    el.width(el.width() + padLR + borderLR);
}

그리고 또 하나. 커스텀 autocomplete에서 keydown 이벤트를 받는데 이벤트 객체의 which 대신 keyCode를 직접 읽던 부분이 있었다. 1.11에서 normalization 타이밍이 아주 살짝 달라져서 특정 IME 조합 상태일 때 한 번씩 keyCode가 0으로 들어오는 경우를 봤다. e.which로 바꾸니 일관성 회복.

minified 용량도 체크. 1.10.2가 92.6KB, 1.11.0이 93.5KB. CDN hit율(jQuery CDN) 올라가니까 자체 호스팅에서 CDN으로 전환하는 것까지 한 번에 해버림.

<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
  // fallback
  window.jQuery || document.write(
    '<script src="/assets/js/jquery-1.11.0.min.js"><\/script>'
  );
</script>

protocol-relative URL(//) 쓰는 이유는 https 페이지에서 mixed content 방지. fallback은 CDN 못 뜨면 로컬 파일. 이거 없으면 한번씩 죽는다.

테스트 돌려 별 이슈 없으면 다음주 화요일 새벽 배포 예정. prod 반영 후 에러 집계 보고 판단.