babel을 사용할 때 js가 필요합니까?


98

나는 ES6으로 실험하고 있고, 나는 gulp를 사용하여 빌드하고 바벨을 사용하여 ES5로 트랜스 파일합니다. 출력은 노드에서 실행되지 않고 태그가있는 .htm 파일에서 링크됩니다. 내가 추가해야 할 것 같아

<script src='require.js'></script>

또는 그런 것.

가져 오기 / 내보내기를 시도하고 있습니다.

////////////////scripts.js
import {Circle} from 'shapes';

c = new Circle(4);

console.log(c.area());


/////////////////shapes.js
export class Circle {

    circle(radius) {
        this.radius = radius;
    }

    area() {
        return this.radius * this.radius * Math.PI;
    } 

}

오류는

Uncaught ReferenceError: require is not defined

이것을 참조하십시오 (gulp에서 .pipe (babel ()) 이후)

var _shapes = require('shapes');

3
예, require브라우저에 존재하지 않기 때문에 Require.js, Browserify 또는 Webpack과 같은 일부 빌드 도구를 사용해야합니다.
Jordan Running

1
Ahh, 내 인터넷 검색에 browserify를 추가하면 답을 얻었습니다. 감사합니다.
jason

10
FWIW, 오류 메시지는 require.js가 필요하다는 것을 나타내지 않습니다. Babel은 기본적으로 Node가 사용하고 require함수 를 정의하는 CommonJS로 모듈을 변환합니다 (다시 말하지만 require.js와 관련이 없음). 그러나 Babel에 모듈을 AMD 또는 UMD와 같은 다른 것으로 변환하도록 지시 하면 require.js와 함께 작동합니다. 어느 쪽이든 브라우저가 기본적으로 (아직) 모듈을 제공하지 않기 때문에 브라우저에서 모듈을로드 할 시스템이 필요합니다.
펠릭스 클링

답변:


136

babel을 사용할 때 js가 필요합니까?

모듈 로더가 필요할 수 있지만 RequireJS는 필요하지 않습니다. 몇 가지 옵션이 있습니다. 다음은 시작하는 데 도움이됩니다.


rollup.js롤업 - 플러그인 - 바벨

Rollup은 차세대 JavaScript 모듈 번 들러입니다. ES2015 모듈을 기본적으로 이해하고 작동하는 데 모듈 로더가 필요하지 않은 번들을 생성합니다. 사용하지 않은 내보내기는 출력에서 ​​트리밍되며이를 트리 쉐이킹이라고합니다.

이제는 가장 명확한 출력을 생성하고 설정하기 쉽기 때문에 개인적으로 rollupjs를 사용하는 것이 좋지만 대답에 다른 측면을 제공합니다. 다른 모든 접근 방식은 다음을 수행합니다.

  1. 바벨로 ES6 코드를 컴파일하고 원하는 모듈 형식을 사용합니다.
  2. 컴파일 된 모듈을 모듈 로더와 함께 연결하거나 종속성을 탐색하는 번 들러를 사용하십시오.

rollupjs를 사용하면 실제로 이런 식으로 작동하지 않습니다. 여기서 롤업은 바벨이 아닌 첫 번째 단계입니다. 기본적으로 ES6 모듈 만 이해합니다. 종속성이 순회되고 연결되는 항목 모듈을 제공해야합니다. ES6는 모듈에서 여러 개의 명명 된 내보내기를 허용하므로 rollupjs는 사용하지 않는 내보내기를 제거 할 수있을만큼 똑똑하므로 번들 크기가 줄어 듭니다. 불행히도 rollupjs-s 파서는> ES6 구문을 이해하지 못하므로 ES7 모듈은 롤업에서 파싱하기 전에 컴파일해야하지만 컴파일은 ES6 가져 오기에 영향을주지 않아야합니다. 그것은 사용하여 수행됩니다 rollup-plugin-babel와 플러그인을babel-preset-es2015-rollup사전 설정이 (이 사전 설정은 모듈 변환기 및 외부 도우미 플러그인을 제외하고 es2015의 사전 설정과 동일합니다). 따라서 롤업은 올바르게 설정된 경우 모듈에서 다음을 수행합니다.

  1. 파일 시스템에서 ES6-7 모듈을 읽습니다.
  2. babel 플러그인은 메모리에서 ES6로 컴파일합니다.
  3. rollup은 가져 오기 및 내보내기를 위해 ES6 코드를 구문 분석합니다 (롤업으로 컴파일 된 도토리 구문 분석기 사용).
  4. 전체 그래프를 순회하고 단일 번들을 생성합니다 (여전히 외부 종속성이있을 수 있으며 항목의 내보내기를 선택한 형식으로 내보낼 수 있음).

