- Сообщений: 547
- Спасибо получено: 666
es6 в mv (с помощью grunt и babel)
8 года 6 мес. назад - 8 года 6 мес. назад #100490
от Amphilohiy
Я верю, что иногда компьютер сбоит, и он выдает неожиданные результаты, но остальные 100% случаев это чья-то криворукость.
Amphilohiy создал тему: es6 в mv (с помощью grunt и babel)
Прошлый раз я вас дружил с глотком(gulp) кофейного сценария(coffeescript)
тут
. А сегодня у нас хрюкающий(grunt) галдеж(babel). Суть примерно та-же: грунт нам обеспечит сборку клиентской части, а бабель конвертнет es6 в es5. В надежде что вы впитали мудрость той статьи я сокращу эту.
Grunt
О том как ставить ноду смотрите по ссылке выше. Теперь же глобально ставим клиент грунта
И в папочке где устроите проект создайте тот же package.json
в ней же запустите команду
Теперь же сама настройка - делаем файл Gruntfile.coffee и записываем следующее
Эмм, да, грунт поддерживает кофе из коробки, так что я не упустил шанс. Сам по себе грунт своеобразен но суть как у gulp а. Дело в том, что каждый отдельный пакет требует набора настроек сразу. Например
тут мы настраиваем бабель. Но simpleBabel и decoratorBabel сами по себе уже являются тасками, и их можно запустить с помощью команды
или
Сейчас будет ошибка, ибо бабель не настроен, но можно уже запускать кофеек. Естественно я вам сразу же подвез вотчеры, причем по умолчанию.
Как бы то ни было за полными манулами вам сюда .
Babel
Сам бабель тоже требует настройки. Для этого создадим фаил .babelrc
Тут у нас пресет, конвертирующий es6 в es5, и плагины на декоратор, о котором позже. По сути эти настройки вы могли записать и в грунте. Но этого достаточно. Давайте попробуем сконвертировать скриптец (предупреждаю сразу - выхлоп будет большой). Сам скрипт(src/test_babel.js):
И выхлоп:
Запущеный скрипт с ноды вывел:
Очень много функций, заменяющих сахар es6, но и с кофе такой есть. Тем не менее можно уже писать и не боятся, пока не посмотрите в выхлоп.
Спец гость - декоратор
Но перегонка между стандартами (или же просто поддержка нескольких выбранных версий разных браузеров, серьезно, если будет время поглядите что могет) не единственная фишка бабеля. Он так же позволяет подкинуть пару плагинов, которые внесут свою лепту в компиляцию, как например прикрутить декоратор. Синтаксически он будет выглядеть как в python:
Маленький @logger теперь является декоратором.Небольшая модификация метода bar которая выводит на экран все входящие аргументы, и все выходящие. Вывод будет таким:
Выхлоп:
Как бы то ни было, можно ознакомиться с плагинами на сайте бабеля (доки к ним ни о чем, сложно понять что каждый из них делает), и писать не только на es6, но и подвезти разных других плюшечек.
Внезапная находка
Есть способ вытащить все хелпер методы в отдельный фаил. Надо прогнать установку следующих пакетов
Затем запустить команду
Чутка подрихтуем babelrc
И соберем файлик заново. Декораторам это не помогло, зато шоукейс es6 вышел поприрятнее
чтобы проверить это на ноде надо добавить сверху строчку с загрузкой хелперов
И вуаля, работает. Правда 550 строчек внешних хелперов (в файле helpers.js)... Можете засунуть себе в ядро (никакого подтекста).
Grunt
О том как ставить ноду смотрите по ссылке выше. Теперь же глобально ставим клиент грунта
Code:
npm install -g grunt-cli
Code:
{
"dependencies": {
"babel-core": "^6.26.0",
"babel-plugin-syntax-decorators": "^6.13.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-preset-es2015": "^6.24.1",
"grunt": "^1.0.1",
"grunt-babel": "^7.0.0",
"grunt-contrib-coffee": "^2.0.0",
"grunt-contrib-watch": "^1.0.0"
}
}
Code:
npm install
ВНИМАНИЕ: Спойлер!
Code:
module.exports = (grunt)->
grunt.initConfig
pkg: grunt.file.readJSON('package.json'),
babel:
simpleBabel:
options:
babelrc: true
files:
'dest/test_babel.js': 'src/test_babel.js'
decoratorBabel:
options:
babelrc: true
files:
'dest/test_decorator.js': 'src/test_decorator.js'
coffee:
compileBare:
options:
bare: true
files:
'dest/test_coffee.js': 'src/test_coffee.coffee'
watch:
coffee:
files: ['src/*.coffee']
tasks: ['coffee']
options:
spawn: false
babel:
files: ['src/*.js']
tasks: ['babel']
options:
spawn: false
grunt.loadNpmTasks('grunt-babel')
grunt.loadNpmTasks('grunt-contrib-coffee')
grunt.loadNpmTasks('grunt-contrib-watch')
grunt.registerTask('default', ['watch'])
Эмм, да, грунт поддерживает кофе из коробки, так что я не упустил шанс. Сам по себе грунт своеобразен но суть как у gulp а. Дело в том, что каждый отдельный пакет требует набора настроек сразу. Например
ВНИМАНИЕ: Спойлер!
Code:
babel:
simpleBabel:
options:
babelrc: true
files:
'dest/test_babel.js': 'src/test_babel.js'
decoratorBabel:
options:
babelrc: true
files:
'dest/test_decorator.js': 'src/test_decorator.js'
тут мы настраиваем бабель. Но simpleBabel и decoratorBabel сами по себе уже являются тасками, и их можно запустить с помощью команды
Code:
grunt babel
Code:
grunt babel:simpleBabel
Как бы то ни было за полными манулами вам сюда .
Babel
Сам бабель тоже требует настройки. Для этого создадим фаил .babelrc
Code:
{
"presets": ["es2015"],
"plugins": ["syntax-decorators", "transform-decorators-legacy"]
}
ВНИМАНИЕ: Спойлер!
Code:
// Стрелочные функции
function log(msg) {
const print = (...args) => console.log(args[0]);
print(`LOG: ${msg}`);
}
log('hello'); // LOG: hello
// Классы
class Task {
constructor() {
console.log("Создан экземпляр task!");
}
showId() {
console.log(23);
}
static loadAll() {
console.log("Загружаем все tasks...");
}
}
console.log(typeof Task); // function
let task = new Task(); // "Создан экземпляр task!"
task.showId(); // 23
Task.loadAll(); // "Загружаем все tasks..."
class Car {
constructor() {
console.log("Создаём новый автомобиль");
}
}
class Porsche extends Car {
constructor() {
super();
console.log("Создаём Porsche");
}
}
let c = new Porsche();
// Создаём новый автомобиль
// Создаём Porsche
И выхлоп:
ВНИМАНИЕ: Спойлер!
Code:
"use strict";
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// Стрелочные функции
function log(msg) {
var print = function print() {
return console.log(arguments.length <= 0 ? undefined : arguments[0]);
};
print("LOG: " + msg);
}
log('hello'); // LOG: hello
// Классы
var Task = function () {
function Task() {
_classCallCheck(this, Task);
console.log("Создан экземпляр task!");
}
_createClass(Task, [{
key: "showId",
value: function showId() {
console.log(23);
}
}], [{
key: "loadAll",
value: function loadAll() {
console.log("Загружаем все tasks...");
}
}]);
return Task;
}();
console.log(typeof Task === "undefined" ? "undefined" : _typeof(Task)); // function
var task = new Task(); // "Создан экземпляр task!"
task.showId(); // 23
Task.loadAll(); // "Загружаем все tasks..."
var Car = function Car() {
_classCallCheck(this, Car);
console.log("Создаём новый автомобиль");
};
var Porsche = function (_Car) {
_inherits(Porsche, _Car);
function Porsche() {
_classCallCheck(this, Porsche);
var _this = _possibleConstructorReturn(this, (Porsche.__proto__ || Object.getPrototypeOf(Porsche)).call(this));
console.log("Создаём Porsche");
return _this;
}
return Porsche;
}(Car);
var c = new Porsche();
// Создаём новый автомобиль
// Создаём Porsche
Запущеный скрипт с ноды вывел:
Code:
LOG: hello
function
Создан экземпляр task!
23
Загружаем все tasks...
Создаём новый автомобиль
Создаём Porsche
Спец гость - декоратор
Но перегонка между стандартами (или же просто поддержка нескольких выбранных версий разных браузеров, серьезно, если будет время поглядите что могет) не единственная фишка бабеля. Он так же позволяет подкинуть пару плагинов, которые внесут свою лепту в компиляцию, как например прикрутить декоратор. Синтаксически он будет выглядеть как в python:
ВНИМАНИЕ: Спойлер!
Code:
let logger = function(target, name, descriptor){
let value = descriptor.value;
descriptor.value = function(...args){
console.log('invoke with args: ', ...args);
let result = value(...args);
console.log('result: ', result);
return result;
}
return descriptor;
}
class Foo {
@logger
bar(x, y, z) {
return x + y + z;
}
}
let foo = new Foo();
let result = foo.bar(1, 2, 3);
console.log('1 + 2 + 3:', result)
Маленький @logger теперь является декоратором.Небольшая модификация метода bar которая выводит на экран все входящие аргументы, и все выходящие. Вывод будет таким:
Code:
invoke with args: 1 2 3
result: 6
1 + 2 + 3: 6
ВНИМАНИЕ: Спойлер!
Code:
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _desc, _value, _class;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
var desc = {};
Object['ke' + 'ys'](descriptor).forEach(function (key) {
desc[key] = descriptor[key];
});
desc.enumerable = !!desc.enumerable;
desc.configurable = !!desc.configurable;
if ('value' in desc || desc.initializer) {
desc.writable = true;
}
desc = decorators.slice().reverse().reduce(function (desc, decorator) {
return decorator(target, property, desc) || desc;
}, desc);
if (context && desc.initializer !== void 0) {
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
desc.initializer = undefined;
}
if (desc.initializer === void 0) {
Object['define' + 'Property'](target, property, desc);
desc = null;
}
return desc;
}
var logger = function logger(target, name, descriptor) {
var value = descriptor.value;
descriptor.value = function () {
var _console;
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
(_console = console).log.apply(_console, ['invoke with args: '].concat(args));
var result = value.apply(undefined, args);
console.log('result: ', result);
return result;
};
return descriptor;
};
var Foo = (_class = function () {
function Foo() {
_classCallCheck(this, Foo);
}
_createClass(Foo, [{
key: 'bar',
value: function bar(x, y, z) {
return x + y + z;
}
}]);
return Foo;
}(), (_applyDecoratedDescriptor(_class.prototype, 'bar', [logger], Object.getOwnPropertyDescriptor(_class.prototype, 'bar'), _class.prototype)), _class);
var foo = new Foo();
var result = foo.bar(1, 2, 3);
console.log('1 + 2 + 3:', result);
Как бы то ни было, можно ознакомиться с плагинами на сайте бабеля (доки к ним ни о чем, сложно понять что каждый из них делает), и писать не только на es6, но и подвезти разных других плюшечек.
Внезапная находка
Есть способ вытащить все хелпер методы в отдельный фаил. Надо прогнать установку следующих пакетов
Code:
npm install babel-cli --save
npm install babel-plugin-external-helpers --save
Code:
./node_modules/.bin/babel-external-helpers > helpers.js
Code:
{
"presets": ["es2015"],
"plugins": ["external-helpers", "syntax-decorators", "transform-decorators-legacy"]
}
ВНИМАНИЕ: Спойлер!
Code:
"use strict";
// Стрелочные функции
function log(msg) {
var print = function print() {
return console.log(arguments.length <= 0 ? undefined : arguments[0]);
};
print("LOG: " + msg);
}
log('hello'); // LOG: hello
// Классы
var Task = function () {
function Task() {
babelHelpers.classCallCheck(this, Task);
console.log("Создан экземпляр task!");
}
babelHelpers.createClass(Task, [{
key: "showId",
value: function showId() {
console.log(23);
}
}], [{
key: "loadAll",
value: function loadAll() {
console.log("Загружаем все tasks...");
}
}]);
return Task;
}();
console.log(typeof Task === "undefined" ? "undefined" : babelHelpers.typeof(Task)); // function
var task = new Task(); // "Создан экземпляр task!"
task.showId(); // 23
Task.loadAll(); // "Загружаем все tasks..."
var Car = function Car() {
babelHelpers.classCallCheck(this, Car);
console.log("Создаём новый автомобиль");
};
var Porsche = function (_Car) {
babelHelpers.inherits(Porsche, _Car);
function Porsche() {
babelHelpers.classCallCheck(this, Porsche);
var _this = babelHelpers.possibleConstructorReturn(this, (Porsche.__proto__ || Object.getPrototypeOf(Porsche)).call(this));
console.log("Создаём Porsche");
return _this;
}
return Porsche;
}(Car);
var c = new Porsche();
// Создаём новый автомобиль
// Создаём Porsche
чтобы проверить это на ноде надо добавить сверху строчку с загрузкой хелперов
Code:
require('../helpers.js')
Я верю, что иногда компьютер сбоит, и он выдает неожиданные результаты, но остальные 100% случаев это чья-то криворукость.
Последнее редактирование: 8 года 6 мес. назад пользователем Amphilohiy.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Время создания страницы: 0.090 секунд
