Archivo de la etiqueta: javascript

Gulp con Browserify, Watch y servidor Express.

Con Gulp tenemos disponible un build system con streams haciendo uso de las pipes de node.js. Es realmente útil para agilizar el desarrollo de aplicaciones de Javascript y se ha convertido en imprescindible para mí en muy poco tiempo.

En el siguiente post, veremos como crear un archivo de configuración para construir desde los archivos fuente de desarrollo a archivos destino los siguientes tipos:

  • HTML
  • CSS
  • Javascript

En Javascipt definiremos la tarea de browsificar modulos de node.js para cargarlos en el lado del navegador.

El script también incluirá la tarea watch para detectar los cambios en los archivos fuente y un servidor con una función de recarga automática para actualizar el navegador sin necesidad de recargar manualmente el documento.

Empezando, HTML

En primer lugar ejecutamos en el directorio raíz de la aplicación el comando:

$npm init

y esto nos crea un archivo JSON necesario para utilizar gulp con la aplicación.

Creamos un archivo llamado gulpfile.js y en él editaremos las tarea que serán llevadas a cabo por gulp.

Requerimos la carga el módulo llamado gulp:

var gulp = require('gulp');
var source = require('vinyl-source-stream');

Si el módulo no está instalado, hay que instalarlo introduciendo un comando tal como sigue:

$ npm install --save-dev nombredemodulo

y creamos la tarea:

gulp.task('html', function() {
  return gulp.src('./src/html/*.html')
    .pipe(gulp.dest('dist'))
});

En la línea de comandos, para lanzar la tarea:

$gulp html

CSS

La tarea:

