Ответ 1
Нужно ли мне использовать js при использовании babel?
Вам может понадобиться некоторый загрузчик модулей, но это необязательно RequireJS. У вас есть несколько вариантов. Следующее поможет вам начать работу.
rollup.js с rollup-plugin-babel
Накопитель - это блок-модуль JavaScript следующего поколения. Он понимает модули ES2015 изначально и создает пакет, для которого не требуется какой-либо загрузчик модулей. Неиспользованный экспорт будет отделен от результата, он называется дрожанием дерева.
Теперь я лично рекомендую использовать rollupjs, поскольку он дает самый четкий вывод и его легко настроить, однако он дает другой аспект ответа. Все остальные подходы делают следующее:
- Скомпилируйте код ES6 с помощью babel, используйте формат модуля по вашему выбору.
- Объединение скомпилированных модулей вместе с загрузчиком модулей ИЛИ использование связующего, которое будет пересекать ваши зависимости.
С rollupjs вещи действительно не работают таким образом. Здесь rollup - это первый шаг, а не babel. По умолчанию он понимает модули ES6. Вы должны предоставить модуль ввода, в котором будут проходить и контатетировать зависимости. Поскольку ES6 допускает множественный экспорт по имени в модуль, rollupjs достаточно умен, чтобы лишить неиспользуемый экспорт, тем самым уменьшая размер пакета. К сожалению, анализатор rollupjs-s не понимает > синтаксис ES6, поэтому модули ES7 должны быть скомпилированы до того, как rollup проанализирует их, но компиляция не должна влиять на импорт ES6. Это делается с помощью плагина rollup-plugin-babel
с предустановкой babel-preset-es2015-rollup
(этот пресет такой же, как у es2015, кроме модуля-трансформатора и плагина внешних помощников). Таким образом, при правильной настройке накопитель будет выполнять следующие действия с вашими модулями:
- Считывает ваш модуль ES6-7 из файловой системы
- Плагин babel скомпилирует его в ES6 в памяти
- rollup анализирует код ES6 для импорта и экспорта (с использованием анализатора желудей, скомпилированного в накопительный файл).
- он перемещает весь граф и создает единый пакет (который по-прежнему может иметь внешние зависимости, и экспорт записей может быть экспортирован в выбранном вами формате)
Пример nodejs build:
// 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 с grunt-rollup
// 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 build с gulp-rollup
// 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 - встроенное удаление мертвого кода. На данный момент (сентябрь 2016 года) я все же предлагаю использовать накопительный пакет с babel, хотя мое мнение может измениться с первого выпуска WebPack 2. Не стесняйтесь обсуждать свои мнения в комментариях.
Консоль пользовательской компиляции
Иногда вы хотите получить больше контроля над процессом компиляции. Вы можете реализовать свой собственный конвейер следующим образом:
Сначала вам нужно настроить babel для использования модулей amd. По умолчанию babel транслирует модули CommonJS, что немного сложно обрабатывать в браузере, хотя браузеру удается справиться с ними красиво.
- Вавилон 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);
}
}
В конце вы можете просто конкатенировать прокладку загрузчика и скомпилированные модули вместе и выполнить обход для этого.
Код шаблона Babel дублируется в каждом модуле
По умолчанию большинство вышеперечисленных методов объединяют каждый модуль с буфером в отдельности, а затем объединяют их вместе. То, что делает babelify, тоже. Но если вы посмотрите на скомпилированный код, вы увидите, что babel вставляет множество шаблонов в начале каждого файла, большинство из которых дублируется во всех файлах.
Чтобы предотвратить это, вы можете использовать плагин babel-plugin-transform-runtime
.