ES5 번들을 부풀리는 3가지 JavaScript 기능

모든 웹 개발자는 멋진 ES6+ 기능(제너레이터, 반복 가능, async-await 등)을 좋아합니다. 그것들을 사용하는 데 어떤 문제가 있습니까?

나쁜 오래된 브라우저



슬프지만 사람들은 여전히 ​​오래된 브라우저를 사용합니다. 여기서 IE에 대해 구체적으로 말하는 것이 아닙니다. 일부 사람들은 휴대폰에서 자동 업데이트를 끄고 더 이상 신경 쓰지 않습니다. 참으로 슬프다 😥

내가 신경써야 하나?



일부 앱을 개발하는 경우에 따라 다릅니다. 당신은 당신의 사용자를 더 잘 알고 있습니다. 아마도 그들은 기술적으로 발전했고 단순히 오래된 브라우저를 사용하지 않을 것입니다. 또는 IE 사용자 비율이 작고 비용을 지불하지 않으므로 완전히 무시할 수 있습니다.

그러나 JS lib를 작성하는 중이라면 반드시 해야 합니다. 현재로서는 libs가 일반적으로 ES5로 트랜스파일되어 어떤 환경에서도 작동할 수 있도록 배포됩니다(그러나 폴리필을 요구하는 것은 괜찮다고 가정함).

자, 멋진 ES6+ 코드를 크고 부풀려진 ES5로 바꾸는 JS 기능이 무엇인지 봅시다!

1. 발전기



아마도 가장 유명한 ES5 적대적 구성일 것입니다. 에어비앤비has a separate note가 올라올 정도로 눈에 띈다.

입력




function* gen() {
    yield 1
    yield 2
}


TypeScript 출력




var __generator = /* Somewhat long helper function */

function gen() {
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0: return [4 /*yield*/, 1];
            case 1:
                _a.sent();
                return [4 /*yield*/, 2];
            case 2:
                _a.sent();
                return [2 /*return*/];
        }
    });
}


TypeScript에 대한 좋은 소식은 번들당 한 번 __generator와 같은 도우미 함수를 정의하는 것입니다. 그러나 생성기 정의는 항상 소스만큼 좋지 않은 유한 오토마타로 변환됩니다 😕

바벨 출력




require("regenerator-runtime/runtime.js");

var _marked = /*#__PURE__*/regeneratorRuntime.mark(gen);

function gen() {
  return regeneratorRuntime.wrap(function gen$(_context) {
    while (1) {
      switch (_context.prev = _context.next) {
        case 0:
          _context.next = 2;
          return 1;

        case 2:
          _context.next = 4;
          return 2;

        case 4:
        case "end":
          return _context.stop();
      }
    }
  }, _marked);
}


Babel은 더 나아가 모든 생성기 런타임을 다른 모듈로 이동합니다. 불행히도 꽤 큽니다 🐘

무엇을 할까요?



이터러블을 사용합니다. 하지만 조심하세요. 코드를 부풀릴 수 있는 방법도 있습니다 😉

2. 비동기 대기



뭐? Promise에 대한 구문 설탕이 아닌가요? 보자!

입력




export async function fetchExample() {
    const r = await fetch('https://example.com')
    return await r.text();
}


TypeScript 출력




var __awaiter = /* Some convoluted JS code */

var __generator = /* We saw it already! */

function fetchExample() {
    return __awaiter(this, void 0, void 0, function () {
        var r;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, fetch('https://example.com')];
                case 1:
                    r = _a.sent();
                    return [4 /*yield*/, r.text()];
                case 2: return [2 /*return*/, _a.sent()];
            }
        });
    });
}


발전기보다 더 나쁘다! async-await 실제로 Promise에서 추가로 일시 중단되는 생성기입니다.

바벨 출력




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

function asyncGeneratorStep/* Like __awaiter */
function _asyncToGenerator/* Yet another converter */

function fetchExample() {
  return _fetchExample.apply(this, arguments);
}

