In a former post (A gulp of coffee: your gulpfile in coffeescript), I've shown how to bootstrap CoffeeScript in Gulp. There is now a far better solution than mine that does not require any additional file: Cult.
This little CLI just analyse the extension and automatically requires the right REPL. A time saver!
Affichage des articles dont le libellé est Gulp. Afficher tous les articles
Affichage des articles dont le libellé est Gulp. Afficher tous les articles
18 mai 2014
17 mai 2014
Famo.us gulped bumped to v0.2.0
I've just updated my sample project for building a Famo.us v0.2.0 with Gulp.
I've also added a simple example to show how you can use the
Look at how simple it is to set content so that it takes advantage of the complete browser's height and width. Centering content is so easy as well. No funny tricks, just a simple code that works well on mobile, tablet and regular desktop browsers.
I've also added a simple example to show how you can use the
HeaderFooterLayout to layout the basis of your SPA:Look at how simple it is to set content so that it takes advantage of the complete browser's height and width. Centering content is so easy as well. No funny tricks, just a simple code that works well on mobile, tablet and regular desktop browsers.
HeaderFooterLayout = require 'famous/views/HeaderFooterLayout'
layout = new HeaderFooterLayout
headerSize: 100
footerSize: 50
mainContext.add layout
layout.header.add new Surface
content: 'Header'
size: [undefined, 100]
classes: ['header-surface']
properties:
lineHeight: '100px'
textAlign: 'center'
layout.content.add new Surface
content: 'Content'
size: [undefined, undefined]
properties:
lineHeight: '300px'
textAlign: 'center'
layout.footer.add new Surface
content: 'Footer'
size: [undefined, 50]
classes: ['footer-surface']
properties:
lineHeight: '50px'
textAlign: 'center'
13 avr. 2014
Famo.us with Gulp.js and Browserify in CoffeeScript
Introduction
Famo.us is a new framework with a new radical approach to HTML5 development. Basically, everything is treated as surfaces which are seen by the browser as accelerated virtual DOM components. This is all achieved under the JS files and not via CSS3 files via transforms and animations. Therefore, it avoids pollution of your CSS which is solely used for theming. As virtual DOM, the real HTML's DOM is not polluted either with DIVs inserted only for animation purposes. The animations and screen dynamics are kept separated in your JS files. But, it is not all that is provided out-of-the-box. Every tricks that needs to be inserted in our codes for being compatible with all mobiles, tablets and desktops have been inserted directly in the library. HTML5 starts to really shine using Famo.us.
Why an HelloWorld?
Currently, Famo.us is distributed either as source file in their Github repository or as a Yeoman generator that uses Grunt. This last option is incredibly nice and will surely be the most preferred one. It is rare enough to note it: Famo.us has done a great job towards its users. There are really few frameworks which provides so much as soon as they are launched. Plus, it has been done 'state-of-the-art' for most users who like writing plain HTML, CSS and JS. Really nice. Kudos to the Famo.us team.
But, if you have read this blog entries, you should know that I don't like writing vanilla codes. I generally prefer relying on preprocessors. So, with this little tutorial, I will show you my best moves to integrate Sass, Jade, CoffeeScript and Famo.us using Gulp.js and Browserify. Once done, it becomes easy to start playing with the great examples that Famo.us provides: Collection of Famo.us examples on Github.
I've shared all the source code of this tutorial into a little Github repository: PEM--/hellofamousgulped.
I've shared all the source code of this tutorial into a little Github repository: PEM--/hellofamousgulped.
Creating the folder hierarchy
Thetree of files is as following:. ├── app │ ├── css │ │ └── main.sass │ ├── index.jade │ └── js │ └── main.coffee ├── bower.json ├── gulpfile.coffee ├── gulpfile.js └── package.json
To create it, use this classic command:
mkdir -p app/css app/js
Import Famo.us using Bower
Now, we import Famo.us thanks to Bower. Here is the content of mybower.json file:
{
"name": "HelloFamousGulped",
"version": "0.0.0",
"authors": [
"PEM--"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"famous": "git@github.com:Famous/famous.git#v0_1_1"
}
}
Once copied, use Bower to import Famo.us and all its submodules:
bower install
Import Gulp.js and Browserify using NPM
No JS on your desktop without the powerful Node Package Management. To import all our required build tools and plugins, use mypackage.json or get inspiration from it:{
"name": "HelloFamousGulped",
"version": "0.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "PEM--",
"license": "MIT",
"dependencies": {},
"devDependencies": {
"gulp": "^3.6.0",
"gulp-load-plugins": "^0.5.0",
"gulp-util": "^2.2.14",
"gulp-autoprefixer": "0.0.6",
"gulp-imagemin": "^0.2.0",
"gulp-clean": "^0.2.4",
"gulp-cache": "^0.1.3",
"gulp-ruby-sass": "^0.4.3",
"gulp-connect": "^2.0.5",
"gulp-cssmin": "^0.1.4",
"gulp-jade": "^0.5.0",
"gulp-concat": "^2.2.0",
"gulp-plumber": "^0.6.1",
"gulp-watch": "^0.5.4",
"gulp-changed": "^0.3.0",
"gulp-bower": "^0.0.4",
"gulp-open": "^0.2.8",
"coffeeify": "^0.6.0",
"browserify": "^3.41.0",
"deamdify": "^0.1.1",
"vinyl-source-stream": "^0.1.1",
"debowerify": "^0.7.0",
"uglifyify": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
}
Once copied and adapted to suit your needs, let NPM do its magic:
npm install
Create the build scripts
Actually as I've already blogged about it (A gulp of coffee: your gulpfile in coffeescript), I use a JS wrapper to call Gulp.js within CoffeeScript. It has the strong advantage to shorten yourGulpfile a lot. Here is the wrapper gulpufile.js:
'use strict';
require('coffee-script/register');
require('./gulpfile.coffee');
And now, the real build script
gulpfile.coffee:
'use strict'
gulp = require 'gulp'
gp = (require 'gulp-load-plugins') lazy: false
path = require 'path'
browserify = require 'browserify'
source = require 'vinyl-source-stream'
# HTML
gulp.task 'html', ->
gulp.src 'app/index.jade'
.pipe gp.plumber()
.pipe gp.jade locals: pageTitle: 'Famo.us built with Gulp'
.pipe gulp.dest 'www'
# JS
gulp.task 'js', ->
browserify
entries: ['./app/js/main.coffee']
extensions: ['.coffee', '.js']
.transform 'coffeeify'
.transform 'deamdify'
.transform 'debowerify'
.transform 'uglifyify'
.bundle()
# Pass desired file name to browserify with vinyl
.pipe source 'main.js'
# Start piping stream to tasks!
.pipe gulp.dest 'www/js'
# CSS
gulp.task 'css', ->
gulp.src 'app/css/*.sass'
.pipe gp.plumber()
.pipe gp.rubySass style: 'compressed', loadPath: ['bower_components', '.']
.pipe gp.cssmin keepSpecialComments: 0
.pipe gp.autoprefixer 'last 1 version'
.pipe gulp.dest 'www/css'
# Images
gulp.task 'img', ->
gulp.src ['app/img/*.jpg', 'app/img/*.png']
.pipe gp.cache gp.imagemin
optimizationLevel: 3
progressive: true
interlaced: true
.pipe gulp.dest 'www/img'
# Clean
gulp.task 'clean', ->
gulp.src ['www', 'tmp'], read: false
.pipe gp.clean force: true
# Build
gulp.task 'build', ['html', 'js', 'css']
# Default task
gulp.task 'default', ['clean'], -> gulp.start 'build'
# Connect
gulp.task 'connect', ['default'], ->
gp.connect.server
root: 'www'
port: 9000
livereload: true
# Watch
gulp.task 'watch', ['connect'], ->
gulp.watch 'app/**/*', read:false, (event) ->
ext = path.extname event.path
taskname = null
reloadasset = null
switch ext
when '.jade'
taskname = 'html'
reloadasset = 'www/index.html'
when '.sass'
taskname = 'css'
reloadasset = 'www/css/main.css'
when '.coffee', '.js'
taskname = 'js'
reloadasset = 'www/js/main.js'
else
taskname = 'img'
reloadasset = "www/img/#{path.basename event.path}"
gulp.task 'reload', [taskname], ->
gulp.src reloadasset
.pipe gp.connect.reload()
gulp.start 'reload'
Now we are ready to code!
Theapp/index.jade, a Jade file that produces our www/index.html, is really kept as its minimum:
doctype html
html(lang="en")
head
meta(charset="UTF-8")
title= pageTitle
meta(name="viewport", content="width=device-width, maximum-scale=1, user-scalable=no")
meta(name="mobile-web-app-capable", content="yes")
meta(name="apple-mobile-web-app-capable", content="yes")
meta(name="apple-mobile-web-app-status-bar-style", content="black")
link(rel="stylesheet", href="css/main.css")
body
script(src="js/main.js")
It's Famo.us that will populate the DOM.
Now, just to reset our CSS and gives a nice clean look to our little app, here is the content of our app/css/main.sass, a Sass file that produces our
www/css/main.css:
// From this gist: https://gist.github.com/trey/3524 html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video margin: 0 padding: 0 border: 0 font-size: 100% font: inherit vertical-align: baseline article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section display: block body line-height: 1 ol, ul list-style: none blockquote, q quotes: none blockquote:before, blockquote:after, q:before, q:after content: '' content: none table border-collapse: collapse border-spacing: 0 // Import Famo.us's CSS @import bower_components/famous/core/famous.css // Real theming happens hereafter $bgColor: #FF851B $mainColor: white html, body, .bgColor background-color: $bgColor body color: $mainColor font-family: Helvetica, Arial, sans-serif
Now comes the real fun. Our
app/js/main.coffee, a CoffeeScript that produces the www/js/main.js single file is where are required all the dependencies. If you plan on splitting your app into multiple files or importing new Famo.us components or installing new dependencies thanks to Bower, Browserify will do all the heavy lifting importing and building everything into a single file. So, here is simple hello world in regular CoffeeScript:
Engine = require 'famous/core/Engine'
Surface = require 'famous/core/Surface'
Modifier = require 'famous/core/Modifier'
# Create the main context
mainContext = Engine.createContext()
outline = new Surface
size: [200, 200]
content: 'Hello world in Famo.us'
classes: ['bgColor']
properties:
lineHeight: '200px'
textAlign: 'center'
outlineModifier = new Modifier
origin: [0.5, 0.5]
mainContext
.add outlineModifier
.add outline
If you haven't installed Gulp.js and CoffeeScript yet, install them globally:
npm -g install gulp coffee-script
It is now time to check our little hello world in Famo.us. Hit the next command:
gulp watch
Now, open your favorite browser at http://localhost:9000.As our
Gulpfile is loaded with Livereload, you can edit the source code live and see all the magic brought to us thanks to Famo.us. You can even open this app with your tablet or smartphone. It works like a charm.Conclusion
Famo.us brings a new interesting way of creating rich HTML5 apps that are almost as fast as native development without the burdens of redeveloping everything on each platform.Though, with this new shift in code design, we have some old constraints that arise again. SEO, for instance. Rethinking RWD is another one. Still with this powerful framework in our hands, it is easy to figure out how. Solving this little issues is not a big deal when compared to the huge problems that Famo.us has solved.
15 févr. 2014
Keep your Gulpfile manageable: the Gulp plugins you need to know
CoffeeScript as your Gulpfile
Though being less in the hype today, CoffeeScript shortens the need of writing boilerplate codes (as already detailed in this post A gulp of coffee: your gulpfile in coffeescript). All you need to do is to follow these simple steps:- Start by installing CoffeeScript globally:
npm -g install coffee-script
- Create a regular
Gulpfile.jsthat bootstraps Gulp into using CoffeeScript:require('coffee-script/register'); // This bootstraps your Gulp's main file require('./Gulpfile.coffee'); - Now, you simply edit your
Gulpfile.coffeeand forget about most of the semicolon, accolades, parenthesis, ...
Load plugins, automatic loading of your plugins
Like MatchDep or grunt-load-tasks do it for NodeJS and Grunt, gulp-load-plugins leverages yourpackage.json and automatically loads all the plugins in Gulp. Here are the steps to follow:- Start by creating a regular
package.jsonfor your project:npm init
- Add locally all your required plugins and save their installation as a development dependency. Here is an example for gulp-clean:
npm install --save-dev gulp-clean
- At the very beginning of your
Gulpfile.coffee, load Gulp and every plugins in two lines of code:gulp = require 'gulp' gp = do require 'gulp-load-plugins' # Load all gulp plugins
- Now all your plugins are loaded and accessible from the
gpobject. Their name matches the plugins name in camel case. Putting it more simply, for the plugin gulp-clean, you use it asgp.clean, for the plugin gulp-ruby-sass, you use is asgp.rubySass.
Plumber, avoid restarting Gulp when transpiling fails
When you start your watch and transpile tasks for the first time, it happens that syntax errors abruptly ends Gulp. It forces you to go the old way, fixing the bugs, re-launching Gulp, fixing the bugs, re-launching Gulp, ... tedious, to say the least.gulp-plumber avoids the stream to end upon error. Thus, whenever you need a transpilation, you just add gulp-plumber to your pipes. Here is a simple example that shows up how to use it.
gulp.task 'css', ->
gulp.src 'app/css/index.sass'
.pipe gp.watch()
.pipe gp.plumber() # Add Plumber just before the transpilation
.pipe gp.rubySass()
.pipe gulp.dest 'www/css'
Installing is made easy thanks to the automatic loading of plugins as described in the previous paragraph:npm install --save-dev gulp-plumber
Connect, start a livereload server, open your file and a create a static server in one plugin
This plugin gulp-connect is incredibly powerful: it combines a connect server with a tiny-lr one and it opens your transpiled files. Pure voodoo style. Here is short example of its basic usage:path = require 'path' # Start a webserver for static files gulp.task 'webserver', gp.connect.server root: path.join __dirname, 'www' port: 9000 livereload: true open: browser: 'Google Chrome'Just like before, the installation is easy as pie:
npm install --save-dev gulp-connectNow, on each watch task requiring a livereload, just add a
gp.connect.reload() call to their task.Note : BrowserSync is also a very good alternative.
Autoprefixer, forget about vendor's prefixes
Wether you use pure CSS, Less, Stylus or Sass and its compagnon Compass, you have to take care of vendor prefixes depending on the public your website or hybrid app are targeting. Doing it manually is a pure madness. But using some libraries assistance may also ends up in a tedious work, piling up a bunch of libraries that you need to add or remove depending on public adoption of next generation of operating systems and browsers.Autoprefixer does this automatically for you. It leverages the usage statistics Caniuse (by the way, an incredible and so useful website) and adds to your CSS just the prefix that it requires. A life time saver. Using it in Gulp is incredibly easy. Here is a simple example that takes Sass as its input and produces the CSS for 99% of browsers:
# Create CSS from SASS
gulp.task 'css', ->
gulp.src 'app/css/index.sass'
.pipe gp.watch()
.pipe gp.plumber()
.pipe gp.rubySass()
.pipe gp.autoprefixer "> 1%" # Set Autoprefixer for 99%
.pipe gulp.dest 'www/css'
A complete sample
To complete this article, here is one of theGulpfile.coffee that I've used on a production website (a very basic SPA):
gulp = require 'gulp'
# Load all gulp plugins
gp = do require 'gulp-load-plugins'
path = require 'path'
# Start a webserver for static files
gulp.task 'webserver', gp.connect.server
root: path.join __dirname, 'www'
port: 9000
livereload: true
open: browser: 'Google Chrome'
# Create CSS from SASS
gulp.task 'css', ->
gulp.src 'app/css/index.sass'
.pipe gp.watch()
.pipe gp.plumber()
.pipe gp.rubySass()
.pipe gp.autoprefixer "> 1%"
.pipe gp.cssmin keepSpecialComments: 0
.pipe gulp.dest 'www/css'
.pipe gp.connect.reload()
# Create HTML from Jade
gulp.task 'html', ->
gulp.src 'app/index.jade'
.pipe gp.watch()
.pipe gp.plumber()
.pipe gp.jade()
.pipe gulp.dest 'www'
.pipe gp.connect.reload()
# Copy font files
gulp.task 'copy_fonts', ->
gulp.src './bower_components/font-awesome/fonts/*'
.pipe gulp.dest 'www/fonts'
# Copy vendor JS files, concatenate them and uglify them
gulp.task 'copy_js', ->
gulp.src [
'bower_components/better-dom/dist/better-dom.js'
'bower_components/better-details-polyfill/dist/better-details-polyfill.js']
.pipe gp.concat 'better-dom-and-plugin.js'
.pipe gp.uglify()
.pipe gulp.dest 'www/js'
# Copy vendor CSS files and minifies it
gulp.task 'copy_css', ->
gulp.src [
'bower_components/better-details-polyfill/dist/better-details-polyfill.css']
.pipe gp.cssmin keepSpecialComments: 0
.pipe gulp.dest 'www/css'
# Clean produced files
gulp.task 'clean', ->
gulp.src ['www', 'tmp']
.pipe gp.clean()
gulp.task 'default', [
'copy_fonts', 'copy_js', 'copy_css'
'css', 'html', 'webserver']
And here are the relevant part of its package.json:
{
"name": "Blablabla",
"version": "0.0.0",
"description": "",
"main": "Gulpfile.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Me",
"license": "MIT",
"devDependencies": {
"gulp-cssmin": "~0.1.0",
"gulp-ruby-sass": "~0.3.0",
"gulp-util": "~2.2.14",
"gulp-autoprefixer": "0.0.6",
"gulp": "~3.5.2",
"gulp-jade": "~0.4.1",
"gulp-watch": "~0.5.0",
"gulp-sass": "~0.6.0",
"gulp-plumber": "~0.5.6",
"gulp-clean": "~0.2.4",
"gulp-load-plugins": "~0.3.0",
"gulp-concat": "~2.1.7",
"gulp-uglify": "~0.2.1",
"gulp-connect": "~0.3.1"
}
}
9 févr. 2014
A gulp of coffee: your gulpfile in coffeescript
Pros and cons
Gulp is a new buildsystem for the web. It contrasts with Grunt by leveraging NodeJS's streams. Therefore, it writes no temporary file on your drive when you're performing multiple operations on your assets. Of course, it speeds up the build process, but it is not the only advantage. Thanks to the streams, when you write your tasks, it feels more like you are describing the required workflow. For me, it is much more natural.The main drawback that I've found is its inability to directly use CoffeeScript as its main file. Streams and their piping abilities produce a ton of parenthesis obfuscating the semantic of your development with unnecessary grammar and syntax requirements.
Regaining access to CoffeeScript
Like Grunt, Gulp expect a main file namedGulpfile.js. We will use this file to bootstrap CoffeeScript and, thus, regain access to a more friendly language. Of course, the same trick could be applied to other languages such as Dart or TypeScript.Gulpfile.js
// Note the new way of requesting CoffeeScript since 1.7.x
require('coffee-script/register');
// This bootstraps your Gulp's main file
require('./Gulpfile.coffee');
That's it.
Now, just an example that demonstrates the achieved advantage, and also, the new parenthesis free chaining of CoffeeScript 1.7. The following script transpiles Jade, minifies it, compresses your SVG, transpiles your Sass, autoprefix it and minifies it, copies the fonts used in your Sass files.
Gulpfile.coffee
# Load all required libraries.
gulp = require 'gulp'
sass = require 'gulp-ruby-sass'
prefix = require 'gulp-autoprefixer'
cssmin = require 'gulp-cssmin'
jade = require 'gulp-jade'
minifyHTML = require 'gulp-minify-html'
svgmin = require 'gulp-svgmin'
# Create your CSS from Sass, Autoprexif it to target 99%
# of web browsers, minifies it.
gulp.task 'css', ->
gulp.src 'app/css/index.sass'
.pipe sass()
.pipe prefix "> 1%"
.pipe cssmin keepSpecialComments: 0
.pipe gulp.dest 'www/css'
# Create you HTML from Jade, Adds an additional step of
# minification for filters (like markdown) that are not
# minified by Jade.
gulp.task 'html', ->
gulp.src 'app/index.jade'
.pipe jade()
.pipe minifyHTML()
.pipe gulp.dest 'www'
# Minify your SVG.
gulp.task 'svg', ->
gulp.src 'app/img/*.svg'
.pipe svgmin()
.pipe gulp.dest 'www/img'
# Copy the fonts using streams.
gulp.task 'copy', ->
gulp.src 'app/fonts/*'
.pipe gulp.dest 'www/fonts'
# Default task call every tasks created so far.
gulp.task 'default', ['css', 'html', 'svg', 'copy']
Inscription à :
Articles (Atom)
