GDI Logo

How to Be a Lazy Developer

An Introduction to build tools

Follow along at https://pselle.github.io/gdi-build-tools.

Is your machine ready to go?

  • Node.js and npm installed
  • Please ask a TA to help you check if you aren't sure! Node 6+ please!
  • Your favorite text editor ready to go
  • I use Atom, but we often recommend Sublime Text

Introductions

  • Your name
  • What you hope to get out of class
  • Your favorite dinosaur

What we're learning today

  • Scaffolding
  • Old school build tooling (make)
  • Dependency management with npm
  • JS build tools: gulp and webpack

What do build tools help us do?

What do build tools help us do?

Developers write software to make their lives easier

  • Start new projects
  • Optimize: minify, bundle
  • Validation: syntax errors, unit tests
  • Compile: Sass, Babel
  • Repeat the above when we make a file change

Scaffolding: Starting new projects

We use scaffolding tools (such as "rails new" or the create-react-app project) to quickly get a project started, or to see how a project works with all the pieces together

Although useful, scaffolding can constrain you to someone else's way of thinking. Critically analyze any scaffolding system you use for suitability!

Let's Develop It!

We're going to try out Yeoman a scaffolding tool for webapps

$ npm install -g yo

Now, run yo from your terminal. What happens? Now, try running one of the many generator options!

$ mkdir [directory name]
$ cd [directory name]
$ yo [choose a generator]

Build Tool Basics

  • Run complex series of tasks with simple commands
  • Check your code for common problems
  • Automatically run when a file changes
  • Host a local server to help development (eg Ajax requests)

Makefile

  • Initially used for compiling C programs
  • Can be used for any command-line tasks
  • Everything we do later with a build script (ex. gulp, npm scripts) you can do with make!
  • Pre-installed Mac/Linux

Makefile sample

all: clean build

clean:
	rm -rf foo

build:
	mkdir foo && cd foo && touch index.html

Make is great!

  • Every "word:" can be run as a command
  • "all" runs by default when you run "make"
  • Add as many commands as you want
  • Make is smart! Runs what is necessary based on what changed

Let's Develop It!

Try making a Makefile using the sample code. You can also download from github.

all: clean build

clean:
	rm -rf foo

build:
	mkdir foo && cd foo && touch index.html

Dependency management

Photo via Flickr user Steven Depolo

npm - Node Package Manager

"npm is the package manager for JavaScript and the world’s largest software registry" - npmjs.com

Yarn is an alternative to npm, and many of the commands map. It's fast and has some strong benefits.

Let's Develop It!

Create a new directory and run "npm init"

package.json

{
  "name": "intro-to-build-tools",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "GDI Philly",
  "license": "MIT"
}

Adding dependencies

Use npm to install a package AND save it to our dependencies!

$ npm install --save dinosaur-fetcher
Tip! You can also use -S instead of --save!

Let's Develop It!

  • Install the dinosaur fetcher module in your node project
  • Create index.js and fill it in with the code below
const dino = require('dinosaur-fetcher');

console.log(dino.random());

BONUS activities: Be creative with how you use dinosaur fetcher! Can you prompt the user? Do something with multiple dinosaur values?

Scripts?? Let's scripts!!

The "scripts" section of package.json can be any word, and you can run with "npm run [word]"

Some words have default behaviors, such as "start" and "install", and npm has lots of details on that.

Edit package.json to look like:

  "scripts": {
    "test": "echo \"No tests yet!\"",
    "start": "node index.js"
  },

And run "npm start"

For a challenge, use a new word (ex. "build") and have it run any bash command! Don't forget "npm run"!

JavaScript Built Tools!

We'll talk about two today:

  • Gulp
  • Webpack

Why use web build tools?

  • Write in language we know (JS)
  • Run in Node runtime
  • Large plugin ecosystems

How do you choose your toolset?

  • More about combinations than choices
  • Choose an overarching runner (ex. gulp or webpack) you can add on to
  • Add tooling to make development more fun: Babel for ES6, CSS pre-processor for variables, etc.
  • Common toolsets: React+Babel+Webpack, Gulp+concat+uglify

Gulp

gulpjs.com

Photo via Flickr user Alden Jewell

Gulp

  • Define tasks
  • Define sources
  • "Pipe" sources through processes
var gulp = require('gulp');

gulp.task('default', function() {
  gulp.src('./*.js')
    .pipe(gulp.dest('dist'));
});

Things we could add to our builds!

  • Linters - ESLint
  • Compilers - Babel, compression, etc.
  • Source maps - point a compressed line of code to its original line number
  • Watch - automatically refresh our page when we changed a file

Let's Develop It!

  • Install gulp as a dependency for your project, using npm
  • Create a "gulpfile.js" file in the project we used with npm
  • BONUS: Add a "script" task to run gulp
  • BONUS: Where is gulp in package.json if you install as a developer dependency (-D vs. -S)?
  • BONUS: Add gulp-watch to your project
var gulp = require('gulp');

gulp.task('default', function() {
  gulp.src('./*.js')
    .pipe(gulp.dest('dist'));
});

Webpack

webpack.js.org

Webpack is a module bundler for web applications.

Webpack: Simple

Webpack is smart. It understands lots of module definitions (CommonJS, AMD, ES 6 modules, etc.) and puts things together.

// webpack.config.js
module.exports = {
  entry: './index.js',
  output: {
    filename: 'bundle.js'
  }
}

Webpack components

  • Entry
  • Output
  • Loaders
  • Plugins
// webpack.config.js
module.exports = {
  entry: './index.js', // Entry!
  output: { // Output!
    filename: 'bundle.js'
  }
}

Note: the Webpack 2 documentation has a great overview of these!

Loaders & Plugins

Loaders are how webpack understands files - how you can 'require()' a CSS file, or an image file, even!

Plugins perform actions on "compilations" or "chunks" of bundled code, vs. on a per file basis like a loader

Loaders

We can use a CSS Loader to require CSS in our JS!

This is useful in, ex. modular components

const path = require('path');
module.exports = {
  entry: './index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.css/,
        loaders: ['style-loader', 'css-loader'],
        include: __dirname + '/css'
      }
    ]
  }
};

Including CSS in our JS

import { coolStuff } from './coolStuff';
import styles from './css/coolStyles.css';
import mainStyles from './css/styles.css';

document.write(`

MOAR COOL STUFF ${coolStuff}!

`);

Using a plugin instead

const path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  entry: './index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.css/,
        loader: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css")
  ]
};

Let's Develop It!

Try making a basic webpack configuration on your own!

Thank you!

Don't forget to fill out the survey!

http://tiny.cc/gdibuilds