plumbin pipelines - a gulp.js workshop

109
Plumbin' Pipelines with Gulp.js

Upload: stefan-baumgartner

Post on 16-Jan-2017

439 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Plumbin Pipelines - A Gulp.js workshop

Plumbin' Pipelines with Gulp.js

Page 2: Plumbin Pipelines - A Gulp.js workshop

@Dynatrace

@Ruxit

Page 3: Plumbin Pipelines - A Gulp.js workshop

@ddprrt

fettblog.eu

Page 4: Plumbin Pipelines - A Gulp.js workshop

HTML

CSS

JavaScript

Page 5: Plumbin Pipelines - A Gulp.js workshop

Sass CoffeeScript LESS

P o s t C S S H A M L J a d e

U g l i f y E S 6 R e a c t J S

Browserify AngularJS

Ember CSSMin JSLint

ESHint ImageOptim Mocha

Jasmine TypeScript

Page 6: Plumbin Pipelines - A Gulp.js workshop
Page 7: Plumbin Pipelines - A Gulp.js workshop
Page 8: Plumbin Pipelines - A Gulp.js workshop
Page 9: Plumbin Pipelines - A Gulp.js workshop
Page 10: Plumbin Pipelines - A Gulp.js workshop

1530 lines of code

original Ant tasks used:

concat — copy — delete — mkdir

Page 11: Plumbin Pipelines - A Gulp.js workshop
Page 12: Plumbin Pipelines - A Gulp.js workshop

Let's talk a short bit about the JS build tool

revolution

Page 13: Plumbin Pipelines - A Gulp.js workshop

Grunt started a boom

Page 14: Plumbin Pipelines - A Gulp.js workshop

Gruntfiles get long

Page 15: Plumbin Pipelines - A Gulp.js workshop

Grunt tasks get slow

Page 16: Plumbin Pipelines - A Gulp.js workshop

lots of reads

and writes

Page 17: Plumbin Pipelines - A Gulp.js workshop

And then came Gulp

Page 18: Plumbin Pipelines - A Gulp.js workshop

Disclaimer

Page 19: Plumbin Pipelines - A Gulp.js workshop

I (occasionally) contribute

to Gulp

Page 20: Plumbin Pipelines - A Gulp.js workshop

I'm writing a book on Gulp

http://bit.ly/gulp-tool-book

39% off with 39baumgarcoupon code!

Page 21: Plumbin Pipelines - A Gulp.js workshop

I don't know Java anymore

Java is to JavaScript whatAlf is to Gandalf

Page 22: Plumbin Pipelines - A Gulp.js workshop

Let's go!

Page 23: Plumbin Pipelines - A Gulp.js workshop

The ecosystem

Page 24: Plumbin Pipelines - A Gulp.js workshop
Page 25: Plumbin Pipelines - A Gulp.js workshop

Runtime environment

JavaScript

Page 26: Plumbin Pipelines - A Gulp.js workshop

Package System for Node

Host of all things Gulp plugins

Page 27: Plumbin Pipelines - A Gulp.js workshop

CLI Gulpfile

PluginA

PluginA

Page 28: Plumbin Pipelines - A Gulp.js workshop

CLI Gulpfile

PluginA

PluginA

starts

Page 29: Plumbin Pipelines - A Gulp.js workshop

CLI Gulpfile

PluginA

PluginA

loadsstarts

Page 30: Plumbin Pipelines - A Gulp.js workshop

CLI Gulpfile

PluginA

PluginA

loadsstarts

uses

Page 31: Plumbin Pipelines - A Gulp.js workshop

npm install -g gulp-cli

npm init

npm install --save-dev gulp

touch gulpfile.js

Page 32: Plumbin Pipelines - A Gulp.js workshop

npm install -g gulpjs/gulp-cli#4.0

npm init

npm install --save-dev gulpjs/gulp#4.0

touch gulpfile.js

Page 33: Plumbin Pipelines - A Gulp.js workshop

The basics:

Streams

Page 34: Plumbin Pipelines - A Gulp.js workshop

