diff --git a/README.md b/README.md index fbc278d..61bed69 100644 --- a/README.md +++ b/README.md @@ -1,157 +1,61 @@ Configurable assets builder =========================== -A collection of configurable [gulp](http://gulpjs.com/) tasks we use to build front-end code, mostly for fully static or CMS-based website projects. +A collection of configurable [gulp](http://gulpjs.com/) tasks we use to build front-end code, mostly for fully static or CMS-based website projects, using [gulp-task-maker](https://www.npmjs.com/package/gulp-task-maker). -- Flexible configuration -- Useful logs and system alerts -- Use the built-in tasks (Sass with Autoprefixer, SVG sprites, and simple JS minification) or write your own +## Task list -*Table of contents:* +- [less](gulp-tasks/less.md): compile Less stylesheets +- [mincss](gulp-tasks/mincss.md): concatenate and minify CSS +- [minjs](gulp-tasks/minjs.md): concatenate and minify JS code +- [sass](gulp-tasks/sass.md): compile Sass stylesheets +- [svgsymbols](gulp-tasks/svgsymbols.md): build SVG symbol sprites -- [Installation and usage](#installation-and-usage) -- [Using tasks](#using-tasks) -- [Enable system notifications](#enable-system-notifications) -- Built-in tasks: - - [less](doc/task-less.md) (Less and Autoprefixer) - - [sass](doc/task-sass.md) (Sass and Autoprefixer) - - [svgsymbols](doc/task-svgsymbols.md) (SVG symbol sprites) - - [jsconcat](doc/task-jsconcat.md) (Concatenate and minify JS scripts) -- [Multiple builds per task](#multiple-builds-per-task) -- [How to write a new task](#how-to-write-a-new-task) +## Example installation - -Installation and usage ----------------------- - -Requirements: [Node.js](https://nodejs.org) 4.x or above - -Installing: +⚠ Requires Node.js 4 or later. 1. [Download a ZIP with the assets-builder scripts and config](https://github.com/gradientz/assets-builder/archive/master.zip) and unzip it in your projet directory. -3. Change the config object in `gulpfile.js`. +3. Change the main config in `gulpfile.js`. 4. Finally, in a command prompt, go to your project dir and run: `npm install` -Usage: +## Usage - `npm run build`: build assets once - `npm run watch`: run in the background and build assets when source files are changed +The first time you try to run a task, e.g. with `npm run build`, you might see an error that looks like this: -Using tasks ------------ - -To use one of the built-in tasks, you will need to do two things: 1) Configure the task and 2) Install its dependencies (if any). +``` +[13:37:21] [gulp-task-maker] Errors in 'sass', 'minjs', 'svgsymbols' + … + Install missing task dependencies with: + npm install -D "gulp-autoprefixer@^3.1" "gulp-sass@^2.3" "gulp-uglify@^2.0" "gulp-svgmin@^1.2" "gulp-svg-symbols@^2.0" -### Task configuration - -Configuration goes in your `gulpfile.js` and generally looks like this: - -```js -require('./assets-builder')({ - taskname: { - src: ['some/files/to/use/*.*', 'some/other/files/*.*'], - dest: 'where/to/write/the/result', - watch: true // will watch the 'src' files - } -}) ``` -The `src`, `dest` and `watch` keys are common to all tasks. Some tasks may offer other options too. For the built-in tasks, those options are documented in [the doc folder](doc). +This is because task dependencies are not installed by default, but documented in the task’s `.json` file. This allows us to maintain as many tasks as we want in this repo, but not install dependencies we don’t use. -### Installing dependencies - -Task dependencies are *not* installed by default. The first time you try to run a task, with `npm run build`, you might see an error like this: +Run the provided command (`npm install -D …`), then run `npm run build` again. You should see something like this: ``` -[21:28:37] Error: missing dependencies for 'sass', 'jsconcat', 'svgsymbols' - - To fix this, install missing dependencies: - - npm install -D "gulp-autoprefixer@^3.1" \ - "gulp-sass@^2.3" \ - "gulp-uglify@^1.5" \ - "gulp-svgmin@^1.2.3" \ - "gulp-svg-symbols@^2.0.2" - -``` - -You can run the provided command to install the missing dependencies. Then run `npm run build` again. - - -Enable system notifications ---------------------------- - -To enable system notifications, install the `node-notifier` package: - -- Locally to the project: `npm install node-notifier` -- Globally on your OS: `npm install -g node-notifier` - -You could also add it to the `devDependencies` (`npm install -D node-notifier`), but that’s not ideal if you want to put this code as a build step on a server. - - -Multiple builds per task ------------------------- - -Each task can accept an array of config objects: - -```js -{ - sass: [ - { - src: 'assets/styles/main.scss', - watch: 'assets/styles/**/*.scss', - dest: 'public/css', - browsers: ['last 3 versions', 'ie >= 11'] - }, - { - src: 'assets/styles/other.scss', - dest: 'public/css', - browsers: ['last 3 versions', 'ie >= 11'], - outputStyle: 'compact' - }, - ] -} -``` - -You can also share settings between objects, with an array-like syntax. This is equivalent to the previous example: - -```js -{ - sass: { - // base settings - dest: 'public/css', - browsers: ['last 3 versions', 'ie >= 11'], - // builds with specific settings - 0: { src: 'assets/styles/main.scss', watch: 'assets/styles/**/*.scss' }, - 1: { src: 'assets/styles/other.scss', outputStyle: 'compact' } - } -} -``` - - -How to write a new task ------------------------ - -Write your own task script in `assets-builder/tasks`. This script should export a function that accepts a config object. - -### Minimal task example - -```js -/** - * assets-builder/tasks/mytask.js - */ - -const gulp = require('gulp') -const tools = require('../tasktools.js') -const doSomething = require('gulp-do-something') - -module.exports = function mytaskBuilder(conf) { - return gulp.src(conf.src) // take some files - .pipe(tools.errors()) // tell gulp to show errors and continue - .pipe(doSomething()) // use a gulp plugin to transform content - .pipe(tools.size(conf.dest)) // log resulting file path/names and size - .pipe(gulp.dest(conf.dest)) // write resulting files to destination -} +$ npm run build + +> assets-builder@4.0.0 build ~/assets-builder +> gulp build + +[13:38:12] Using gulpfile ~/assets-builder/gulpfile.js +[13:38:12] Starting 'build-sass'... +[13:38:12] Starting 'build-minjs'... +[13:38:12] Starting 'build-svgsymbols'... +[13:38:14] ./test/dist/ minjs.js 88.59 kB +[13:38:14] ./test/dist/ sass.css 406 B +[13:38:14] Finished 'build-minjs' after 2.33 s +[13:38:14] ./test/dist/ svgsymbols.svg 9.31 kB +[13:38:14] ./test/dist/ svgsymbols.svg.html 30.6 kB +[13:38:14] Finished 'build-sass' after 2.37 s +[13:38:14] Finished 'build-svgsymbols' after 2.34 s +[13:38:14] Starting 'build'... +[13:38:14] Finished 'build' after 6.65 μs ``` diff --git a/gulp-tasks/less.md b/gulp-tasks/less.md index 4307106..9339ba7 100644 --- a/gulp-tasks/less.md +++ b/gulp-tasks/less.md @@ -1,31 +1,49 @@ -# Task: compile Less with Autoprefixer +# Task: compile Less stylesheets -- Config key: `less` -- Source: `assets-builder/tasks/less.js` +## Features -Compile with Less and run through Autoprefixer. Optionally concatenates files. +- Compile Less +- Concatenate files +- Autoprefixer support +- Sourcemaps support +- Minify with csso ## Options ```js -{ - // (Required) Source can be a single Sass stylesheet +require('gulp-task-maker').task('gulp-tasks/less.js', { + // (Required) Source can be a single Less or CSS stylesheet // or pattern, or an array of paths or patterns src: 'assets/styles/*.less', // (Required) Destination can be a folder name, or a filename ending in '.css'. - // The main difference is when building more than one Sass stylesheet. + // The main difference is when building more than one Less stylesheet. // - Filename ending in '.css': the result will be concatenated // - Otherwise: original filenames are used, and put in the destination folder. dest: 'public/css', - // (Optional) File patterns to watch for changes + // (Optional; defaults to false) + // File patterns to watch for changes watch: 'assets/styles/**/*.less', - // (Optional) Autoprefixer: target browsers - browsers: ['last 3 versions'], + // (Optional; defaults to true) + // Should we minify with csso? + minify: true, - // (Optional) LESS include paths (for resolving @import) - includePaths: ['node_modules'] -} + // (Optional; defaults to '.'; false to disable) + // Where should we write sourcemaps (relative to 'dest') + sourcemaps: '.', + + // (Optional; defaults shown below) + // gulp-less options + less: { paths: ['.'] }, + + // (Optional; defaults shown below; false to disable) + // gulp-autoprefixer options + autoprefixer: { flexbox: 'no-2009', grid: false }, + + // (Optional; defaults shown below) + // gulp-csso options + csso: { restructure: false } +}) ``` diff --git a/gulp-tasks/mincss.md b/gulp-tasks/mincss.md new file mode 100644 index 0000000..a8c8933 --- /dev/null +++ b/gulp-tasks/mincss.md @@ -0,0 +1,44 @@ +# Task: concatenate and minify CSS + +## Features + +- Concatenate files +- Autoprefixer support +- Sourcemaps support +- Minify with csso + +## Options + +```js +require('gulp-task-maker').task('gulp-tasks/mincss.js', { + // (Required) Source can be a single stylesheet + // or pattern, or an array of paths or patterns + src: 'assets/styles/*.css', + + // (Required) Destination can be a folder name, or a filename ending in '.css'. + // The main difference is when building more than one stylesheet. + // - Filename ending in '.css': the result will be concatenated + // - Otherwise: original filenames are used, and put in the destination folder. + dest: 'public/css/main.css', + + // (Optional; defaults to false) + // File patterns to watch for changes + watch: true, + + // (Optional; defaults to true) + // Should we minify with csso? + minify: true, + + // (Optional; defaults to '.'; false to disable) + // Where should we write sourcemaps (relative to 'dest') + sourcemaps: '.', + + // (Optional; defaults shown below; false to disable) + // gulp-autoprefixer options + autoprefixer: { flexbox: 'no-2009', grid: false }, + + // (Optional; defaults shown below) + // gulp-csso options + csso: { restructure: false } +}) +``` diff --git a/gulp-tasks/minjs.md b/gulp-tasks/minjs.md index 5605a24..9e39977 100644 --- a/gulp-tasks/minjs.md +++ b/gulp-tasks/minjs.md @@ -1,27 +1,43 @@ -# Task: concatenate and minify JS scripts +# Task: concatenate and minify JS code -- Config key: `jsconcat` -- Source:: `assets-builder/tasks/jsconcat.js` +## Features -Lets you concatenate and minify JS code. Note that there is no support for wrapping code in IIFEs, or working with modules (see e.g. Browserify or Rollup for that). +- Concatenate files +- Sourcemaps support +- Minify with UglifyJS (warning: no ES6 support!) ## Options ```js -{ - // (Required) Source files. Like with other tasks, we can - // provide an array of paths instead of a single path. - src: [ 'assets/libs/hello.js', - 'assets/scripts/*.js' ], +require('gulp-task-maker').task('gulp-tasks/minjs.js', { + // (Required) Source can be a single script or pattern, + // or an array of paths or patterns + src: 'assets/scripts/*.js', - // (Required) Destination must be a file name - dest: 'public/js/main.js', + // (Required) Destination can be a folder name, or a filename ending in '.js'. + // The main difference is when building more than one script. + // - Filename ending in '.js': the result will be concatenated + // - Otherwise: original filenames are used, and put in the destination folder. + dest: 'public/css/main.js', - // (Optional) File patterns to watch for changes, or `true` - // to use the same value as the src property + // (Optional; defaults to false) + // File patterns to watch for changes watch: true, - // (Optional) Should we minify the result? Default is true. - minify: true -} + // (Optional; defaults to true) + // Should we minify with csso? + minify: true, + + // (Optional; defaults to '.'; false to disable) + // Where should we write sourcemaps (relative to 'dest') + sourcemaps: '.', + + // (Optional; defaults shown below) + // gulp-uglify options + uglifyjs: { + output: {inline_script: true}, + compress: {drop_debugger: false}, + preserveComments: 'license' + } +}) ``` diff --git a/gulp-tasks/sass.md b/gulp-tasks/sass.md index f979965..1654ff2 100644 --- a/gulp-tasks/sass.md +++ b/gulp-tasks/sass.md @@ -1,14 +1,17 @@ -# Task: compile Sass with Autoprefixer +# Task: compile Sass stylesheets -- Config key: `sass` -- Source: `assets-builder/tasks/sass.js` +## Features -Runs node-sass and autoprefixer. +- Compile Sass (`.scss` only) +- Concatenate files +- Autoprefixer support +- Sourcemaps support +- Minify with csso ## Options ```js -{ +require('gulp-task-maker').task('gulp-tasks/sass.js', { // (Required) Source can be a single Sass stylesheet // or pattern, or an array of paths or patterns src: 'assets/styles/*.scss', @@ -19,17 +22,28 @@ Runs node-sass and autoprefixer. // - Otherwise: original filenames are used, and put in the destination folder. dest: 'public/css', - // (Optional) File patterns to watch for changes - watch: 'assets/styles/**/*.scss', + // (Optional; defaults to false) + // File patterns to watch for changes + watch: 'assets/styles/**/*.less', - // (Optional) Autoprefixer: target browsers - browsers: ['last 3 versions'], + // (Optional; defaults to true) + // Should we minify with csso? + minify: true, - // (Optional) Sass output style - // Defaults to 'compressed', can also be: 'nested', 'expanded', 'compact' - outputStyle: 'compressed', + // (Optional; defaults to '.'; false to disable) + // Where should we write sourcemaps (relative to 'dest') + sourcemaps: '.', - // (Optional) Sass include paths (for resolving @import) - includePaths: ['node_modules'] -} + // (Optional; defaults shown below) + // gulp-sass options + sass: { outputStyle: 'compact', includePaths: ['.'] }, + + // (Optional; defaults shown below; false to disable) + // gulp-autoprefixer options + autoprefixer: { flexbox: 'no-2009', grid: false }, + + // (Optional; defaults shown below) + // gulp-csso options + csso: { restructure: false } +}) ``` diff --git a/gulp-tasks/svgsymbols.js b/gulp-tasks/svgsymbols.js index 741198d..1ed88ed 100755 --- a/gulp-tasks/svgsymbols.js +++ b/gulp-tasks/svgsymbols.js @@ -19,12 +19,12 @@ const symbols = require('gulp-svg-symbols') */ module.exports = function svgsymbolsBuilder(config, tools) { config = Object.assign({ - sourcemaps: false, + minify: true, demo: false, id: 'icon-%f', slug: file => file.toLowerCase().replace(/[^a-z0-9]/g,''), svgClassname: false - }, config) + }, config, { sourcemaps: false }) // rename files internally so we can use the simplified names in ids // (both in svgmin and gulp-svg-symbols) @@ -69,7 +69,7 @@ module.exports = function svgsymbolsBuilder(config, tools) { // Build sprite (+demo page) return tools.commonBuilder(config, [ renameInputTransform, - minifyTransform, + config.minify && minifyTransform, spriteTransform, renameOutputTransform ]) diff --git a/gulp-tasks/svgsymbols.md b/gulp-tasks/svgsymbols.md index ca7da95..9b45849 100644 --- a/gulp-tasks/svgsymbols.md +++ b/gulp-tasks/svgsymbols.md @@ -1,37 +1,47 @@ -# Task: SVG symbol sprites +# Task: build SVG symbol sprites -- Config key: `svgsymbols` -- Source: `assets-builder/tasks/svgsymbols.js` +## Features -Takes a bunch of SVG files and make a [SVG symbol sprite](https://fvsch.com/code/svg-icons/how-to/), to be used inline in your HTML pages or as an external resource. - -This task can also output a nice HTML demo page (see options). +- Takes individual SVG images and generates a symbol sprite +- Generates a HTML demo page for each sprite +- Minifies with svgo ## Options ```js -{ - // (Required) Source SVG images - src: 'assets/icons/main/*.svg', +require('gulp-task-maker').task('gulp-tasks/svgsymbols.js', { + // (Required) Source can be a single script or pattern, + // or an array of paths or patterns + src: 'assets/scripts/*.js', - // (Required) Destination must be a file name - dest: 'public/svg/main.svg', + // (Required) Destination must be a filename ending in '.svg'. + dest: 'public/css/main.svg', - // (Optional) File patterns to watch for changes, or `true` - // to use the same value as the src property + // (Optional; defaults to false) + // File patterns to watch for changes watch: true, - // (Optional) Output a HTML demo page alongside the sprite + // (Optional; defaults to true) + // Should we minify with svgo? + // Note: when disabling svgo, some features such as internal references may break + minify: true, + + // (Optional; defaults to the string shown below) + // Pattern for the symbol’s id attribute. + // '%f' is the cleaned-up original filename. + id: 'icon-%f', + + // (Optional; defaults to false) + // Should we make a HTML demo page? demo: false, - // (Optional) Add attributes for an inline sprite - inline: false, - - // (Optional) Pattern to use for symbol id attributes. '%f' is the - // original filename with only lowercase letters and digits. - symbolId: 'icon-%f', + // (Optional; defaults to false) + // Add a class name on the sprite's root element? + // Can be useful for sprites you want to directly include in a web page. + svgClassname: 'inline-sprite', - // (Optional) Class name(s) to use in HTML usage examples. - symbolClass: 'icon icon--%f' -} + // (Optional; defaults to the function shown below) + // Function that cleans up file names to be used in the symbol's id attribute + slug: file => file.toLowerCase().replace(/[^a-z0-9]/g,'') +}) ``` diff --git a/gulpfile.js b/gulpfile.js index cb63db3..d9f7aac 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,36 +1,18 @@ -'use strict' +'use strict'; /** * Configuration for assets-builder (https://github.com/gradientz/assets-builder), * based on gulp-task-maker (https://github.com/fvsch/gulp-task-maker) */ -const gtm = require('gulp-task-maker') +const gtm = require('gulp-task-maker'); gtm.conf({ - notify: true, // use system notifications for errors? (default: true) - strict: false // throw errors immediately? (default: false, shows errors at the end) -}) + notify: true, // use system notifications + strict: false // shows errors at the end, instead of throwing +}); gtm.load('gulp-tasks', { - // IMPORTANT: - // - // These are only example configs for each task, remove or change - // them to match your needs and your file structure. - // - // For the mincss, sass and less tasks, Autoprefixer will use - // the "browserslist" config in package.json - - mincss: { - src: [ - 'node_modules/normalize.css/normalize.css', - 'test/src/css/*.css' - ], - minify: true, // minify with csso? (default: true) - watch: true, // watch the 'src' files (default: false) - dest: 'test/dist/mincss.css' - }, - sass: { src: [ 'test/src/css/*.css', @@ -40,33 +22,21 @@ gtm.load('gulp-tasks', { dest: 'test/dist/sass.css' }, - less: { - src: [ - 'test/src/css/*.css', - 'test/src/less/test.less' - ], - watch: 'test/src/**/*.{css,less}', - dest: 'test/dist/less.css' - }, - minjs: { src: [ 'node_modules/jquery/dist/jquery.min.js', 'test/src/js/*.js' ], dest: 'test/dist/minjs.js', - watch: 'test/src/js/*.js', - minify: true + watch: 'test/src/js/*.js' }, - svgsymbols: [ - { - src: 'test/src/svg/*.svg', - dest: 'test/dist/svgsymbols.svg', - id: 'icon-%f', // id pattern for symbols, where '%f' is the cleaned up file name - svgClassname: 'inline-sprite', // add class to the root element - demo: true - } - ] + svgsymbols: { + src: 'test/src/svg/*.svg', + dest: 'test/dist/svgsymbols.svg', + id: 'icon-%f', // id pattern for symbols, where '%f' is the cleaned up file name + svgClassname: 'inline-sprite', // add class to the root element + demo: true + } -}) +});