Este artigo é destinado para usuários com alguma experiência com Gulp.js.
Nos meus últimos dois dias úteis, estive lidando com um problema muito chato para executar minhas tarefas de Browserify e React.js no Gulp e vou compartilhar a solução que, na minha opinião, é a mais simples que encontrei até então. Vamos lá?
Background
Estou utilizando Bower para gerenciar as dependências que ficam no cliente e, portanto, me obrigo a fazer o shim delas para utilizá-las (facilmente) junto ao Browserify. O ponto é que eu estou utilizando o bundle de módulos gulp-browserify para solucionar o meu problema com Gulp + Browserify e não o módulo Browserify puro.
Vejam a minha task com gulp-browserify:
gulp.task('scripts', function () { return gulp.src('./assets/js/main.js') .pipe(browserify({ insertGlobals: true, shim: { jquery: { path: './assets/vendor/jquery/dist/jquery.js', exports: '#039; }, underscore: { path: './assets/vendor/underscore/underscore.js', exports: '_', depends: { jquery: '#039; } }, backbone: { path: './assets/vendor/backbone/backbone.js', exports: 'Backbone', depends: { underscore: '_' } } } })) .pipe(gulp.dest('./static/js')); });
Tudo estava a funcionar muito bem até que decidi por utilizar o React: eis aqui quando a dor de cabeça veio à tona.
Background – II
O React possui duas diretrizes, sendo uma essencial e outra optativa. A essencial é o React em si e a optativa é a utilização da sua “sintaxe” JSX. Por questões pessoais e para facilitar a minha vida na escrita de código, decidi por ir de JSX, o que significa o seguinte:
“Preciso fazer shim do React; Preciso fazer com que arquivos .jsx se “transformem” em .js”.
Então, fui logo para a internet procurar uma solução para trabalhar com o Gulp e tudo o que eu achei se referia a utilização do falado módulo browserify para se utilizar com o gulp. Em nenhum momento encontrei algo para o gulp-browserify, que já traz consigo o browserify e o browserify-shim – que, como falado, é necessário para que eu possa lidar com as dependências instaladas através do Bower.
Background – III
Insisti em uma solução que utilizasse o gulp-browserify para que me poupasse de reinventar a roda, mas não encontrei nada. Então, fiz alguns testes com o módulo “vanilla” browserify utilizando reactify e browserify-shim como transformers, mas o resultado não foi satisfatório porque não entrava na minha cabeça como utilizá-los em conjunto.
Quando me dei conta de que estava “perdendo” muito tempo, comecei a seguir exatamente o que os guias me instruíam e, de novo, nenhum êxito.
Em seguida, “descobri” que o meu problema absoluto era o shiming. React e Browserify + shim não estavam conversando no mesmo idioma.
A solução!
Pode parecer óbvio – e definitivamente é! –, mas para mim foi um momento Eureka, porque durante dois dias inteiros eu não tinha pensado nisso: só pensei em procurar uma solução através de um módulo e pronto.
Vejam só a descrição do gulp-react: Precompile Facebook React JSX templates into JavaScript
Em português traduzido livremente: Pré-compila os templates JSX do React do Facebook em JavaScript
Pensando de forma sequencial, tenho o seguinte: Primeiro de tudo, compilo JSX em JS, depois, com o JS gerado, consigo fazer o que eu quiser através da minha anteriormente apresentada task scripts.
O que eu fiz, então, foi manter intacta a minha tarefa scripts e então criei uma nova para transformação de JSX em JS:
gulp.task('jsx', function () { return gulp.src('./assets/jsx/**/*.jsx') .pipe(react()) .pipe(gulp.dest('./assets/js/')); });
E então, voi là! Simples, não?
Mas vamos fazer o seguinte: vou explicar o passo-a-passo, do zero, para você entender de maneira flat.
A solução – simples
Para baixar e instalar o gulp, gulp-browserify e gulp-react:
npm install --D gulp gulp-browserify gulp-react
Então, o seu gulpfile.js:
var gulp = require ('gulp') , browserify = require ('gulp-browserify') , react = require ('gulp-react'); gulp.task('jsx', function () { return gulp.src('./assets/jsx/**/*.jsx') .pipe(react()) .pipe(gulp.dest('./assets/js/')); }); gulp.task('scripts', function () { return gulp.src('./assets/js/main.js') .pipe(browserify({ shim: { react: { path: './assets/vendor/react/react.js', exports: 'React' } } })) .pipe(gulp.dest('./static/js/')); }); gulp.task('default', ['jsx', 'scripts']);
Lendo o arquivo, de cima para baixo e à grosso modo, teríamos:
- O carregamento das três dependências;
- A tarefa jsx, que acessa todas (**) as pastas de ./assets/jsx/ e itera entre os arquivos de extensão .jsx para transformá-los em .js, salvando-os na pasta ./assets/js/.
- A tarefa scripts, que utiliza do gulp-browserify para gerenciar as dependências e fazer o shiming do react para finalmente salvar em um arquivo único, nomeado de main.js, na pasta ./static/js/.
Depois, via linha de comando:
gulp
Ou, individualmente:
gulp jsx
e
gulp scripts
Considerações finais
Por incrível que possa parecer, essa é a solução mais simples que eu pude encontrar. Me poupa de reinventar a roda utilizando o módulo browserifyno Gulp e faz exatamente o que eu quero. Para outros que enfrentam o mesmo problema, eis aqui a solução.