gulp.task('styles', function() {
return gulp.src('src/styles/*.css')
.pipe(gulp.dest('./dist/styles'))

Node.js con Browserify

En primer lugar, crearemos una tarea para los archivos Javascript browseificados:

var browserify = require('browserify');
var html = require('html-browserify');
var gulpif = require('gulp-if');
var watch;

gulp.task('browserify-watch', function(){
watch = true;
browserifyShare();
});

function browserifyShare(){
var b = browserify({
cache: {},
packageCache: {},
fullPaths: true
});

if(watch) {
b = watchify(b);
b.on('update', function(){
bundleShare(b);
});
}

b.add('./script.js');

bundleShare(b);
}

function bundleShare(b) {
b.bundle()
.pipe(source('./script.js'))
.pipe(gulp.dest('./dist/scripts'))
}


Una tarea para lanzar las demás

Creamos otras tareas para llamar a las otras tareas definidas ahora mismo:

gulp.task('build', ['html', 'styles', 'browserify-watch']);
gulp.task('default', ['build']);

Con esto conseguimos que la tarea por defecto cargue el resto de tareas del script.

Para hacerlo:

$gulp

Observar los cambios: Watch

Hasta ahora, para cada cambio en un archivo fuente hay que ejecutar alguna tarea con el comando gulp, pero existe el modulo watch el cual se encarga de detectar cada cambio en los archivos fuente y ejecutar la tarea necesaria para su construcción sin cargar manualmente la tarea:

Para ello hay que hacer algunos cambios:

var watchify = require('watchify');

gulp.task('watch', ['browserify-watch'], function(){
gulp.watch('src/html/*.html', ['html']);
gulp.watch('src/styles/*.css', ['styles']);
}

gulp.task('build', ['html', 'styles', 'browserify-watch']);
gulp.task('default', ['build', 'watch']);

Instalando el servidor

Creamos las siguientes variables:

var express = require('express');
var server;

Y añadimos la tarea:

gulp.task('server', function() {
server = express();
server.use(express.static('dist'));
server.listen(8000);
browserSync({ proxy: 'localhost:8000' });
});

Abrimos el servidor:

$gulp server

Al iniciar la tarea server se lanzará el servidor y se podrá cerrar en cualquier momento con CTRL+C en la línea de comandos. El navegador accederá a la aplicación Javascript en la dirección localhost:8000

Recarga automática: BrowserSync

Hasta ahora hemos conseguido avances muy majos, pero aún podemos automatizar más el desarrollo de nuestra aplicación. Haremos una función que recarga automáticamente en el navegador los archivos modificados.

var browserSync = require('browser-sync');

Entonces, el servidor queda modificado así:

gulp.task('server', function() {
server = express();
server.use(express.static('dist'));
server.listen(8000);
browserSync({ proxy: 'localhost:8000' });
});

Al ejecutar la tarea, gulp abrirá el navegador por defecto y cargará el recurso en localhost:3000. Esto es así porque BrowserSync tiene incorporado un proxy para nuestros archivos.

Para recargar la tarea al modificar las fuentes, puede crearse esta función:

function reload() {
if (server) {
return browserSync.reload({ stream: true });
}

return gutil.noop();
}

Luego llamamos a la función en tuberías en cada tareas, por ejemplo, en la tarea HTML sería:

gulp.task('html', function() {
return gulp.src('./src/html/*.html')
.pipe(gulp.dest('dist'))
.pipe(reload());
});

para CSS:

gulp.task('styles', function() {
return gulp.src('src/styles/*.css')
.pipe(gulp.dest('./dist/styles'))
.pipe(reload());
});

y para Browserify:

function bundleShare(b) {
b.bundle()
.pipe(source('./script.js'))
.pipe(gulp.dest('./dist/scripts'))
.pipe(gulpif(watch, livereload()))
.pipe(reload());
}

Para llamar al proceso desde la tarea watch, ésta se puede modificar para que quedé así:

gulp.task('watch', ['browserify-watch'], function(){
gulp.watch('src/html/*.html', ['html']);
gulp.watch('src/styles/*.css', ['styles']);

livereload.listen(35729);

Por último, para lanzar gulp el servidor y todas las tareas:

$gulp

Resumen

A modo de resumen, el archivo gulpfile.js quedará así:

'use strict'
var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var express = require('express');
var html = require('html-browserify');
var watchify = require('watchify');
var livereload = require('gulp-livereload');
var gulpif = require('gulp-if');
var browserSync = require('browser-sync');
var notify = require('gulp-notify')
var util = require('gulp-util')
var server;
var watch;

gulp.task('html', function() {
return gulp.src('./src/html/*.html')
.pipe(gulp.dest('dist'))
.pipe(reload());
});

gulp.task('images', function() {
return gulp.src('images/*.svg')
.pipe(gulp.dest('./dist/images'))
.pipe(reload());
});

gulp.task('styles', function() {
return gulp.src('src/styles/*.css')
.pipe(gulp.dest('./dist/styles'))
.pipe(reload());
});

gulp.task('browserify-watch', function(){
watch = true;
browserifyShare();
});

function browserifyShare(){
var b = browserify({
cache: {},
packageCache: {},
fullPaths: true
});

if(watch) {
b = watchify(b);
b.on('update', function(){
bundleShare(b);
});
}

b.add('./script.js');

bundleShare(b);
}

function bundleShare(b) {
b.bundle()
.pipe(source('./script.js'))
.pipe(gulp.dest('./dist/scripts'))
.pipe(gulpif(watch, livereload()))
.pipe(reload());
}

gulp.task('server', function() {
server = express();
server.use(express.static('dist'));
server.listen(8000);
browserSync({ proxy: 'localhost:8000' });
});

gulp.task('watch', ['browserify-watch'], function(){
gulp.watch('src/html/*.html', ['html']);
gulp.watch('src/styles/*.css', ['styles']);

livereload.listen(35729);
});
gulp.task('build', ['html', 'styles', 'browserify-watch']);
gulp.task('default', ['build', 'server', 'watch']);

function reload() {
if (server) {
return browserSync.reload({ stream: true });
}

return util.noop();
}

Enlaces 17-09-2015

Talleres de Node.js y Javascript: Estos son workshops organizados en persona, generalmente sin costo, en los cuales los workshoppers son utilizados como planes de estudio y los mentores ayudan a los participantes a completar los ejercicios.

Buenas prácticas de desarrollo con node.js:  Node.js is JavaScript, so everything you already know about JavaScript applies to your Node application as well. The patterns you use to write your front-end client code can be used when writing your server-side application logic. Node does not use any JavaScript language extensions or modifications to accomplish its goal of server side JavaScript.

Libro JQuery en español: jQuery se está convirtiendo rápidamente en una herramienta que todo desarrollador de interfaces web debería de conocer. El propósito de este libro es proveer un resumen de la biblioteca, de tal forma que para cuando lo haya terminado de leer, será capaz de realizar tareas básicas utilizando jQuery y tendrá una sólida base para continuar el aprendizaje. El libro fue diseñado para ser utilizado como material en un salón de clases, pero también puede ser útil para estudiarlo de forma individual.

Entendiendo los prototipos en Javascript: El objeto prototype de JavaScript genera confusión allá por donde pasa. Veteranos profesionales de JavaScript e incluso autores frecuentemente exhiben un entendimiento limitado de este concepto. Creo que gran parte del problema radica en la primera toma de contacto, casi siempre de la mano de new, constructor y la tan desorientadora propiedad prototype de las funciones. En realidad, el prototipado es un concepto notablemente sencillo. Para entenderlo mejor solo es necesario olvidarse de lo que hayamos aprendido sobre prototipos de constructores y empezar de nuevo desde los principios.

Top 10 de errores que comenten los desarrolladores de node.js: Node.js has seen an important growth in the past years, with big companies such as Walmart or PayPal adopting it. More and more people are picking up Node and publishing modules to NPM at such a pace that exceeds other languages. However, the Node philosophy can take a bit to get used to, especially if you have switched from another language. In this article we will talk about the most common mistakes Node developers make and how to avoid them. You can find the source code for the examples on github.

Algunos apuntes para elegir frameworks js en una app: Cuando se comienza un desarrollo y decide uno hacerlo bajo un framework, elegirlo es una cuestión muy peliaguda. Es facil dejarse llevar por la moda, o porque tal o cual empresa lo utilizan, pero la verdad es que habría que analizar las preferencias en la manera de trabajar de cada uno, su coveniencia para el proyecto concreto, tiempos de desarrollo y muchos otros factores. No es un tema menor, la arquitectura de nuestra aplicación puede quedar fuertemente atada al framework y por tanto la evolución y escalado de la misma.