Babel kullandığımda js'ye ihtiyacım var mı?


100

ES6 ile deneyler yapıyorum ve ES5'e aktarmak için gulp kullanıyorum. Çıktı düğümde çalıştırılmıyor, sadece bir etiketi olan bir .htm dosyasından bağlanıyor. Eklemem gerektiğini düşünüyorum

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

ya da böyle bir şey.

İçe / dışa aktarmaya çalışıyorum.

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

}

Hata

Uncaught ReferenceError: require is not defined

Bunu ifade eder (yudumda .pipe (babel ()) 'dan sonra)

var _shapes = require('shapes');

3
Evet, requiretarayıcıda bulunmadığından, Require.js, Browserify veya Webpack gibi bazı oluşturma araçlarını kullanmanız gerekir.
Jordan Running

1
Ahh, googling'ime browsererify eklemek bana cevabı verdi, teşekkür ederim.
jason

10
FWIW, hata mesajının require.js'ye ihtiyacınız olduğunu göstermediğini unutmayın. Babel, modülleri varsayılan olarak CommonJS'ye dönüştürür; bu, Node'un kullandığı ve bir requireişlevi tanımlayan şeydir (yine, require.js ile hiçbir ilgisi yoktur). Ancak, Babel'e modülleri başka bir şeye , örneğin AMD veya UMD'ye dönüştürmesini söyleyebilirsiniz , bu daha sonra require.js ile çalışacaktır. Her iki durumda da, tarayıcıya modülleri yüklemek için bir sisteme ihtiyacınız vardır, çünkü tarayıcı varsayılan olarak (henüz) bir modül sağlamaz.
Felix Kling

Yanıtlar:


137

Babel kullandığımda js'ye ihtiyacım var mı?

Bir modül yükleyiciye ihtiyacınız olabilir, ancak RequireJS gerekli değildir. Birkaç seçeneğiniz var. Aşağıdakiler başlamanıza yardımcı olacaktır.


rollup-eklenti-babel ile rollup.js

Toplama, yeni nesil bir JavaScript modülü paketleyicisidir. ES2015 modüllerini yerel olarak anlar ve çalışmak için herhangi bir modül yükleyiciye ihtiyaç duymayan bir paket üretir. Kullanılmayan dışa aktarımlar çıktıdan kesilecektir, buna ağaç sallama denir.

Şimdi, en net çıktıyı ürettiği ve kurulumu kolay olduğu için ben şahsen rollupjs kullanmanızı tavsiye ediyorum, ancak cevaba farklı bir yön veriyor. Diğer tüm yaklaşımlar şunları yapar:

  1. ES6 kodunu babel ile derleyin, seçtiğiniz modül formatını kullanın
  2. Bir modül yükleyiciyle birlikte derlenen modülleri birleştirin VEYA bağımlılıkları sizin için geçecek bir paketleyici kullanın.

Rollupjs ile işler gerçekten bu şekilde yürümez. Burada, babel yerine toparlama ilk adımdır. Yalnızca varsayılan olarak ES6 modüllerini anlar. Bağımlılıklarının geçilip birleştirileceği bir giriş modülü vermelisiniz. ES6 bir modülde birden çok adlandırılmış dışa aktarmaya izin verdiği için, toplayıcılar kullanılmayan dışa aktarmaları kaldıracak kadar akıllıdır ve böylece paket boyutunu küçültür. Ne yazık ki, rollupjs-s ayrıştırıcısı> ES6 sözdizimini anlamıyor, bu nedenle, ES7 modüllerinin, toplama onları ayrıştırmadan önce derlenmesi gerekir, ancak derleme, ES6 içe aktarımlarını etkilememelidir. Ön ayarlı rollup-plugin-babeleklenti kullanılarak yapılır babel-preset-es2015-rollup(bu ön ayar, modül transformatörü ve harici yardımcılar eklentisi dışında es2015 ile aynıdır). Dolayısıyla, doğru bir şekilde ayarlanmışsa toplama, modüllerinizle aşağıdakileri yapacaktır:

  1. ES6-7 modülünüzü dosya sisteminden okur
  2. Babel eklentisi bunu bellekte ES6'ya derler
  3. toplama, ithalat ve ihracat için ES6 kodunu ayrıştırır (meşe palamudu ayrıştırıcı kullanarak, toplama halinde derlenir)
  4. tüm grafiği gezer ve tek bir paket oluşturur (ki bu hala harici bağımlılıklara sahip olabilir ve girişin dışa aktarımları seçtiğiniz bir formatta dışa aktarılabilir)

Örnek nodejs derlemesi:

// 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 ile örnek homurtu derleme

// 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"]
        }
      }
    }
  });
}

Yudum toplaması ile örnek yudum yapısı

// 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'in babelify adında temiz bir paketi var . Kullanımı basit ve anlaşılırdır:

$ 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 ] ]

veya node.js'den kullanabilirsiniz:

$ 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"));

Bu, kodunuzu aynı anda aktaracak ve birleştirecektir. Browserify's .bundleküçük bir CommonJS yükleyici içerecek ve aktarılan modüllerinizi işlevlere göre düzenleyecektir. Hatta göreli ithalata bile sahip olabilirsiniz.