gulp.src(…) gulp.dest(…)

Reads files Writes files

Page 35: Plumbin Pipelines - A Gulp.js workshop

gulp.src(…) gulp.dest(…)

Page 36: Plumbin Pipelines - A Gulp.js workshop

gulp.src(…) .pipe(uglify()) gulp.dest(…)

Page 37: Plumbin Pipelines - A Gulp.js workshop

gulp.src(…) .pipe(uglify()) gulp.dest(…).pipe(concat())

Page 38: Plumbin Pipelines - A Gulp.js workshop

to the command line!

Page 39: Plumbin Pipelines - A Gulp.js workshop

Gulp API

• gulp.task creates a new task

• It requires to return either a Stream, a Promise or an Observable

• gulp.src “globs” files and returns a stream of virtual file objects

• each file can be piped through a process (jshint, uglify, less, etc.)

• gulp.dest saves the file back to the file system

Page 40: Plumbin Pipelines - A Gulp.js workshop

gulp.task('styles', function() { return gulp.src('app/styles/main.less') .pipe(less()) .pipe(minifyCSS()) .pipe(prefix()) .pipe(gulp.dest('dist/styles')); });

Page 41: Plumbin Pipelines - A Gulp.js workshop

gulp.task('styles', function() { return gulp.src('app/styles/main.less') .pipe(less()) .pipe(minifyCSS()) .pipe(prefix()) .pipe(gulp.dest('dist/styles')); });

defines a new task

Page 42: Plumbin Pipelines - A Gulp.js workshop

gulp.task('styles', function() { return gulp.src('app/styles/main.less') .pipe(less()) .pipe(minifyCSS()) .pipe(prefix()) .pipe(gulp.dest('dist/styles')); });

with a defined name

Page 43: Plumbin Pipelines - A Gulp.js workshop

gulp.task('styles', function() { return gulp.src('app/styles/main.less') .pipe(less()) .pipe(minifyCSS()) .pipe(prefix()) .pipe(gulp.dest('dist/styles')); });

we load a certain file

(or files)

Starting here, we have virtual

files in-memory instead of

real files we

Page 44: Plumbin Pipelines - A Gulp.js workshop

gulp.task('styles', function() { return gulp.src('app/styles/main.less') .pipe(less()) .pipe(minifyCSS()) .pipe(prefix()) .pipe(gulp.dest('dist/styles')); });

and pipe it through a

series of operations

Page 45: Plumbin Pipelines - A Gulp.js workshop

gulp.task('styles', function() { return gulp.src('app/styles/main.less') .pipe(less()) .pipe(minifyCSS()) .pipe(prefix()) .pipe(gulp.dest('dist/styles')); });

before we save it

again on the "real" file system

Page 46: Plumbin Pipelines - A Gulp.js workshop

Tasks

Page 47: Plumbin Pipelines - A Gulp.js workshop

scripts styles lint

Page 48: Plumbin Pipelines - A Gulp.js workshop

scripts

styles

lintgulp.parallel

Page 49: Plumbin Pipelines - A Gulp.js workshop

scripts

styles

lint

gulp.parallel

gulp.series

Page 50: Plumbin Pipelines - A Gulp.js workshop

to the command line!

Page 51: Plumbin Pipelines - A Gulp.js workshop

Gulp API

• The second parameter of gulp.task is always a function.

• gulp.series is a task function that runs tasks in sequential order.

• gulp.parallel is a task function that starts every task concurrently

• Both task functions accept task names and other functions as parameters.

• They can be combined infinitly

Page 52: Plumbin Pipelines - A Gulp.js workshop

