Eu preciso de require js quando uso o babel?
Você pode precisar de algum carregador de módulo, mas não é necessário RequireJS. Você tem várias opções. O que segue irá ajudá-lo a começar.
Rollup é um empacotador de módulo JavaScript de próxima geração. Ele entende os módulos ES2015 nativamente e produzirá um pacote que não precisa de nenhum carregador de módulo para operar. As exportações não utilizadas serão cortadas da saída, é chamado de agitação de árvore.
Agora, eu pessoalmente recomendo usar rollupjs, pois produz a saída mais clara e é fácil de configurar, no entanto, oferece um aspecto diferente para a resposta. Todas as outras abordagens fazem o seguinte:
- Compile o código ES6 com o babel, use o formato do módulo de sua escolha
- Concatene os módulos compilados junto com um carregador de módulo OU use um empacotador que atravessará as dependências para você.
Com rollupjs as coisas realmente não funcionam assim. Aqui, o rollup é a primeira etapa, em vez de babel. Ele só entende módulos ES6 por padrão. Você deve fornecer um módulo de entrada do qual as dependências serão percorridas e concatenadas. Como o ES6 permite várias exportações nomeadas em um módulo, rollupjs é inteligente o suficiente para retirar as exportações não utilizadas, reduzindo assim o tamanho do pacote. Infelizmente, o analisador rollupjs-s não entende a sintaxe ES6, então os módulos ES7 devem ser compilados antes que o rollup os analise, mas a compilação não deve afetar as importações ES6. Isso é feito usando o rollup-plugin-babel
plugin com o babel-preset-es2015-rollup
preset (este preset é igual ao es2015, exceto o transformador do módulo e o plugin de auxiliares externos). Portanto, o rollup fará o seguinte com seus módulos, se configurados corretamente:
- Lê seu módulo ES6-7 do sistema de arquivos
- O plugin babel o compila para ES6 na memória
- rollup analisa o código ES6 para importações e exportações (usando o analisador acorn, compilado em rollup)
- ele atravessa todo o gráfico e cria um único pacote (que ainda pode ter dependências externas e as exportações da entrada podem ser exportadas, em um formato de sua escolha)
Exemplo de compilação de 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"]
}
}
}
});
}
Exemplo de gulp build com 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'));
});
O Babel tem um pacote bacana chamado babelify . Seu uso é simples e direto:
$ 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 ] ]
ou você pode usá-lo em 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"));
Isso irá transpilar e concatenar seu código de uma vez. O Browserify .bundle
incluirá um pequeno carregador CommonJS agradável e organizará seus módulos transpilados em funções. Você pode até ter importações relativas.
Exemplo:
// 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);
Para compilar, basta executar node build.js
na raiz do projeto.
Compile todo o seu código usando o babel. Eu recomendo que você use o transformador do módulo amd (chamado babel-plugin-transform-es2015-modules-amd
em babel 6). Depois disso, empacote suas fontes compiladas com WebPack.
O WebPack 2 foi lançado! Ele compreende módulos ES6 nativos e executa (ou melhor, simula) a agitação da árvore usando a eliminação de código morto embutida do babili . Por enquanto (setembro de 2016), eu ainda sugiro usar o rollup com o babel, embora minha opinião possa mudar com o primeiro lançamento do WebPack 2. Sinta-se à vontade para discutir suas opiniões nos comentários.
Pipeline de compilação personalizado
Às vezes, você deseja ter mais controle sobre o processo de compilação. Você pode implementar seu próprio pipeline desta forma:
Primeiro, você deve configurar o babel para usar os módulos amd. Por padrão, o babel transpila para módulos CommonJS, o que é um pouco complicado de manipular no navegador, embora o browserify consiga lidar com eles de uma maneira agradável.
- Babel 5:
{ modules: 'amdStrict', ... }
opção de uso
- Babel 6: use o
es2015-modules-amd
plugin
Não se esqueça de ativar a moduleIds: true
opção.
Verifique o código transpilado para nomes de módulos gerados, muitas vezes há incompatibilidades entre os módulos definidos e necessários. Consulte sourceRoot e moduleRoot .
Finalmente, você deve ter algum tipo de carregador de módulo, mas não é necessário. Há almondjs , um pequeno calço que funciona bem. Você pode até implementar o seu próprio:
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);
}
}
No final, você pode apenas concatenar o shim do carregador e os módulos compilados juntos e executar um uglify nisso.
O código padrão do Babel é duplicado em todos os módulos
Por padrão, a maioria dos métodos acima compila cada módulo com babel individualmente e, em seguida, concatena-os. É isso que o babelify também faz. Mas se você olhar o código compilado, verá que o babel insere vários clichês no início de cada arquivo, a maioria deles duplicados em todos os arquivos.
Para evitar isso, você pode usar o babel-plugin-transform-runtime
plugin.
require
não existe no navegador, você precisa usar alguma ferramenta de construção como Require.js, Browserify ou Webpack.