Misal:

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

Derlemek için sadece node build.jsproje kök dizininde çalıştırın .


Babel + WebPack

Babel kullanarak tüm kodunuzu derleyin. Amd modül transformatörünü kullanmanızı tavsiye ederim ( babel-plugin-transform-es2015-modules-amdbabel 6'da denir ). Bundan sonra derlenmiş kaynaklarınızı WebPack ile paketleyin.

WebPack 2 çıktı! Yerel ES6 modüllerini anlar ve babili -s yerleşik ölü kod eleme kullanarak ağaç sallamayı gerçekleştirir (veya daha doğrusu simüle eder) . Şimdilik (Eylül 2016), WebPack 2'nin ilk sürümüyle görüşüm değişse de, babel ile toplamayı kullanmayı öneririm. Görüşlerinizi yorumlarda tartışmaktan çekinmeyin.


Özel derleme ardışık düzeni

Bazen derleme işlemi üzerinde daha fazla kontrole sahip olmak istersiniz. Kendi ardışık düzeninizi şu şekilde uygulayabilirsiniz:

Öncelikle, babel'i amd modüllerini kullanacak şekilde yapılandırmanız gerekir. Varsayılan olarak babel, tarayıcıda işlenmesi biraz karmaşık olan CommonJS modüllerine aktarılır, ancak browsererify bunları iyi bir şekilde yönetmeyi başarır.

  • Babel 5: { modules: 'amdStrict', ... }seçeneği kullan
  • Babel 6: es2015-modules-amdeklentiyi kullanın

moduleIds: trueSeçeneği açmayı unutmayın .

Oluşturulan modül adları için aktarılmış kodu kontrol edin, tanımlanmış ve gerekli modüller arasında genellikle uyuşmazlıklar olur. SourceRoot ve moduleRoot'a bakın .

Son olarak, bir tür modül yükleyiciniz olması gerekir, ancak bu zorunlu değildir. Orada almondjs küçücük iyi çalışıyor şimi gerektirir. Hatta kendinizinkini bile uygulayabilirsiniz:

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

Sonunda, yükleyici şimini ve derlenmiş modülleri birbirine bağlayabilir ve bunun üzerinde çirkinleştirebilirsiniz.


Babel'in klişe kodu her modülde kopyalanmıştır

Varsayılan olarak, yukarıdaki yöntemlerin çoğu her modülü babel ile ayrı ayrı derler ve sonra bunları birleştirir. Babelify'ın yaptığı da budur. Ancak derlenen koda bakarsanız, babel'in her dosyanın başına çok sayıda ortak metin eklediğini görürsünüz, bunların çoğu tüm dosyalarda kopyalanır.

Bunu önlemek için babel-plugin-transform-runtimeeklentiyi kullanabilirsiniz .


1
Bu çok kanlı kapsamlı; teşekkür ederim. Ynt: dosya başına yinelenen Babel ortak metni - gzip'in bunu tamamen ortadan kaldıracağını varsaymak doğru olur mu?
iono

1
Bunu kendim hiç ölçmedim, ancak dağıtımdan önce paketin küçültüleceğini ve küçültmenin muhtemelen yerel halk için farklı isimler bulacağını ve bu nedenle tamamen aynı olmayacağını varsayardım. Gzip, ortak parçaları bulmalıdır (iyi bir sıkıştırma oranı sağlar), ancak tarayıcının yine de bunları ayrı ayrı ayrıştırması gerekir. Nihayetinde göze çarpan bir ek yük olmamalı, ancak benim gibi kopyalanmış kodlardan hoşlanmayan insanlar olacak.
Tamas Hegedus

Yeterince adil, cevap için teşekkürler. Çıktı kodunu sürüm kontrolünde yedeklemeniz veya izlemeniz gerektiğinde (sıkıştırılmamış dosya boyutunun çoğaldığı) veya herhangi bir nedenle çıktının küçültülmemiş olmasını istediğiniz durumlarda da muhtemelen çok mantıklı olacaktır.
iono

yudum toplaması da bu listeye iyi bir katkı olabilir
GGG

@GGG Yudum örneği eklendi. Ne yazık ki şu anda örneklerden hiçbiri pencerelerde çalışmıyor, kodların üst kısmındaki açıklamaya bakın.
Tamas Hegedus

8

barebones web paketi 2

1) Bu sizin kök dizininizse:

index.html

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

scripts.js

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

shape.js

export class Circle {
  ...
}

2) düğüm kurulu düğüme sahip olmak

3) terminalinizde aşağıdaki komutu çalıştırın:

$ npm install -g webpack

5) kök dizininizde aşağıdakileri çalıştırın:

$ webpack scripts.js bundle.js

Şimdi kök dizininizde, index.html'nizin tüketeceği dosya olacak bundle.js adlı bir dosyanızın olması gerekir. Bu, web paketinden minimalist bir paket oluşturma özelliğidir. Buradan daha fazlasını öğrenebilirsiniz


4

requiretarayıcıda yok, bu nedenle bu hata bekleniyor. Required.js veya Browserify gibi bir şey kullanmanız gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.