gulp.task('default', gulp.series('clean', gulp.parallel('styles', 'scripts'), ‘server' ) );

Page 53: Plumbin Pipelines - A Gulp.js workshop

gulp.task('default', gulp.series('clean', gulp.parallel('styles', 'scripts'), ‘server' ) );

runs in series

Page 54: Plumbin Pipelines - A Gulp.js workshop

gulp.task('default', gulp.series('clean', gulp.parallel('styles', 'scripts'), ‘server' ) );

runs in parallel

Page 55: Plumbin Pipelines - A Gulp.js workshop

A development

environment

Page 56: Plumbin Pipelines - A Gulp.js workshop

gulp.watch

scripts

*.js

Page 57: Plumbin Pipelines - A Gulp.js workshop

Bowser-Sync!

r

Page 58: Plumbin Pipelines - A Gulp.js workshop

to the command line!

Page 59: Plumbin Pipelines - A Gulp.js workshop

Gulp API

• gulp.watch creates a file watcher and listens to changes

• changes include ‘change’, ‘add’, ‘unlink’ and others

• BrowserSync is a development tool that can be fully integrated in Gulp.

• Watchers trigger a browserSync.reload call

Page 60: Plumbin Pipelines - A Gulp.js workshop

function watcher(done) { gulp.watch('styles/**/*.less', gulp.parallel(‘styles’)); done(); }

Page 61: Plumbin Pipelines - A Gulp.js workshop

function watcher(done) { gulp.watch('styles/**/*.less', gulp.parallel(‘styles’)); done(); }

watches this Glob pattern

Page 62: Plumbin Pipelines - A Gulp.js workshop

function watcher(done) { gulp.watch('styles/**/*.less', gulp.parallel(‘styles’)); done(); }

starts this task on

change, unlink, add

Page 63: Plumbin Pipelines - A Gulp.js workshop

gulp.task('server', function(done) { bSync({ server: { baseDir: ['dist', 'app'] } }) done(); });

Page 64: Plumbin Pipelines - A Gulp.js workshop

gulp.task('server', function(done) { bSync({ server: { baseDir: ['dist', 'app'] } }) done(); }); BrowserSync set up to start

a dev server, serving dist and

app statically

Page 65: Plumbin Pipelines - A Gulp.js workshop

gulp.watch('dist/**/*', bSync.reload);

And a watcher that triggers a

reload

Page 66: Plumbin Pipelines - A Gulp.js workshop

Incremental

builds

Page 67: Plumbin Pipelines - A Gulp.js workshop

Some tasks take long

gulp.src(‘scripts/*.js’)

.pipe(uglify())

.pipe(gulp.dest())

.pipe(concat())

Page 68: Plumbin Pipelines - A Gulp.js workshop

Some tasks take long

gulp.src(‘scripts/*.js’)

.pipe(uglify())

.pipe(gulp.dest())

.pipe(concat())

Page 69: Plumbin Pipelines - A Gulp.js workshop

Some tasks take long

gulp.src(‘scripts/*.js’)

.pipe(uglify())

.pipe(gulp.dest())

.pipe(concat())

Too much is going on!

Each change: Uglify all

the files?

Page 70: Plumbin Pipelines - A Gulp.js workshop

Some tasks take long

gulp.src(‘scripts/*.js’)

.pipe(uglify())

.pipe(gulp.dest())

.pipe(concat())

Page 71: Plumbin Pipelines - A Gulp.js workshop
Page 72: Plumbin Pipelines - A Gulp.js workshop

filter files

that have changed

Page 73: Plumbin Pipelines - A Gulp.js workshop

filter files

that have changed

do performance

heavy operations

Page 74: Plumbin Pipelines - A Gulp.js workshop

filter files

that have changed

do performance

heavy operations

remember the

old files

Page 75: Plumbin Pipelines - A Gulp.js workshop

filter files

that have changed

do performance

heavy operations

remember the

old files

and continue

with the other ops

Page 76: Plumbin Pipelines - A Gulp.js workshop

to the command line!

Page 77: Plumbin Pipelines - A Gulp.js workshop

Gulp Plugins

• gulp-cached and gulp-remember can be used to create file caches

• The plugin filters non-changed files and ads them back to the stream once we are done with performance-heavy tasks

• Additionally to that, we can use gulp.lastRun in Gulp 4 to filter files during globbing

• gulp-newer allows us to do incremental copies/builds on a per-file basis

Page 78: Plumbin Pipelines - A Gulp.js workshop

gulp.task('scripts', function () { return gulp.src('app/scripts/**/*.js') .pipe(cached('ugly')) .pipe(uglify()) .pipe(remember('ugly')) .pipe(concat('main.min.js')) .pipe(gulp.dest('dist/scripts')); });

Page 79: Plumbin Pipelines - A Gulp.js workshop

gulp.task('scripts', function () { return gulp.src('app/scripts/**/*.js') .pipe(cached('ugly')) .pipe(uglify()) .pipe(remember('ugly')) .pipe(concat('main.min.js')) .pipe(gulp.dest('dist/scripts')); });

we use the cache to

check if files have

changed

Page 80: Plumbin Pipelines - A Gulp.js workshop

gulp.task('scripts', function () { return gulp.src('app/scripts/**/*.js') .pipe(cached('ugly')) .pipe(uglify()) .pipe(remember('ugly')) .pipe(concat('main.min.js')) .pipe(gulp.dest('dist/scripts')); });

once we are done,

we remember all

the other files

we stored in

the cache

Page 81: Plumbin Pipelines - A Gulp.js workshop

Part II

Page 82: Plumbin Pipelines - A Gulp.js workshop

A short

source map interlude

Page 83: Plumbin Pipelines - A Gulp.js workshop

Browserify

(for Babel/React)

Page 84: Plumbin Pipelines - A Gulp.js workshop

so similar … yet so

different?

Gulp

Streams

Browserify Streams

Page 85: Plumbin Pipelines - A Gulp.js workshop

Why not both??

Page 86: Plumbin Pipelines - A Gulp.js workshop

var b = browserify({ entries: ['_js/main.js'] });

var bundle = function() { return b.bundle() .pipe(source(‘main.js’)) .pipe(buffer()) .pipe(uglify()) .pipe(gulp.dest('js')); }

Page 87: Plumbin Pipelines - A Gulp.js workshop

var b = browserify({ entries: ['_js/main.js'] });

var bundle = function() { return b.bundle() .pipe(source(‘main.js’)) .pipe(buffer()) .pipe(uglify()) .pipe(gulp.dest('js')); }

b.bundle emits a

stream.

But no vinyl file

objects

Page 88: Plumbin Pipelines - A Gulp.js workshop

var b = browserify({ entries: ['_js/main.js'] });

var bundle = function() { return b.bundle() .pipe(source(‘main.js’)) .pipe(buffer()) .pipe(uglify()) .pipe(gulp.dest('js')); }

vinyl-source-stream

wraps the original

stream into

a vinyl file object

Page 89: Plumbin Pipelines - A Gulp.js workshop

var b = browserify({ entries: ['_js/main.js'] });

var bundle = function() { return b.bundle() .pipe(source(‘main.js’)) .pipe(buffer()) .pipe(uglify()) .pipe(gulp.dest('js')); }

vinyl-buffer converts

the stream contents

to a buffer for

plugins who need

such

Page 90: Plumbin Pipelines - A Gulp.js workshop

Stream arrays

and merge Streams

Page 91: Plumbin Pipelines - A Gulp.js workshop

A static

site generator

Page 92: Plumbin Pipelines - A Gulp.js workshop

What does it do?

• Generates static HTML sites

• From a templating engine

• Can parse Markdown

• Can parse HTML

• Can create permalinks

• For different types (posts, pages)

Page 93: Plumbin Pipelines - A Gulp.js workshop

The stack

• We use kramdown to convert Markdown to HTML

• We use nujucks for our templating engine

• We rename posts to feature blog permalink

• We rename pages to resemble pretty URLs

Page 94: Plumbin Pipelines - A Gulp.js workshop

In pipes

gulp.src(‘posts/*.md')

.pipe(kramdown())

.pipe(wrap())

.pipe(nunjucks())

.pipe(rename())

.pipe(gulp.dest())

Page 95: Plumbin Pipelines - A Gulp.js workshop

In pipes

gulp.src(‘posts/*.md')

.pipe(kramdown())

.pipe(wrap())

.pipe(nunjucks())

.pipe(rename())

.pipe(gulp.dest())

gulp.src(‘posts/*.html')

.pipe(wrap())

.pipe(nunjucks())

.pipe(rename())

.pipe(gulp.dest())

Page 96: Plumbin Pipelines - A Gulp.js workshop

In pipes

gulp.src(‘posts/*.md')

.pipe(kramdown())

.pipe(wrap())

.pipe(nunjucks())

.pipe(rename())

.pipe(gulp.dest())

gulp.src(‘posts/*.html')

.pipe(wrap())

.pipe(nunjucks())

.pipe(rename())

.pipe(gulp.dest())

the same!

Page 97: Plumbin Pipelines - A Gulp.js workshop

In pipes

gulp.src(‘pages/*.md')

.pipe(kramdown())

.pipe(wrap())

.pipe(nunjucks())

.pipe(rename())

.pipe(gulp.dest())

gulp.src(‘pages/*.html')

.pipe(wrap())

.pipe(nunjucks())

.pipe(rename())

.pipe(gulp.dest())

Page 98: Plumbin Pipelines - A Gulp.js workshop

In pipes

gulp.src(‘pages/*.md')

.pipe(kramdown())

.pipe(wrap())

.pipe(nunjucks())

.pipe(rename())

.pipe(gulp.dest())

gulp.src(‘pages/*.html')

.pipe(wrap())

.pipe(nunjucks())

.pipe(rename())

.pipe(gulp.dest())

the same!

Page 99: Plumbin Pipelines - A Gulp.js workshop

What if we could

reuse parts of the

stream?

Page 100: Plumbin Pipelines - A Gulp.js workshop

to the command line!

Page 101: Plumbin Pipelines - A Gulp.js workshop

to the command line!

Page 102: Plumbin Pipelines - A Gulp.js workshop

gulp.task('default', function(cb) { var streams = elements.map(function(el) { return merge( gulp.src(el.dir + '/**.md').pipe(markdown()), gulp.src(el.dir + '/**.html') ).pipe(rename(el.renamefn)); }); return merge(streams).pipe(data(options)) .pipe(wrap(layoutStr)) .pipe(swig()) .pipe(gulp.dest('build')); });

Page 103: Plumbin Pipelines - A Gulp.js workshop

gulp.task('default', function(cb) { var streams = elements.map(function(el) { return merge( gulp.src(el.dir + '/**.md').pipe(markdown()), gulp.src(el.dir + '/**.html') ).pipe(rename(el.renamefn)); }); return merge(streams).pipe(data(options)) .pipe(wrap(layoutStr)) .pipe(swig()) .pipe(gulp.dest('build')); });

we combine

multiple sources

to one stream

Page 104: Plumbin Pipelines - A Gulp.js workshop

gulp.task('default', function(cb) { var streams = elements.map(function(el) { return merge( gulp.src(el.dir + '/**.md').pipe(markdown()), gulp.src(el.dir + '/**.html') ).pipe(rename(el.renamefn)); }); return merge(streams).pipe(data(options)) .pipe(wrap(layoutStr)) .pipe(swig()) .pipe(gulp.dest('build')); });

with Array.map

and merge we can

create stream

arrays

Page 105: Plumbin Pipelines - A Gulp.js workshop

Material

Page 106: Plumbin Pipelines - A Gulp.js workshop

Workshop files

https://github.com/frontend-tooling

https://github.com/frontend-tooling/sample-project-gulp

https://github.com/frontend-tooling/static-site-generator

http://fettblog.eu

http://speakerdeck.com/ddprrt

Page 107: Plumbin Pipelines - A Gulp.js workshop

Reading Material

http://bit.ly/gulp-tool-book

39% off with 39baumgarcoupon code!

Page 108: Plumbin Pipelines - A Gulp.js workshop
Page 109: Plumbin Pipelines - A Gulp.js workshop

@ddprrt