Needlessly Postulating Minds

    samsao-blendid

    4.2.0 • Public • Published

    Blendid

    Build Status Stories in Ready

    Blendid (formerly known as Gulp Starter) is a delicious stand-alone blend of tasks and build tools poured into Gulp to form a full-featured modern asset pipeline. It can be used as-is as a static site builder, or can be configured and integrated into your own development environment and site or app structure.

    Quick start on a fresh project (empty directory)

    yarn init
    yarn add blendid
    yarn run blendid -- init
    yarn run blendid

    This will create default src and config files in your directory and start compiling and live-updating files! Try editing them and watch your browser auto-update!

    Using Craft? Replace line 3 above with:

    yarn run blendid -- init-craft

    Using Drupal 8? Replace line 3 above with:

    yarn run blendid -- init-drupal

    Using Rails? Replace line 3 above with:

    yarn run blendid -- init-rails

    These initializers will generate pre-configured blendid config files, helpers, and asset folder structure for the referenced platform. Pull requests welcome to add more!

    Adding to an existing project?

    You can generate just the base config files with:

    yarn run blendid -- init-config
    

    Then edit the configs to match the needs of your project.

    Recommended Setup

    Node Version Manager

    Blendid requires at least Node 6. While you can install Node a variety of ways, we highly recommend using nvm to install and manage Node versions.

    Yarn

    We recommend yarn over npm for a few reasons: yarn.lock files are a lifesaver, modules install way faster, and yarn run for running package.json scripts and node_modules/.bin executables is a nice convience. It's just better.

    Commands

    All commands should be run through yarn run. If you haven't switched to yarn yet, now's a great time!

    yarn run blendid

    This is where the magic happens. The perfect front-end workflow. This runs the development task, which starts compiling, watching, and live updating all our files as we change them. Browsersync will start a server on port 3000, or do whatever you've configured it to do. You'll be able to see live changes in all connected browsers. Don't forget about the additional Browsersync UI tools available on port 3001!

    yarn run blendid -- build

    Compiles files for production to your destination directory. JS files are built with webpack 3 with standard production optimizations (uglfiy, etc.). CSS is run through CSSNano. If rev is set to true in your task-config.js file, filenames will be hashed (file.css -> file-a8908d9io20.css) so your server may cache them indefinitely. A rev-manifest.json file is output to the root of your dest directory (public by default), and maps original filenames to hashed ones. Helpers exist for Rails and Craft that read this file and automatically update filenames in your apps. CSS and HTML files read this file and string-replace filenames automatically.

    yarn run blendid -- ghPages

    If you are building a static site, and would like to preview it on GitHub pages, this handy script does just that using gulp-gh-pages. Be sure to add or update the homepage property in your package.json to point to your gh-pages url.

    It's a good idea to add aliases for these commands to your package.json scripts object.

    // package.json
      "scripts": {
        "start": "yarn run blendid",
        "build": "yarn run blendid -- build"
      }
    
    // Command line
    yarn start
    yarn run build
    

    Configuration

    You may override the default configuration by creating a config folder with the following two files in it: path-config.json and task-config.js. These files will be created by any of the -- init tasks, or you can generate only the config files with the following command:

    yarn run blendid -- init-config
    

    By default, Blendid expects these files to live in a ./config a the root of your project. You may specify an alternative relative location by setting an environment variable:

    // package.json
    "scripts": {
      "blendid": "BLENDID_CONFIG_PATH='./some/location' blendid"
    }
    
    // command line
    yarn run blendid
    

    The files must be named path-config.json and task-config.js.

    Configuring file structure

    path-config.json

    File structure is configued through a config/path-config.json file. This file is JSON so that other platforms like Ruby or PHP can easily read it in and use it to build asset path helpers for replacing hashed filenames in production.

    This file specifies the src and dest root directories, and src and dest for each task, relative to the configured root.

    A minimal setup might look someting like this:

    {
      "src": "./src",
      "dest": "./public",
    
      "javascripts": {
        "src": "javascripts",
        "dest": "javascripts"
      },
    
      "stylesheets": {
        "src": "stylesheets",
        "dest": "stylesheets"
      },
    
      "images": {
        "src": "images",
        "dest": "images"
      }
    }

    That's saying that your source files live at ./src, and the root of where you want your files to be output is at ./public. So for example, ./src/stylesheets/app.scss would get compiled to ./public/stylesheets/app.css.

    Configuring tasks

    task-config.js

    Specific task configuration is done through a config/task-config.js file. Depending on your project and platform, you may want to disable some tasks, or customize others. This file exposes per-task configuration and overrides. At minimum, you just need to set the task to true to enable the task with its default configuration. If you wish to configure a task, provide a configuation object instead.

    A minimal setup might look someting like this:

    module.exports = {
      html        : false,
      fonts       : false,
      static      : false,
      svgSprite   : false,
      ghPages     : false,
    
      images      : true,
      stylesheets : true,
    
      javascripts: {
        entry: {
          // files paths are relative to
          // javascripts.dest in path-config.json
          app: ["./app.js"]
        }
      },
    
      browserSync: {
        server: {
          // should match `dest` in
          // path-config.json
          baseDir: 'public'
        }
      }
    }
    • Any task may be disabled by setting the value to false. For example, if your project has its own handling HTML and templating (Rails, Craft, Django, etc), you'll want to set html to false in your task-config.
    • All asset tasks have an extensions option that can be used to overwrite the that are processed and watched.
    • The html and stylesheets tasks may be replaced via their alternateTask options

    See task config defaults for a closer look. All configuration objects will be merged with these defaults. Note that array options are replaced rather than merged or concatinated.

    browserSync (required)

    Options to pass to Browsersync.

    If you're using Nunjucks (built in) to compile a static site, you'll want to use the server and tell it which server to serve up via the baseDir option.

    browserSync: {
      server: {
        baseDir: "public"
      }
    }

    If you're running your own server, you'll want to use the proxy option, along with files to tell browserSync to watch additional files (like your templates).

    browserSync: {
      proxy: {
        target: "my-rails-project.dev:3000"
      },
      files: ["app/views"]
    }

    If you need to turn on polling within webpack-dev-middleware, specify watchOptions within this section, too.

    browserSync: {
      watchOptions: {
        poll: true,
        aggregateTimeout: 300
      }
    }

    javascripts

    Under the hood, JS is compiled with webpack 3 with a heavily customized webpack file to get you up and running with little to no configuration. An API for configuring some of the most commonly accessed options are exposed, along with some other helpers for scoping to environment. Additionally, you can get full access to modify Blendid's webpackConfig via the customizeWebpackConfig option.

    entry (required)

    Discrete js bundle entry points. A js file will be bundled for each item. Paths are relative to the javascripts folder. This maps directly to webpackConfig.entry.

    publicPath

    The public path to your assets on your server. Only needed if this differs from the result of path.join(PATH_CONFIG.dest, PATH_CONFIG.javascripts.dest). Maps directly to webpackConfig.publicPath

    devtool

    Sets the webpack devtool option in development mode. Defaults to eval-cheap-module-source-map, one of the fastest source map options. To enable sourcemaps in production builds, use customizeWebpackConfig](#customizeWebpackConfig).

    babel

    Object to overwrite the default Babel loader config object. This defaults to { presets: [["es2015", { "modules": false }], 'stage-1'] }. Same format as a .babelrc file. See #380.

    babelLoader

    Object to extend the default config for entire Babel loader object. See webpack loader documentation for details.

    provide

    Key value list of variables that should be provided for modules to resolve dependencies on import using webpack.ProvidePlugin. A common example is making jQuery available to all modules (jQuery plugins need this). In that scenario, with jquery installed via yarn, add this to your javascripts config:

    provide: {
      $: "jquery",
      jQuery: "jquery"
    }

    Under the hood, this gets passed directly to webpack.ProvidePlugin in the webpack config.

    plugins: [
      new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery"
      })
    ]

    plugins

    Define additional webpack plugins that should be used in all environments

    loaders

    Define additional webpack loaders that should be used in all environments. Adds to webpackConfig.module.rules

    development, production

    Specify additional environment specific configuration to be merged in with Blendid's defaults

    Production Only:

    Note that if devtool is set in production, Blendid will automaticallyset to uglifyJsPlugin.sourceMap to true.

    Example:

    production: {
      devtool: 'hidden-source-map',
      uglifyJsPlugin: {
        extractComments: true
      },
      definePlugin: {
        SOME_API_KEY: 'abcdefg'
      },
      plugins: (webpack) => { return [ new webpack.IgnorePlugin(/jsdom$/) ] },
      loaders: [] // Adds to `webpackConfig.module.rules`
    }

    By default, the env will be "development" when running yarn run blendid, and "production" when running yarn run blendid -- build.

    hot

    By default, webpack HMR will simply will do a full browser refresh when your js files change. If your code takes advantage of hot module replacement methods, modules will be hot loaded.

    Defaults to:

    hot: {
      enabled: true,
      reload: true,
      quiet: true,
      react: false
    }

    If you're using React yarn add react-hot-loader@next and set react: true to enable react-hot-loader 3. Follow the docs and update your React app to take advantage.

    customizeWebpackConfig

    In the event that an option you need is not exposed, you may access, modify and return a futher customized webpackConfig by providing this option as a function. The function will recieve the Blendid webpackConfig, env and webpack as params. The env value will be either development (yarn run blendid) or production (yarn run blendid -- build).

    customizeWebpackConfig: function (webpackConfig, env, webpack) {
      if(env === 'production') {
        webpackConfig.devtool = "nosources-source-map"
      }
    
      return webpackConfig
    }

    CAUTION! Avoid overwriting webpackConfig.entry or webpackConfig.plugins via this function, and rely on the entry and plugins options above to avoid breaking Blendid's hot-loading and file revisioning setup (view source).

    stylesheets

    You're welcome to use straight CSS, but Blendid will also compile Sass (.scss and .sass) for you automatically.

    autoprefixer

    Your Sass gets run through Autoprefixer, so don't prefix! Use this option to pass configuration. Defaults to { browsers: ["last 3 versions"].

    sass

    Options to pass to node-sass.

    Defaults to { includePaths: ["./node_modules"]} so you can @import files installed to node_modules.

    alternateTask

    If you're not a Sass fan, or for whatever reason, want to use your own task for compiling your stylesheets, you may use the alternateTask option to return an alternate function to run as the stylesheets task.

    stylesheets: {
      alternateTask: function(gulp, PATH_CONFIG, TASK_CONFIG) {
        // PostCSS task instead of Sass
        return function() {
          const plugins = [
              autoprefixer({browsers: ['last 1 version']}),
              cssnano()
          ]
          return gulp.src('./src/*.css')
              .pipe(postcss(plugins))
              .pipe(gulp.dest('./dest'))
        }
      }
    }

    html

    Note: If you are on a platform that's already handing compiling html (Wordpress, Craft, Rails, etc.), set html: false or delete the configuration object completely from task-config.js. If that's the case, don't forget to use the Browsersync files option in the browserSync config object to start watching your templates folder.

    Blendid can work with straight HTML, but it will also compile Nunjucks, a Jinja/Django-like templating language similar to Twig (used by Craft and Synfony), Liquid (used by Shopify), and the no longer maintained Swig.

    nunjucksRender

    Pass options directly to gulp-nunjucks-render. For example, you can add custom Nunjucks filters via the manageEnv option.

    html: {
      nunjucksRender: {
        manageEnv: function(env) {
          env.addFilter('excited', function(input) {
            return (input + '!')
          })
        }
      }
    }

    dataFunction

    gulp-data dataFunction used provide data to templates. Defaults to reading a in a global JSON, specified by the dataFile option.

    dataFile

    A path to a JSON file containing data to use in your Nunjucks templates via gulp-data.

    htmlmin

    Options to pass to gulp-htmlmin.

    excludeFolders

    You'll want to exclude some folders from being compiled directly. This defaults to: ["layouts", "shared", "macros", "data"]

    alternateTask

    If you're not a nunjucks fan, or for whatever reason, want to use your own task for compiling your html, you may use the alternateTask option to return an alternate function to run as the html task.

    html: {
      alternateTask: function(gulp, PATH_CONFIG, TASK_CONFIG) {
        // Jade task instead of Nunjucks
        return function() {
          gulp
            .src('./lib/*.jade')
            .pipe(jade())
            .pipe(gulp.dest('./dist/'))    }
      }
    }

    static

    There are some files that belong in your root destination directory that you won't want to process or revision in production. Things like favicons, app icons, etc. should go in src/static, and will get copied over to public as a last step (after revisioning in production). Nothing should ever go directly in public, since it gets completely trashed and re-built when running the default or production tasks.

    srcOptions

    Options passed to gulp.src. See gulp documetation for details. Defaults to:

    static: {
      srcOptions: {
        dot: true // include dotfiles
      }
    }

    fonts, images

    These tasks simply copy files from src to dest configured in path-config.json. Nothing to configure here other than specifying extensions or disabling the task.

    The image task previously ran through image-min, but due to the size of the package and the fact it doesn't need to be run everytime - it was removed. The current recommendation is to install imagemin-cli globally and running it on your source files periodically. If you prefer GUIs, you can try ImageOptim instead.

    ghPages

    You can deploy the contents your dest directly to a remote branch (gh-pages by default) with yarn run blendid -- ghPages. Options specified here will get passed directly to gulp-gh-pages.

    svgSprite

    Generates an SVG Sprite from svg files in src/icons! You can either include the created SVG directly on the page and reference the icon by id like this:

      <svg viewBox="0 0 1 1"><use xlink:href='#my-icon'></use></svg>

    or reference the image remotely.

    <svg viewBox="0 0 1 1"><use xlink:href='images/spritesheets/sprites.svg#my-icon'></use></svg>

    If you reference the sprite remotely, be sure to include something like inline-svg-sprite or svg4everybody to ensure external loading works on Internet Explorer.

    Blendid includes a helper whiches generates the required svg markup in src/html/macros/helpers.html, so you can just do:

      {{ sprite('my-icon') }}

    which spits out:

      <span class='sprite -my-icon'>
        <svg viewBox="0 0 1 1"><use xlink:href='images/spritesheets/sprites.svg#my-icon'></use></svg>
      </span>

    This particular setup allows styling 2 different colors from your CSS. You can have unlimited colors hard coded into your svg.

    In the following example, the first path will be red, the second will be white, and the third will be blue. Paths without a fill attribute will inherit the fill property from CSS. Paths with fill="currentColor" will inherit the current CSS color value, and hard-coded fills will not be overwritten, since inline styles trump CSS values.

    .sprite
      fill: red
      color: white
      <svg xmlns="http://www.w3.org/2000/svg">
        <path d="..."/>
        <path fill="currentColor" d="..."/>
        <path fill="blue" d="..."/>
      </svg>

    I recommend setting up your SVGs on a 500 x 500 canvas, centering your artwork, and expanding/combining any shapes of the same color. This last step is important. Read more on SVG optimization here!

    clean

    clean: {
      patterns: [
        path.resolve(process.env.PWD, 'dist/assets'),
        path.resolve(process.env.PWD, 'dist/templates')
      ]
    }
    
    By default, the entire `dest` directory is deleted before each build. By setting the `clean.patterns` option, you can specify which directory or directories (using globbing syntax) should be deleted instead. Use this if you have subdirectories within the `dest` directory that should be left alone (media uploaded through a CMS, say).
    
    ### production
    By default, filenames are revisioned when running the production `build` task. If you want to disable this behavior, you can set `rev` to false.
    
    ```js
    production: {
      rev: false
    }

    additionalTasks

    If you wish to define additional gulp tasks, and have them run at a certain point in the build process, you may use this configuration to do so via the following config object:

    additionalTasks: {
      initialize(gulp, PATH_CONFIG, TASK_CONFIG) {
        // Add gulp tasks here
      },
      development: {
        prebuild: [],
        postbuild: []
      },
      production: {
        prebuild: [],
        postbuild: []
      }
    }

    Blendid will call initialize, passing in gulp, along with the path and task configs. Use this method to define or require additional gulp tasks. You can specify when and in what order your custom tasks should run in the production and development prebuild and postbuild options.

    For example, say you had a sprite task you wanted to run before your css compiled, and in production, you wanted to run an image compression task you had after all assets had been compiled. Your configuration might look something like this:

    additionalTasks: {
      initialize(gulp, PATH_CONFIG, TASK_CONFIG) {
        gulp.task('createPngSprite', function() {
          // do stuff
        })
        gulp.task('compressImages', function() {
          // compress all the things
        })
      },
      development: {
        prebuild: ['createPngSprite'],
        postbuild: []
      },
      production: {
        prebuild: ['createPngSprite'],
        postbuild: ['compressImages']
      }
    }
    

    FAQ

    Can I customize and add Gulp tasks?

    Yep! See additionalTasks, as well as the task option of the stylesheets and html configs.

    I don't see JS files in my dest directory during development

    JS files are compiled and live-updated via Browsersync + webpack Dev Middleware + webpack Hot Middleware. That means you won't actually see .js files output to your destination directory during development, but they will be available to your browser running on the Browsersync port.

    Where'd the Karma + Mocha + Sinon + Chai JS testing setup go?

    Just use Jest! It used to be super complicated to string the right series of tools together to get a cohesive and full featured JS test suite — which is why we previously did it for you. But now Jest exists, solves these issues and is our strong recommendation.

    What's under the hood?

    Gulp tasks! Built combining the following:

    Feature Packages Used
    CSS Sass (Libsass via node-sass), Autoprefixer, CSSNano, Source Maps
    JavaScript Babel, webpack 3
    HTML Nunjucks, gulp-data, or bring your own
    Images Compression with imagemin
    Icons Auto-generated SVG Sprites
    Fonts Folder and .sass mixin for including WebFonts
    Live Updating Browsersync, webpack Dev Middleware, webpack Hot Middleware
    Production Builds CSS is minified, JS is compressed and optimized with various webpack plugins, filename md5 hashing (reving), file size reporting for long-term file caching
    Deployment Quickly deploy public folder to gh-pages with gulp-gh-pages

    Code At Viget

    Visit code.viget.com to see more projects from Viget.

    Keywords

    none

    Install

    npm i samsao-blendid

    DownloadsWeekly Downloads

    1

    Version

    4.2.0

    License

    MIT

    Last publish

    Collaborators

    • maoueh