Java에서도 ES2015를 사용하고 싶다! → (´・ω・`)

12378 단어 npm자바babelNode.js

MOTIVATION



Babel 은 최신의 ECMAScript 구문 (클래스나 람다나 const , let 등)을 낡은 사양의 JS 환경에서도 실행할 수 있도록(듯이) 변환하는 트랜스 컴파일러. 예를 들어 React는 ECMA2015 + JSX 소스를 Babel의 일반적인 브라우저에서도 해석할 수 있는 JS로 변환하고 있습니다.

React 를 사용하는 일이 있어, 익숙한 Finagle 인가 Akka 로 API 서버를 준비하려고 생각해, Node/React 와 JavaVM 는 잘 공존시키고 싶었던 것이 원래 시작. Babel에서 브라우저 실행 가능한 JS를 생성할 수 있다면 Java Scripting API의 Nashorn에서 ES2015를 사용할 수 있거나 Node.js 라이브러리를 사용할 수 있는 것은?

CONCLUSION



결론부터 먼저.

ES2015로 작성된 JS를 Babel로 트랜스 컴파일하고 Nashorn에서 실행할 수 있습니다. 그러나:



힘든. 이유는 다음과 같습니다.
  • babel-standalone 준비 eval() 에 30 초 걸린다. 우는 CPU 팬. 아무튼 서버사이드등은 준비가 끝난 ScriptEngine 를 캐쉬 해 두면 좋을지도 모른다.
  • 준비 시간을 타협할 수 있으면 트랜스 컴파일은 가능. 그러나 Nashorn에는 require()가 없으므로 외부 라이브러리를 사용할 수 없습니다. webpack도 함께 사용할 필요가 있을 것 같다. 혹은 Java 로 동등 기능을 구현해 bindings 로 건네주면 회피 가능할지도 모른다.
  • 원래 환경 설정에 npm 를 전제로 하기 때문에 Nashorn 를 사용하지 않고도 babel 를 직접 기동하는 수단이 있다 (그리고 그쪽이 빠르다).
  • babel-standalone 은 presets 에 env 를 사용할 수 없는 등 제약이 엄격하다.

  • 따라서 Nashorn을 사용하는 것보다 실행 환경의 node npm

    PLAN



    이런 계획으로 실행했다는 절차.

    npm에서 es2015의 presets를 설치하고 있습니다 (정말로 필요한지 알 수 없음).
    $ npm init
    $ npm install babel-cli babel-preset-es2015 --save
    

    1. babel.js 준비



    babel-standaloneInstallation 에서처럼 출시 페이지 또는 npm 에서 Runtime.exec() 를 얻습니다.
    final ScriptEngineManager manager = new ScriptEngineManager();
    
    final ScriptEngine babel = manager.getEngineByName("JavaScript");
    final String babelJS = "babel.js";
    babel.put(ScriptEngine.FILENAME, babelJS);
    try(Reader in = new FileReader(babelJS)){
      babel.eval(in);
    }
    

    babel.js 에서 30초 정도 걸립니다. 또한 babel.eval(in)를 사용하면 예외가 발생하므로 babel.min.js를 사용합니다.
    javax.script.ScriptException: SyntaxError: empty range in char class in babel.min.js at line number 4
            at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(Unknown Source)
    ...
    Caused by: babel.min.js:4 SyntaxError: empty range in char class
            at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.error(Unknown Source)
    ...
    Caused by: jdk.nashorn.internal.runtime.ParserException: empty range in char class
            at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.regexp.RegExp.throwParserException(Unknown Source)
    ...
    

    2. 트랜스 컴파일 실행


    final String es2015JS = "es2015.js";
    final String es2015 = new String(Files.readAllBytes(Paths.get(es2015JS)), StandardCharsets.UTF_8);
    babel.put(ScriptEngine.FILENAME, "<transcompile>");
    babel.put("src", es2015);
    babel.put("a", new Object[3]);
    final Object[] result = (Object[])babel.eval(
      "var r = Babel.transform(src, {presets:['es2015']});\n" +
      "a[0] = r.code;\n" +
      "a[1] = r.map;\n" +
      "a[2] = r.ast;\n" +
      "a"
    );
    System.out.println(result[0]);
    
    babel.js 는 왜 undefined 이었습니다. 함수 내에서 arguments를 사용하고 있습니까?

    먼저 ES2015 소스를 한 번 읽고 Babel.transformFileSync 결과를 반환 버퍼에 저장합니다. es2015.js 안에서는 다음과 같다:
    // run `npm install kuromoji` before
    import kuromoji from "kuromoji"
    
    kuromoji.builder({ dicPath: "./node_modules/kuromoji/dict" }).build((err, tokenizer) => {
      var path = tokenizer.tokenize("すもももももももものうち")
      console.log(path)
    })
    

    Nashorn에서의 트랜스컴파일에 의해 다음과 같은 소스가 생성되었습니다.
    "use strict";
    
    var _kuromoji = require("kuromoji");
    
    var _kuromoji2 = _interopRequireDefault(_kuromoji);
    
    function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
    
    _kuromoji2.default.builder({ dicPath: "./node_modules/kuromoji/dict" }).build(function (err, tokenizer) {
      var path = tokenizer.tokenize("すもももももももものうち");
      console.log(path);
    }); // run `npm install kuromoji` before
    

    Babel로 트랜스 컴파일한 결과도 똑같다.
    $ node_modules/.bin/babel --presets=es2015 es2015.js
    

    3. 트랜스 컴파일된 코드 실행



    스크립트 엔진을 Babel과는 별도로 트랜스 컴파일된 코드를 실행합니다.
    final ScriptEngine engine = manager.getEngineByName("JavaScript");
    engine.put(ScriptEngine.FILENAME, es2015JS);
    engine.eval(result[0].toString());
    

    그러나 transform를 사용하기 때문에 실행할 수 없습니다.
    javax.script.ScriptException: ReferenceError: "require" is not defined in es2015.js at line number 3
            at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(Unknown Source)
    ...
    

    오시마

    좋은 웹페이지 즐겨찾기