Study/JavaScript

Transpiler

AC 2021. 12. 4. 17:24

 

소개

Transpilers 또는 소스 대 소스 컴파일러는 한 프로그래밍 언어로 작성된 소스 코드를 읽고 다른 언어로 동등한 코드를 생성하는 도구입니다. JavaScript로 변환하는 언어는 종종 compile-to-JS 언어라고 하며 JavaScript  대상 으로 한다고 합니다 .

아, 그리고 사람들이 "컴파일[r]"과 "트랜스파일[r]"을 같은 의미로 사용하는 경향이 있지만 이 기사에서는 후자를 선호합니다.

CoffeeScript  TypeScript 에 대해 들어보셨을 것입니다 . CoffeeScript는 아직 JavaScript에 고유하지 않은 여러 기능에 대한 구문 설탕을 제공 하는 동시에 JavaScript의 "나쁜 부분" 중 일부  억제 합니다. TypeScript는 근본적으로 다른 언어에 고전적인 객체 지향 의미  추가하여 보다 과감 합니다 .

JavaScript로 작성할 수 있는 모든 것은 CoffeeScript 또는 TypeScript로 작성할 수 있습니다.

 

"use strict";

// Good 'ol JS
function printSecret ( secret ) {
    console.log(`${secret}. But don't tell anyone.`);
}

printSecret("I don't like CoffeeScript");
"use strict"

# CoffeeScript
printSecret (secret) =>
    console.log '#{secret}. But don't tell anyone.'

printSecret "I don't like JavaScript."
"use strict";

// TypeScript -- JavaScript, with types and stuff
function printSecret ( secret : string ) {
    console.log("${secret}. But don't tell anyone.");
}

printSecret("I don't like CoffeeScript.");

문제는 JavaScript 환경은 ... 자, JavaScript만 이해한다는 것입니다. 콘솔에서 마지막 두 가지 예를 시도하면 오류가 발생합니다. 사실, 이전 브라우저에서 순수한 JavaScript 예제를 시도하면 여전히 오류가 발생합니다. 템플릿 리터럴에는 여전히 안정적인 브라우저 지원이 없습니다.

이것이 바로 트랜스파일러가 들어오는 곳입니다. 그들은 CoffeeScript, TypeScript 및 ES2015를 읽고 어디에서나 작동하도록 보장된 JavaScript를 뱉어냅니다.

 

트랜스파일러를 보호하기 위해

워크플로에 트랜스파일러가 아직 포함되어 있지 않은 경우 귀찮게 하는 이유가 궁금할 것입니다. 처음에 작성할 수 있었던 자바스크립트만 하루가 끝나면 왜 새로운 구문을 배우고 새로운 도구를 선택해야 할까요?

JavaScript를 대상으로 하는 언어의 경우 주로 선호도 또는 배경의 문제입니다. 당신이 하는 방식대로 "생각하는" 언어로 글을 쓰면 생산성이 높아집니다. OOP에 대한 배경 지식이 있는 사람들은 익숙한 영역이기 때문에 TypeScript를 좋아하는 경우가 많습니다. CoffeeScript를 좋아하는 Pythonista. Clojurist는 ClojureScript를 작성합니다. 당신은 아이디어를 얻을.

그러나 일반 JavaScript를 완벽하게 작성하는 나머지 우리는 여전히 트랜스파일러를 사용합니다. 트랜스파일러가 ES2015 및 그 이후의 기능을 사용하는 유일한 신뢰할 수 있는 방법이기 때문입니다.

내일의 자바스크립트, 오늘

이전에 브라우저 호환성 문제를 처리해야 했던 사람이라면 어디에서나 실행되는 JavaScript를 작성하는 것만큼 간단하지 않다는 것을 알고 있습니다. 모든 브라우저가 다른 JavaScript 엔진을 사용하기 때문입니다. Chrome은 V8을 실행 하고 Firefox는 SpiderMonkey를 실행 하고 Interet Explorer는 Chakra를 실행 합니다. 각각은 서로 다른 성능 특성을 갖고 있으며, 각각은 ES2015 기능의 서로 다른 하위 집합을 구현하며, 각각은 서로 다른 속도로 사양을 완전히 준수하고 있습니다.

즉, 템플릿 리터럴 예제는 최신 Chrome, Firefox 또는 Safari를 실행하는 사용자 에게는 잘 작동하지만 이전 버전을 실행하는 사용자 에게는 작동 하지 않습니다 . 또는 Internet Explorer를 사용하는 사람을 위해.

ES6 호환성 표 는 우리가 분명히 진전을 이루고 있지만 ES2015를 직접 작성할 때가 아니라는 것을 보여줍니다. 대신 ES2015에 소스를 작성하고 트랜스파일러가 이를 모든 브라우저 에서 작동하는 바닐라 ES5로 번역하도록 합니다. 지난 천년의 브라우저를 지원해야 하는 경우 ES3로 컴파일할 수도 있습니다.

