Нужно ли мне требовать js, когда я использую babel?
Вам может понадобиться загрузчик модулей, но это не обязательно RequireJS. У вас есть несколько вариантов. Следующее поможет вам начать работу.
Rollup - это сборщик модулей JavaScript нового поколения. Он изначально понимает модули ES2015 и создаст пакет, для работы которого не нужен загрузчик модулей. Неиспользуемый экспорт будет удален из вывода, это называется встряхиванием дерева.
Теперь я лично рекомендую использовать rollupjs, так как он дает наиболее четкий вывод и прост в настройке, однако он дает другой аспект ответа. Все остальные подходы делают следующее:
- Скомпилируйте код ES6 с помощью babel, используйте формат модуля по вашему выбору
- Объедините скомпилированные модули вместе с загрузчиком модулей ИЛИ используйте сборщик, который будет обходить зависимости за вас.
С rollupjs дела обстоят не так. Здесь rollup - это первый шаг, а не babel. По умолчанию он понимает только модули ES6. Вы должны указать модуль ввода, зависимости которого будут отслеживаться и объединяться. Поскольку ES6 позволяет использовать несколько именованных экспортов в модуле, rollupjs достаточно умен, чтобы удалять неиспользуемые экспорты, уменьшая таким образом размер пакета. К сожалению, парсер rollupjs-s не понимает> синтаксис ES6, поэтому модули ES7 должны быть скомпилированы до того, как их проанализирует объединительный пакет, но компиляция не должна влиять на импорт ES6. Это делается с помощью rollup-plugin-babel
плагина с babel-preset-es2015-rollup
пресетом (этот пресет такой же, как у es2015, за исключением модуля-преобразователя и плагина external-helpers). Таким образом, при правильной настройке накопительный пакет будет выполнять следующие действия с вашими модулями:
- Читает ваш модуль ES6-7 из файловой системы
- Плагин babel компилирует его в ES6 в памяти
- rollup анализирует код ES6 для импорта и экспорта (с помощью синтаксического анализатора acorn, скомпилированного в rollup)
- он проходит через весь граф и создает один пакет (который все еще может иметь внешние зависимости, и экспорт записи может быть экспортирован в формате по вашему выбору)
Пример сборки 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));
// 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"]
}
}
}
});
}
// 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'));
});
У 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. Я рекомендую вам использовать трансформатор модуля amd (названный babel-plugin-transform-es2015-modules-amd
в babel 6). После этого свяжите ваши скомпилированные исходники с WebPack.
WebPack 2 вышел! Он понимает собственные модули ES6 и будет выполнять (или, скорее, моделировать) встряхивание дерева с помощью babili. встроенную мертвого кода . На данный момент (сентябрь 2016 г.) я все же предлагаю использовать rollup с babel, хотя мое мнение может измениться с выходом первого выпуска WebPack 2. Не стесняйтесь обсуждать свое мнение в комментариях.
Пользовательский конвейер компиляции
Иногда вам нужно больше контроля над процессом компиляции. Вы можете реализовать свой собственный конвейер следующим образом:
Во-первых, вам нужно настроить babel для использования модулей amd. По умолчанию babel переносится в модули CommonJS, что немного сложно обрабатывать в браузере, хотя browserify справляется с ними хорошо.
- Вавилон 5: использование
{ modules: 'amdStrict', ... }
вариант
- Babel 6: используйте
es2015-modules-amd
плагин
Не забудьте включить moduleIds: true
опцию.
Проверьте переданный код на наличие сгенерированных имен модулей, часто есть несоответствия между определенными и требуемыми модулями. Смотрите sourceRoot и moduleRoot .
Наконец, у вас должен быть какой-то загрузчик модулей, но это не обязательно requirejs. Есть 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);
}
}
В конце вы можете просто объединить прокладку загрузчика и скомпилированные модули вместе и запустить на этом uglify.
Стандартный код Babel дублируется в каждом модуле
По умолчанию большинство вышеперечисленных методов компилируют каждый модуль с babel по отдельности, а затем объединяют их вместе. Это то, что делает babelify. Но если вы посмотрите на скомпилированный код, вы увидите, что babel вставляет множество шаблонов в начало каждого файла, большинство из них дублируются во всех файлах.
Чтобы предотвратить это, вы можете использовать babel-plugin-transform-runtime
плагин.
require
его нет в браузере, вам нужно использовать какой-нибудь инструмент сборки, например Require.js, Browserify или Webpack.