예제 nodejs 빌드 :

// setup by `npm i rollup rollup-plugin-babel babel-preset-es2015 babel-plugin-external-helpers --save-dev`

// build.js:
require("rollup").rollup({
  entry: "./src/main.js",
  plugins: [
    require("rollup-plugin-babel")({
      "presets": [["es2015", { "modules": false }]],
      "plugins": ["external-helpers"]
    })
  ]
}).then(bundle => {
  var result = bundle.generate({
    // output format - 'amd', 'cjs', 'es6', 'iife', 'umd'
    format: 'iife'
  });

  require("fs").writeFileSync("./dist/bundle.js", result.code);
  // sourceMaps are supported too!
}).then(null, err => console.error(err));

grunt-rollup을 사용한 grunt 빌드의 예

// setup by `npm i grunt grunt-rollup rollup-plugin-babel babel-preset-es2015 babel-plugin-external-helpers --save-dev`

// gruntfile.js
module.exports = function(grunt) {
  grunt.loadNpmTasks("grunt-rollup");
  grunt.initConfig({
    "rollup": {
      "options": {
        "format": "iife",
        "plugins": [
          require("rollup-plugin-babel")({
            "presets": [["es2015", { "modules": false }]],
            "plugins": ["external-helpers"]
          })
        ]
      },
      "dist": {
        "files": {
          "./dist/bundle.js": ["./src/main.js"]
        }
      }
    }
  });
}

gulp-rollup을 사용한 gulp 빌드 예제

// setup by `npm i gulp gulp-rollup rollup-plugin-babel babel-preset-es2015 babel-plugin-external-helpers --save-dev`

// gulpfile.js
var gulp       = require('gulp'),
    rollup     = require('gulp-rollup');

gulp.task('bundle', function() {
  gulp.src('./src/**/*.js')
    // transform the files here.
    .pipe(rollup({
      // any option supported by Rollup can be set here.
      "format": "iife",
      "plugins": [
        require("rollup-plugin-babel")({
          "presets": [["es2015", { "modules": false }]],
          "plugins": ["external-helpers"]
        })
      ],
      entry: './src/main.js'
    }))
    .pipe(gulp.dest('./dist'));
});

Babelify + Browserify

Babel에는 babelify 라는 깔끔한 패키지가 있습니다 . 사용법은 간단하고 간단합니다.

$ npm install --save-dev babelify babel-preset-es2015 babel-preset-react
$ npm install -g browserify
$ browserify src/script.js -o bundle.js \
  -t [ babelify --presets [ es2015 react ] ]

또는 node.js에서 사용할 수 있습니다.

$ npm install --save-dev browserify babelify babel-preset-es2015 babel-preset-react

...

var fs = require("fs");
var browserify = require("browserify");
browserify(["./src/script.js"])
  .transform("babelify", {presets: ["es2015", "react"]})
  .bundle()
  .pipe(fs.createWriteStream("bundle.js"));

이것은 코드를 한 번에 트랜스 파일하고 연결합니다. Browserify의.bundle 는 멋진 CommonJS 로더를 포함하고 트랜스 파일 된 모듈을 함수로 구성합니다. 상대적 수입도 가능합니다.

예:

// project structure
.
+-- src/
|   +-- library/
|   |   \-- ModuleA.js
|   +-- config.js
|   \-- script.js
+-- dist/
\-- build.js
...

// build.js
var fs = require("fs");
var browserify = require("browserify");
browserify(["./src/script.js"])
  .transform("babelify", {presets: ["es2015", "react"]})
  .bundle()
  .pipe(fs.createWriteStream("dist/bundle.js"));

// config.js
export default "Some config";

// ModuleA.js
import config from '../config';
export default "Some nice export: " + config;

// script.js
import ModuleA from './library/ModuleA';
console.log(ModuleA);

컴파일하려면 node build.js프로젝트 루트에서 실행 하십시오.


Babel + WebPack