이렇게 하면 지금 선택한 트랜스파일러가 지원하는 모든 기능을 사용할 수 있으며 , IE8을 사용할 수 밖에 없는 공무원부터 FireFox를 실행하는 해커 유형에 이르기까지 사이트를 방문하는 모든 사람에게 이 기능이 작동한다는 것을 알 수 있습니다. 밤마다.

미래의 JavaScript, 그 길을 따라

Transpilers는 또한 ECMAScript 표준 설계를 담당하는 그룹인 TC39 위원회의 결정을 안내하는 데 중요한 역할을 합니다.

첫째, 트랜스파일러는 표준에 기능을 포함하는 데 직접 기여할 수 있습니다. 잠재적 기능이 1단계(제안)에서 2단계(초안)로 이동하려면:

기능에 대한 두 가지 실험적 구현이 필요하지만 그 중 하나는 Babel과 같은 트랜스파일러에 포함될 수 있습니다.

포함 과정에 대한 Dr. Rauschmayer의 나머지 개요는 그의 2ality 블로그에 있습니다. .

아마도 이 기여보다 더 중요한 것은 Babel 또는 Traceur 와 같은 트랜스파일러의 사용자 및 구현자의 피드백이 TC39가 구문 및 제안을 반복하는 데 도움 이 된다는 것 입니다. 이것은 TC39 회의 중에 자주 나타납니다. TC39 회의 노트 의 모든 줄을 읽 거나, 아시다시피, rgrep -i바벨이 36번 언급된 것을 발견하고 2015년 3월 25일 회의의 결론을 발견할 수 있습니다. 에 이 결합 구문 했다 "바벨의 사용자로부터 더 많은 피드백을 얻으십시오!"

요약하자면, 트랜스파일러:

  1. CoffeeScript, TypeScript 또는 ClojureScript와 같은 JavaScript로 컴파일하는 언어를 작성할 수 있습니다.
  2. 새롭고 잠재적인 JavaScript 기능을 안정적으로 사용합시다. 그리고
  3. ECMAScript 사양 개발에 기여하십시오.

트랜스파일러가 무엇인지 알아야 할 모든 것을 알았으므로 이제 트랜스파일러를 사용하는 방법에 대해 알아보겠습니다.

변환기 사용

많은 ES2015-to-ES5 트랜스파일러가 있지만 저는 Babel에 집중할 것 입니다.

이 섹션에서는 다음을 다룹니다.

  1. ES2015 소스를 트랜스파일된 출력과 비교합니다.
  2. Babel 명령줄 인터페이스(CLI) 설정 그리고
  3. Webpack, JSPM 및 Babelify와 같은 빌드 도구가 프로세스를 간소화하는 방법을 살펴보세요.

나의 근원은 당신의 근원이다

시작하려면 Babel의 라이브 트랜스파일러로 이동하십시오 . 아래 코드를 JavaScript 편집기(왼쪽 상자)에 복사합니다.

"use strict";

class Planet {

  constructor (mass, moons) {
    this.mass  = mass;
    this.moons = moons || 0;
  }

  reportMoons () {
    console.log(`I have ${this.moons} moons.`)
  }

}

// Yeah, Jupiter really does have (at least) 67 moons.
const jupiter = new Planet('Pretty Big', 67);
jupiter.reportMoons();
 
복사

출력을 살펴보십시오(편의를 위해 아래에 재현됨). ES2015 기능  없음을 알 수 있습니다. const변수는 신중하게 범위가 지정된 var선언으로 변환됩니다 . class구식 함수 생성자로 변환됩니다. 템플릿 문자열 desugars를 단순 문자열 연결로 변환합니다.

// Everything below is Babel's output.
'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Planet = function () {
  function Planet(mass, moons) {
    _classCallCheck(this, Planet);

    this.mass = mass;
    this.moons = moons || 0;
  }

  _createClass(Planet, [{
    key: 'reportMoons',
    value: function reportMoons() {
      console.log('I have ' + this.moons + ' moons.');
    }
  }]);

  return Planet;
}();
 
복사

이것들은 언어가 처음부터 가지고 있던 기능입니다. 그것들을 사용하여 ES2015의 기능을 에뮬레이트하는 것이 바로 지금 비표준 기능을 사용 하고 안전하게 부팅 할 수 있게 하는 방법 입니다.

재미있는 작은 메모로, catch절은 JavaScript에서 범위를 만듭니다. 이 동작은 ES3에서 완전히 표준화되었습니다. Tracer는 블록 범위 지정을 에뮬레이트하기 위해 얼마 동안 이것을 이용하여 다음과 같은 것을 생성했습니다.

"use strict";

// ES2015
{
    let name = "Never woulda thunk.";
}

// ES3/5 output
try { throw void 0; } catch(name) {
    name = "Never woulda thunk.";
    console.log(name);
}
 
복사

폴리필은 어때요?

Babel CLI 설정

라이브 REPL은 매끄럽지만 전체 코드베이스를 그런 식으로 작성하는 것은 형편없을 것입니다. 약간의 작업을 저장하고 Babel CLI를 설정해 보겠습니다.