function _fetchExample() {
  _fetchExample = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
    var r;
    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return fetch('https://example.com');

          case 2:
            r = _context.sent;
            _context.next = 5;
            return r.text();

          case 5:
            return _context.abrupt("return", _context.sent);

          case 6:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));
  return _fetchExample.apply(this, arguments);
}


Babel은 TypeScript와 마찬가지로 async-await를 생각합니다. 몇 가지 추가 항목이 있는 생성기이므로 가져오기뿐만 아니라 일부 도우미 함수도 생성합니다.

무엇을 할까요?



간단한 Promise 체인을 사용하십시오. 너무 "전통적"으로 보일 수 있지만 어떤 것으로도 잘 변환됩니다.

3. 반복 가능한 반복



여러 JS 구성으로 인해 반복자 반복이 발생합니다. for-of 루프, 반복 가능한 확산 및 반복 가능한 구조 해제.

그러나 이 기능에 대한 몇 가지 좋은 소식이 있습니다.

  • TypeScript: 컴파일러가 없으면 downlevelIteration 1) 배열 반복만 허용하고 2) 반복을 단순 인덱싱된 액세스로 변환합니다
  • .

  • Babel: 컴파일러가 배열을 유추하는 경우 단순 인덱싱된 액세스를 사용합니다
  • .

    그러나 이러한 소식이 코드에 적용되지 않으면 코드가 부풀려집니다 😐

    입력




    const iterable = (() => [1, 2])()
    for (const i of iterable) {
        console.log(i)
    }
    


    TypeScript 출력




    var __values = /* ... */
    var e_1, _a;
    var iterable = (function () { return [1, 2]; })();
    try {
        for (var iterable_1 = __values(iterable), iterable_1_1 = iterable_1.next(); !iterable_1_1.done; iterable_1_1 = iterable_1.next()) {
            var i = iterable_1_1.value;
            console.log(i);
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (iterable_1_1 && !iterable_1_1.done && (_a = iterable_1.return)) _a.call(iterable_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
    

    iterable가 생성기인 경우에는 special handling이 있습니다. 이 예제에서는 필요하지 않지만 컴파일러는 확신할 수 없습니다.

    바벨 출력




    function _createForOfIteratorHelper/* ... */
    function _unsupportedIterableToArray/* ... */
    function _arrayLikeToArray/* ... */
    
    var iterable = function () {
      return [1, 2];
    }();
    
    var _iterator = _createForOfIteratorHelper(iterable),
        _step;
    
    try {
      for (_iterator.s(); !(_step = _iterator.n()).done;) {
        var i = _step.value;
        console.log(i);
      }
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }
    


    TS와 마찬가지로 Babel은 실제로 이 예제에서 필요하지 않은 예외 경우를 처리합니다.

    할 일


  • 배열 이외의 것을 반복하지 마십시오.
  • 그렇지 않으면 간단한 함수를 작성하십시오.

  • function forEach(iterable, effect) {
        const itr = iterable[Symbol.iterator]()
        for ( ; ; ) {
            const n = itr.next()
            if (n.done) {
                return n.value
            }
            effect(n.value)
        }
    }
    


    다른 블로터가 있습니까?



    솔직히 ES6+ 기능은 추가 코드를 생성합니다. 그러나 내가 아는 한 생성된 코드는 위의 예만큼 크지 않습니다.

    무엇을 할까요?



    컴파일러가 생성하는 모든 것을 읽고 그것에 대해 무언가를 할 수 있는지 생각하십시오 🙂

    my projectdist를 처음 봤을 때 충격을 받았습니다. 거의 모든 파일에 __read 또는 __whatever 가 있었고 모든 깔끔한 for-of 가 크고 보기 흉한 구조로 바뀌었습니다. 그러나 여기 및 에서 설명한 기술을 적용하여 번들 크기를 약 15% 줄였습니다. 당신도 할 수 있습니다! 😉


    읽어주셔서 감사합니다. 다른 번들 블로터의 이름을 지정할 수 있습니까?

    좋은 웹페이지 즐겨찾기