babel을 사용하여 모든 코드를 컴파일하십시오. amd 모듈 변압기 (babel-plugin-transform-es2015-modules-amd Babel 6에서 . 그 후에 컴파일 된 소스를 WebPack과 함께 묶으십시오.

WebPack 2가 출시되었습니다! 네이티브 ES6 모듈을 이해하고 babili -s 내장 데드 코드 제거를 사용하여 트리 쉐이킹수행 (또는 시뮬레이션) 합니다. 현재 (2016 년 9 월) WebPack 2의 첫 번째 릴리스에서 내 의견이 변경 될 수 있지만 여전히 babel과 함께 롤업을 사용하는 것이 좋습니다. 의견에서 의견을 자유롭게 토론하십시오.


커스텀 컴파일 파이프 라인

때로는 컴파일 프로세스를 더 많이 제어하고 싶을 때가 있습니다. 다음과 같이 자체 파이프 라인을 구현할 수 있습니다.

먼저 amd 모듈을 사용하도록 babel을 구성해야합니다. 기본적으로 babel은 CommonJS 모듈로 트랜스 파일합니다. 이는 브라우저에서 처리하기가 약간 복잡하지만 browserify는이를 훌륭하게 처리합니다.

  • Babel 5 : 사용 { modules: 'amdStrict', ... }옵션
  • Babel 6 : es2015-modules-amd플러그인 사용

켜는 것을 잊지 마십시오 moduleIds: true옵션 .

생성 된 모듈 이름에 대해 트랜스 파일 된 코드를 확인하십시오. 정의 된 모듈과 필수 모듈이 일치하지 않는 경우가 종종 있습니다. sourceRoot 및 moduleRoot를 참조하십시오 .

마지막으로, 어떤 종류의 모듈 로더가 있어야하지만 꼭 필요한 것은 아닙니다. 이 almondjs는 작은 잘 작동 심을 필요합니다. 직접 구현할 수도 있습니다.

var __modules = new Map();

function define(name, deps, factory) {
    __modules.set(name, { n: name, d: deps, e: null, f: factory });
}

function require(name) {
    const module = __modules.get(name);
    if (!module.e) {
        module.e = {};
        module.f.apply(null, module.d.map(req));
    }
    return module.e;

    function req(name) {
        return name === 'exports' ? module.e : require(name);
    }
}

마지막으로 로더 shim과 컴파일 된 모듈을 함께 연결하고 uglify를 실행할 수 있습니다.


Babel의 상용구 코드는 모든 모듈에서 중복됩니다.

기본적으로 대부분의 위 메서드는 babel을 사용하여 각 모듈을 개별적으로 컴파일 한 다음 함께 연결합니다. 바 벨리 파이도 그렇게합니다. 그러나 컴파일 된 코드를 살펴보면 babel이 각 파일의 시작 부분에 많은 상용구를 삽입하는 것을 볼 수 있으며 대부분은 모든 파일에 복제됩니다.

이를 방지하기 위해 babel-plugin-transform-runtime플러그인을 사용할 수 있습니다 .


1
이것은 너무나도 철저합니다. 감사합니다. Re : 파일 당 중복 된 Babel 상용구-gzip이이를 부정한다고 가정하는 것이 맞습니까?
iono

1
직접 측정 한 적은 없지만 배포 전에 번들을 축소 할 것이라고 가정하고 축소는 로컬에 대해 다른 이름을 찾을 수 있으므로 정확히 동일하지는 않습니다. Gzip은 공통 부분을 찾아야하지만 (좋은 압축 비율을 제공함) 브라우저는 여전히 개별적으로 구문 분석해야합니다. 궁극적으로 눈에 띄는 오버 헤드는 안되지만, 중복 된 코드를 싫어하는 사람들이있을 것입니다.
Tamas Hegedus 2016-06-20

응답 해 주셔서 감사합니다. 버전 제어에서 출력 코드를 백업하거나 추적해야하는 경우 (압축되지 않은 파일 크기가 증가하는 경우) 또는 어떤 이유로 든 출력이 축소되지 않도록하려는 경우에도이 방법이 유용 할 것입니다.
iono

꿀꺽 - 롤업 도이 목록에 좋은 보탬이 될 수있다
GGG

@GGG gulp 예제를 추가했습니다. 불행히도 현재 창에서 작동하는 예제는 없습니다. 코드 상단의 설명을 참조하십시오.
Tamas Hegedus 2016 년

8

베어 본 웹팩 2

1) 이것이 루트 디렉토리 인 경우 :

index.html

<html>
  ...
  <script src="./bundle.js"></script>
  ...
</html>

scripts.js

import { Circle } from './shapes.js';
  ...

shapes.js

export class Circle {
  ...
}

2) 노드 설치 노드

3) 터미널에서 다음 명령을 실행하십시오.

$ npm install -g webpack

5) 루트 디렉토리에서 다음을 실행하십시오.

$ webpack scripts.js bundle.js

이제 index.html이 사용할 파일이 될 루트 디렉토리에 bundle.js라는 파일이 있어야합니다. 이것은 웹팩의 최소한의 번들링 기능입니다. 여기에서 자세히 알아볼 수 있습니다.


4

require브라우저에 존재하지 않으므로이 오류가 예상됩니다. require.js 또는 Browserify와 같은 것을 사용해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.