Как использовать модули ECMAScript6 на веб-страницах
Мне очень нравится использование функций ECMAScript 6 теперь через Babeljs - в частности, мне бы хотелось, чтобы мой код JavaScript был более модульным, используя функцию новых модулей.
Вот что я написал до сих пор:
// ECMAScript 6 code - lib.js
export const sqrt = Math.sqrt;
export function square (x) {
return x * x;
}
export function diag (x, y) {
return sqrt(square(x) + square(y));
}
// ECMAScript 6 code - main.js
import { square, diag } from 'lib';
console.log(square(11));
console.log(diag(4, 3));
Я понимаю, что я могу передать этот код с ES6 на ES5 через babel в командной строке:
babel lib.js > lib6to5.js
babel main.js > main6to5.js
Но что мне нужно сделать, чтобы использовать этот код в моем HTML?
Например, как выглядел бы этот файл index.html:
<!-- index.html -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ECMAScript 6</title>
<!-- What goes here?
How do I include main6to5.js and lib6to5.js to make this work in the browser? -->
<script src="?????"></script>
</head>
<body>
</body>
</html>
Спасибо
Ответы
Ответ 1
Без использования модулей:
Если вы не используете модули (импорт/экспорт), вы можете просто перевести свой код в ES5 и включить эти файлы ES5 в свой html.
Пример:
// ES6 - index.js
// arrow function
var result = [1, 2, 3].map(n => n * 2);
console.log(result);
// enhanced object literal
var project = "helloWorld";
var obj = {
// Shorthand for ‘project: project’
project,
// Methods
printProject() {
console.log(this.project);
},
[ "prop_" + (() => 42)() ]: 42
};
console.log(obj.printProject());
console.log(obj);
Переместить на es5: babel index.js > es5.js
В index.html
включить <script src="es5.js"></script>
Распечатайте в консоли следующее:
[2,4,6]
helloWorld
{"project":"helloWorld","prop_42":42}
Использование модулей: Теперь, если вы используете модули (в вашем случае с lib.js
и main.js
), после преобразования вашего кода в ES5 вам также придется связывать их (из AMD/CommonJS/Модули для кода, который может понять ваш браузер). Вы можете сделать это с помощью различных систем построения, таких как gulp, webpack, browserify и т.д. Я собираюсь использовать пример браузера в качестве примера.
Скажите, что моя структура папок выглядит так:
es6
|- src
|- lib.js
|- main.js
|- compiled
|- index.html
Я запускаю babel, чтобы передать мои файлы /src
в папку /compiled
: babel src --out-dir compiled
.
Теперь у меня есть код ES5 в скомпилированной папке. Я устанавливаю браузер в строке cmd, а затем свяжу my main.js(точку входа) в моей скомпилированной папке
~/es6 » npm install --global browserify
~/es6 » browserify ./compiled/main.js -o ./bundle.js
Теперь у меня есть bundle.js
, который выглядит так:
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
exports.square = square;
exports.diag = diag;
var sqrt = exports.sqrt = Math.sqrt;
function square(x) {
return x * x;
}
function diag(x, y) {
return sqrt(square(x) + square(y));
}
Object.defineProperty(exports, "__esModule", {
value: true
});
},{}],2:[function(require,module,exports){
"use strict";
var _lib = require("./lib");
var square = _lib.square;
var diag = _lib.diag;
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
},{"./lib":1}]},{},[2]);
Затем в вашем index.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ECMAScript 6</title>
<script src="./bundle.js"></script>
</head>
<body>
</body>
</html>
Затем просто откройте свой index.html
, и ваша консоль должна предоставить вам следующее:
121 bundle.js:27
5 bundle.js:28
Ответ 2
[ Примечание: я понимаю, что мой ответ плох, поскольку он не полностью отражает
задающие вопрос о намерении использовать модули ES6 через babeljs в интерфейсе рабочего процесса.
Ответьте ей за тех, кто хочет использовать модули ES6 на веб-странице]
Попробуйте использовать jspm.io для загрузки модулей ES6 в браузере без предварительной пересылки с помощью babel.
Плункер можно найти здесь
jspm работает сверху system.js, который пытается быть загрузчиком для любого формата модуля (ES6, AMD, CommonJS).
Чтобы сделать эту работу в моем браузере, я основывался на этой демонстрации jspm ES6. Просто скопировал System.js и es6-module-loader.js в папку js/lib и скопировал ваши файлы es6 js в папку js. Тогда html выглядит следующим образом:
<html>
<body>
Test .. just open up the Chrome Devtools console to see the ES6 modules output using jspm
<script src="js/lib/system.js"></script>
<script>System.import("main");</script> </body>
</html>
Здесь можно найти плункер здесь
Ответ 3
Я начал с того, что попытался сделать то же самое, но в итоге обнаружил, что Gulp действительно помог многим.
Следует иметь в виду: babel source.js > destination.js
не будет polyfill нового синтаксиса ES6. Ваш код прямо сейчас не использует никаких операторов let
, деструктурированного назначения, функций генератора или чего-либо подобного; но если вы добавите это на более позднем этапе, вам понадобится более сложное преобразование.
Вот ответ, в котором объясняется, как настроить файл Gulp: использование модуля экспорта Javascript 6to5 (теперь Babel) (Отказ от ответственности: это один из моих ответов: р)
Ниже приведены шаги, характерные для вашего случая:
- Создайте файл
gulpfile.js
в вашем каталоге со следующим:
var gulp = require('gulp');
var browserify = require('browserify');
var babelify= require('babelify');
var util = require('gulp-util');
var buffer = require('vinyl-buffer');
var source = require('vinyl-source-stream');
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
gulp.task('build', function() {
browserify(['./lib.js', './main.js'], { debug: true })
.add(require.resolve('babel/polyfill'))
.transform(babelify)
.bundle()
.on('error', util.log.bind(util, 'Browserify Error'))
.pipe(source('app.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(uglify({ mangle: false }))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./'));
});
gulp.task('default', ['build']);
- Запустите
npm install gulp browserify babel babelify gulp-util vinyl-buffer vinyl-source-stream gulp-uglify gulp-sourcemaps
, чтобы установить необходимые зависимости.
- Запустите
gulp
, чтобы собрать все вместе.
- Используйте связанный script в вашем HTML с этим элементом:
<script src="app.js"></script>
В дополнение к добавленным полифайлам приятно, что код минимизирован, и вы получаете исходные карты, что означает даже в ваших инструментах разработчика, вы можете отлаживать сам код ES6.
Примечание.. В то время как оператор импорта, который вы используете, является правильным в соответствии со спецификацией проекта ES6, Babel ему это не понравится. Вам нужно будет добавить ./
, чтобы он выглядел примерно так:
import { square, diag } from './lib';
Я подозреваю, что это происходит потому, что преобразование происходит в Node.js, и это отличает файл от модуля node. В качестве побочного пункта вы можете написать ES6 для node require с операторами импорта:)
Ответ 4
Будет ли один из переключателей --modules
скомпилирован в JS, который может быть непосредственно включен в веб-страницу так же, как флаг --script
будет компилироваться в браузер JS (--script
нельзя использовать с модулями)? См. https://github.com/google/traceur-compiler/wiki/Options-for-Compiling