in-a-gulp
A good starting point for creating a static web application.
Requirements
npm install -g gulp bower
Installing bower is not required, but is heavily suggested.
How to
To fire up your project just move into the source
directory and run gulp
(or check out the full Commands Reference).
The example project will get compiled and a browser window should open with your project.
In the source
directory you'll find several directories:
templates
: Handlebars templates for your viewsdata
: JSON data containing the data you want to display with your templatescontents
: toml files containing your localized stringsimages
: Images needed by your applicationstylesheets
: sass stylesheets used to define the look of your applicationscripts
: JavaScript files to embed in your applicationgulpfile
: The script which make everything automatic (that you shouldn't touch)
By editing and creating files inside these directory you'll be able to create a web application in an efficient way.
Templates
It's a good practice to separate your data from your design. That's why in-a-gulp includes Handlebars templates to generate your HTML.
Including partials is supported from the partials
and layouts
directories - and we're supporting layouts through handlebars-layouts.
One more thing: We don't want your beautifully crafted website to have ugly ".html" URL.
in-a-gulp will only generate index.html
for index.hbs
files (at any depth) in your /templates
directory.
templates/layouts/main.hbs
<html>
<head></head>
<body>
{{> header}}
<div>
{{#block "body"}}{{/block}}
</div>
{{> footer}}
</body>
</html>
templates/partials/header.hbs
Footer
templates/partials/footer.hbs
Header
templates/index.hbs
{{#extend "main"}}
{{#content "body"}}
Hello World
{{/content}}
{{/extend}}
Data
To define data you simply create a index.json
file on the same path of your template file in /data
.
Data is language agnostic.
data/index.json
{
"object": "Framp"
}
templates/index.hbs
{{#extend "main"}}
{{#content "body"}}
Hello {{object}}
{{/content}}
{{/extend}}
Contents
To define contents in different languages you simply create a index.toml
file on the same path of your template file in /contents/ln-LN/
, where ln-LN
is the country-language choice of your language.
The default language, will be generated in the root of the destination folder. All the other languages will live in /ln-LN
subdirectories.
The default language is the one whose directory in /contents
starts with a _
.
If you need to provide translations which are common in different pages you can simply insert them in the /contents/ln-LN/partials.toml
file: it will be used in all your pages.
You'll be able to use your strings in templates using the handlebars-tr plugin. Your translations will have access to the whole context, letting you use variables in them.
data/index.json
{
"object": "Framp"
}
contents/_en-US/index.json
greeting = "Hello {{object}}"
contents/it-IT/index.json
greeting = "Ciao {{object}}"
templates/index.hbs
{{#extend "main"}}
{{#content "body"}}
{{tr "greeting"}}
{{/content}}
{{/extend}}
This small example will generate $dest/index.html
in en-US
and $dest/it-IT/index.html
in it-IT
.
We chose toml over JSON for language files because it's easier to use for such a flat structure.
Images
All the images you put inside will be copied to $dest/images
.
In production mode we'll copy an optimized image with a version number suffix, so that browsers won't have cache problems. The end result will be /images/image.v1.png
.
Stylesheets
Thanks to sass your stylesheets will have a nice readable structure. Screw the 5k LOC '.css`!
Only index.scss
files (at any depth, in every subdirectory) will be parsed and used to generate corrisponding index.css
files.
In production mode we'll generate an optimized and autoprefixed file in index.v1.min.css
.
Our suggestion is to leverage the modularity of sass and use the index.scss
file only for @import
of well named sass
modules.
If you need to import modules form thirdy-party you can install them using bower:
bower install --save meyer-reset
And @import
them directly:
index.scss
@import 'meyer-reset/stylesheets/meyer-reset';
@import 'colors';
@import 'general';
@import 'menu';
@import 'homepage';
This is working only because bower_components
is one of the includedPaths
used by libsass
when looking for a file.
Scripts
Say goodbye to spaghetti-code! in-a-gulp relies on browserify to help you organize your code following CommonJS syntax.
Like in all the other modules, only your index.js
files, at any depth, will be used to generate files. We suggest you to use your index.js
files only for importing other scripts.
index.js
require('./core');
require('./routes');
Again, feel free to install packages from bower (even the ones who are using AMD).
bower install --save jquery
And use them freely:
var $ = require('jquery');
$(document).ready(function(){
$(document.body).css('background', '#ff6699');
});
Gulpfile
in-a-gulp is, obviously, using gulp, the awesome streaming build system.
The gulpfile.js
is used to generate your application and work with it. If everything suits your taste you don't have to touch anything.
We believe that if you want to customize more your workflow, you should be able to do it.
The main gulpfile only defines the main commands you can run with in-a-gulp, delegating the bulk of the work to scripts contained in the gulpfile
directory.
templates.js
We load the languages from /contents
and create a gulp stream for each language and setup handlebars and its helpers. Feel free to throw in more helpers if you need to.
For each stream we load data and contents with gulp-data and pipe everything to gulp-handlebars-html.
images.js
This one is easy: we just use imagemin to compress our images.
stylesheets.js
We're just using gulp-sass, gulp-autoprefixer and gulp-minify-css.
scripts.js
We use gulp-browserify with the bowerify and the deamdify transforms.
We compress everything using gulp-uglify.
misc.js
The tasks in misc are used to:
- increase the
version
and force the productionenvironment
- setup the livereload server thanks to gulp-connect
- open a browser window with your project thanks to gulp-open
A note on debug
We use gulp-debug together with gulp-if to help you debug your building process only when you want to.
A note on cache and remember
We use gulp-cached and gulp-remember to reduce the amount of unneeded work done when rebuilding files.
Unfortunately this is not always trivial and we, currently, can't use that when a task has external untracked dependencies (eg. a file which includes other files and which needs to be recreated when one of its dependencies update).
A note on clean tasks
The clean tasks should be straightforward. We do roughly the same thing as the process-
task while stripping all the gulp plugins who actually do something to the file contents. After gulp.dest
we use vinyl-paths to retrieve our paths and just pass them to fs.unlink
.
Commands Reference
gulp
: build the application in development mode and launch a livereload servergulp deploy
:clean-all
and build the application in production mode and increment theversion
of the application (theversion
is used only in when deploying)gulp clean-all
: call all theclean-*
tasks and clean all the filesgulp process-all
: call all theprocess-*
tasks and build all the files neededgulp process-templates
: build .html files from your .hbs templatesgulp process-images
: optimize images filesgulp process-stylesheets
: build .css files from your .scss stylesheetsgulp process-scripts
: build .js files from your scriptsgulp clean-templates
: clean templates generated withprocess-templats
gulp clean-images
: clean images generated withprocess-imags
gulp clean-stylesheets
: clean stylesheets generated withprocess-stylesheets
gulp clean-scripts
: clean scripts generated withprocess-scripts
Passing parameters to gulp can be done to override some of the default values:
--dest=..
will override the destination in which your file are generated--version=0
will override theversion
--debug=false
will display debugging information about your building process--environment=development
will override your environment (which isproduction
when you're deploying ordevelopment
when running all the other commands)NODE_ENV=production gulp...
is just another way to set the environment
Why did you bother writing all these little pesky details?
I strongly feel like one of the major issues in nowadays frameworks is communication.
Several frameworks abstract a lot of what they do without documenting stuff clearly enough; the result is a magic box users simply use without understanding. And no, they won't be happy after finding a bug and understanding they have no idea what the hell is happening.
The solution is transparency.
License
MIT