시작하려면:

  1. 어딘가에 디렉토리를 만드십시오.
  2. NPM 프로젝트로 초기화하십시오.
  3. 우리가 사용할 사전 설정 및 플러그인과 함께 Babel 도구를 설치합니다. 그리고
  4. 이러한 사전 설정 및 플러그인을 사용하도록 Babel을 구성합니다.

홈 디렉토리로 이동하여 폴더를 생성합니다.

  • cd && mkdir babel_example && cd $_
 
복사

그곳에서 원하지 않는다면 cd다른 곳에서.

  • npm init
 
복사

ENTER여러 번 치고 

  • npm install --save-dev babel-cli babel-preset-es2015 babel-plugin-transform-async-to-generator
 
복사

그러면 Babel CLI( babel-cli) 가 설치됩니다 . Babel이 지원하는 모든 ES2015 기능을 활성화하는 플러그인 모음( babel-preset-es2015); ES7 제안, 비동기 기능 ( babel-plugin-transform-async-to-generator) 을 사용할 수 있는 플러그인 .

Babel을 실행하려면 간단히 babel <FILENAME>. 하지만 그 전에 어떤 플러그인을 사용할지 알려줘야 합니다. Babel은 .babelrcNPM 프로젝트의 최상위 수준에 있는 이라는 파일에서 이 정보를 찾습니다 .

{
    "presets": ["es2015"],
    "plugins": ["transform-async-to-generator"]
}
 
복사

이제 Planet 클래스가 있는 위의 스니펫을 에 복사 index.js하고 를 실행 babel index.js --out-file index.transpiled.js --source-maps합니다. 이렇게 하면 index.js, in index.transpiled.js및 별도의 소스맵 파일 index.transpiled.js.map. 소스지도는 당신의 transpiled 코드 대응의 선이있는 당신의 원본 소스의 라인은, 그래서 당신은 디버깅 할 수 있습니다 브라우저 알려주는 파일입니다 index.js직접.

변경 사항을 저장할 때마다 파일을 변환하려면 다음을 실행할 수 있습니다.

  • babel index.js --out-file index.transpiled.js --source-maps --watch
 
복사

빌드 도구

Babel CLI와 함께 사용할 수 있는 몇 가지 다른 옵션이 있습니다 . 그러나 아마도 상상할 수 있듯이 사용 중인 다른 도구 외에 구성 방법을 파악하는 것이 다루기 어려울 수 있습니다.

우리에게는 달리기 babel --watch로 충분합니다. 그러나 중요하지 않은 프로젝트에는 여러 빌드 단계가 있습니다. 배포를 위해 출력 트랜스파일, 축소, 구성, 업데이트해야 할 항목 결정, 이미지 최적화.

CLI를 직접 사용하는 경우 각 단계를 수동으로 실행하거나 프로세스를 직접 스크립팅해야 합니다. 두 번째 옵션은 확실히 실행 가능 하지만 다음과 같을 수 있습니다.

  1. 다루기 힘든;
  2. 팀에 어려움; 그리고
  3. 플랫폼 간에 이식할 수 없습니다.

여기에서 빌드 도구가 필요합니다. Grunt  Gulp 는 빌드 프로세스의 오케스트레이션을 간소화하는 인기 있는 시스템입니다. 다른 기사 에서 읽을 수 있는 Webpack , JSPM  Browserify  같은 번 들러 및 모듈 로더  다른 모든 마법과 함께 트랜스파일을 처리합니다.

나는 Browserify를 사용하여 CoffeeScript로 작성된 테스트를 일반 JS로 변환했습니다. 테스트 실행 후 출력을 삭제합니다. 코드가 모두 통과하면 내 코드를 Babel과 번들로 묶습니다. 소스 맵과 함께 모든 것을 올바른 위치에 배치합니다. 명령줄 도구를 직접 사용하면 이 모든 것이 가능하지만 깨지기 쉽습니다.

당신은 그것에 대해 나를 신뢰할 수 있습니다 – 나는 이것을 위해 bash 스크립트를 사용했습니다. 그 Linux의 완고한 사람이 나를 물기 위해 돌아옵니다. 그리고 여러 모듈 형식 을 로드해야 하거나 핫 모듈 교체 를 실험하고 싶다면 빌드 시스템으로 전환하는 것 외에 선택의 여지가 없습니다.

물론 자신의 글루 코드를 굴리는 것을 좋아하지 않는 한 .

결론

Transpilers에서 벗어나는 것은 어렵습니다. JavaScript로 컴파일하는 언어를 작성할 계획이든 단순히 ES015를 안정적으로 사용할 계획이든 상관없이 Transpilers가 필요합니다. 우리는 후자 그룹에 속한 사람들의 피드백이 TC39 위원회가 JavaScript의 미래 방향에 대한 결정을 내리는 데 중요한 지침이 된다는 것을 알았습니다.

우리는 Babel CLI를 사용하여 소스 맵으로 ES2015를 변환하는 방법을 살펴보고 더 복잡한 프로젝트에서 변환을 간소화하는 도구에 대해 배웠습니다.

James Kyle의 Babel 핸드북  Babel  모든 것에 대한 참고 자료입니다. Webpack에 관심이 있다면 문서를 살펴 보기 전에 How-To를 읽어보십시오 .

LIST