babelを使用する場合、jsが必要ですか?


98

ES6を試してみたり、gulpを使用してビルドしたり、Babelを使用して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などのビルドツールを使用する必要があります。
ジョーダン

1
ああ、ググリングにbrowserifyを追加すると、答えがわかりました。ありがとうございます。
ジェイソン2015

10
FWIW、エラーメッセージはrequire.jsが必要であることを示していないことに注意してください。BabelはデフォルトでモジュールをCommonJSに変換します。これはNodeが使用し、require関数を定義します(ここでもrequire.jsとは関係ありません)。ただし、モジュールを他の何か( AMDやUMDなど)に変換するようにBabelに指示できます。これにより、require.jsで動作します。どちらの方法でも、ブラウザーはデフォルトで(まだ)モジュールを提供しないため、ブラウザーにモジュールをロードするシステムが必要です。
Felix Kling、2015

ここを参照してください:stackoverflow.com/questions/28125554/...
トッド・

回答:


136

babelを使用する場合、jsが必要ですか?

いくつかのモジュールローダーが必要になる場合がありますが、RequireJSは必要ありません。いくつかのオプションがあります。以下はあなたが始めるのに役立ちます。


rollup.jsロールアップ・プラグインバベル

Rollupは次世代のJavaScriptモジュールバンドルです。ES2015モジュールをネイティブに理解し、モジュールローダーの操作を必要としないバンドルを生成します。未使用のエクスポートは出力から削除されます。これはツリーシェーキングと呼ばれます。

現在、私は個人的には、rollupjsを使用することをお勧めします。これは、最も明確な出力を生成し、セットアップが容易であるためですが、答えには別の側面があります。他のすべてのアプローチは次のことを行います。

  1. ES6コードをbabelでコンパイルし、選択したモジュール形式を使用します
  2. コンパイルされたモジュールをモジュールローダーと連結するか、依存関係をトラバースするバンドラーを使用します。

rollupjsでは、物事は実際にはこのように機能しません。ここでは、ロールアップがバベルではなく、最初のステップです。デフォルトではES6モジュールのみを認識します。依存関係をたどって連結するエントリモジュールを指定する必要があります。ES6はモジュール内で複数の名前付きエクスポートを許可するため、rollupjsは未使用のエクスポートを取り除くのに十分なほどスマートで、バンドルサイズを縮小します。残念ながら、rollupjs-sパーサーは> ES6構文を理解できないため、ES7モジュールはロールアップが解析する前にコンパイルする必要がありますが、コンパイルはES6のインポートに影響を与えるべきではありません。これはrollup-plugin-babelbabel-preset-es2015-rollupプリセットを備えたプラグインを使用して行われます(このプリセットは、モジュールトランスフォーマーと外部ヘルパープラグインを除いて、es2015と同じです)。したがって、ロールアップは、正しく設定されている場合、モジュールに対して次のことを行います。

  1. ファイルシステムからES6-7モジュールを読み取ります
  2. babelプラグインはそれをメモリ内のES6にコンパイルします
  3. ロールアップは、インポートとエクスポートのために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-amdBabel 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を参照してください。

最後に、いくつかの種類のモジュールローダーが必要ですが、requirejsは必ずしも必要ではありません。almondjsがあります。これは、うまく機能する小さなrequireシムです。自分で実装することもできます。

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);
    }
}

最後に、ローダーシムとコンパイルされたモジュールを連結して、uglifyを実行するだけです。


Babelのボイラープレートコードはすべてのモジュールで複製されます

デフォルトでは、上記のメソッドのほとんどは、babelを使用して各モジュールを個別にコンパイルしてから、それらを連結します。それもbabelifyが行うことです。しかし、コンパイルされたコードを見ると、babelが各ファイルの先頭に多くのボイラープレートを挿入していることがわかります。それらのほとんどは、すべてのファイルにわたって複製されています。

これを防ぐには、babel-plugin-transform-runtimeプラグインを使用できます。


1
これは非常に流血です。ありがとうございました。再:ファイルごとの重複するBabelボイラープレート-gzipがそれをすべて否定するだろうと仮定することは正しいでしょうか?
iono

1
私はそれを自分で測定したことはありませんが、配布前にバンドルを縮小すると想定します。縮小すると、ローカルの異なる名前が見つかる可能性があるため、完全に同じではありません。Gzipは共通の部分を見つける必要がありますが(結果として適切な圧縮率が得られます)、ブラウザーは引き続きそれらを個別に解析する必要があります。結局、それは目立ったオーバーヘッドにはならないはずですが、私のような、重複したコードを好まない人がいます。
タマスHegedus

十分に公平な対応をしてくれてありがとう。バージョン管理で出力コードをバックアップまたは追跡する必要がある場合(圧縮されていないファイルサイズが増加する場合)、または何らかの理由で出力を縮小化したい場合にも、それはおそらく非常に理にかなっています。
iono

gulp-rollupもこのリストに追加するとよいでしょう
GGG

@GGG gulpの例を追加しました。残念ながら、現時点ではWindowsで機能する例はありません。コードの上部にある説明を参照してください。
タマスHegedus

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

これで、ルートディレクトリにbundle.jsというファイルが作成され、index.htmlが使用するファイルになります。これは、webpackの最小限のバンドル機能です。あなたはここでもっと学ぶことができます


4

requireはブラウザに存在しないため、このエラーが予想されます。require.jsやBrowserifyなどを使用する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.