# Node.js / Build System 20161011 [<i class="fa fa-github"></i> Elantris](https://github.com/Elantris) Note: https://hackmd.io/s/H1LliB_p ###### tags: `2016` `javascript` `handout` ## Node.js [Official Site](https://nodejs.org/) ### Setup Install Node.js. * Mac - [Homebrew](http://brew.sh/) + `brew update` + `brew upgrade` + `brew install node` - [Homebrew-versions](https://github.com/Homebrew/homebrew-versions) + `brew tap homebrew/versions` + `brew install node4-lts` + `brew install node5` * Windows - Download - Double click - Next, next, next - Done * Linux - Do It Yourself Update Node.js. * Mac - `brew update` (now with auto-update) - `brew upgrade` * Windows - Download - Double click - Next, next, next - Done * Linux - Do It Yourself Update NPM (Node Package Manager). ```sh $ npm install --global npm // latest $ npm install --global npm@2 // v2 ``` Check versions. ```sh $ node -v v6.7.0 $ npm -v 3.10.8 ``` ### CLI Commands ```sh $ npm i -g gulp pnpm ``` * [Gulp](https://github.com/gulpjs/gulp) The streaming build system http://gulpjs.com * [pnpm](https://github.com/rstacruz/pnpm) Performant 'npm install' http://ricostacruz.com/pnpm * [npm-check-update](https://github.com/tjunnone/npm-check-updates) Find newer versions of package dependencies than what your package.json or bower.json allows * [tldr](https://github.com/tldr-pages/tldr) A collection of simplified and community-driven man pages. * [Bower](https://github.com/bower/bower) A package manager for the web http://bower.io * [PM2](https://github.com/Unitech/pm2) Production process manager for Node.js apps with a built-in load balancer http://pm2.io ### Module System Every package in NPM is a module. Everything in JavaScript is an object. Export module. ```js // square.js function square(x) { return x * x; } module.exports = square; ``` Import module. ```js // index.js var square = require('./square.js'); console.log(square(12)); ``` ### Node.js Project Find a place to create a folder for a new Node.js project. ```sh $ mkdir node-project $ cd node-project ``` Prepare a NPM environment. > (Keep pressing enter till the end.) > It will create a file named `package.json`. ```sh $ npm init ``` Install dependencies. > https://github.com/jackdcrawford/five > It will create a folder named `node_modules`. ```sh $ npm install --save five ``` Write some codes. ```js // index.js var five = require('five'); console.log(five()); console.log(five.upHigh()); console.log(five.downLow()); ``` Run scripts. ```sh $ node index.js ``` ## Build System ### Front End Tools * Bower https://bower.io * ESLint http://eslint.org * Pug https://pugjs.org * Sass http://sass-lang.com * Babel https://babeljs.io * Browserify http://browserify.org ### Sublime Text Packages [Package Control](https://packagecontrol.io) * Bagel https://packagecontrol.io/packages/Babel * CSS3 https://packagecontrol.io/packages/CSS3 * Emmet https://packagecontrol.io/packages/Emmet * HTML5 https://packagecontrol.io/packages/HTML5 * SCSS https://packagecontrol.io/packages/SCSS ### Gulp [Official Site](http://gulpjs.com) Install packages with prefix of `gulp-`. * gulp-if https://github.com/robrich/gulp-if * gulp-rename https://github.com/hparra/gulp-rename * gulp-sourcemaps https://github.com/floridoo/gulp-sourcemaps * gulp-cssmin https://github.com/chilijung/gulp-cssmin * gulp-uglify https://github.com/terinjokes/gulp-uglify * gulp-concat https://github.com/contra/gulp-concat * gulp-eslint https://github.com/adametry/gulp-eslint * gulp-bower https://github.com/zont/gulp-bower * gulp-sass https://github.com/dlmanning/gulp-sass * gulp-autoprefixer https://github.com/sindresorhus/gulp-autoprefixer ```sh $ git clone https://github.com/Elantris/react-boilerplate.git ``` Load dependencies in `gulpfile.js`. ```js /*==================================== = Dependencies = ====================================*/ const fs = require('fs') const clc = require('cli-color') // https://github.com/medikoo/cli-color const moment = require('moment') // https://github.com/moment/moment/ // gulp const gulp = require('gulp') // https://github.com/gulpjs/gulp const gulpif = require('gulp-if') // https://github.com/robrich/gulp-if const rename = require('gulp-rename') // https://github.com/hparra/gulp-rename const sourcemaps = require('gulp-sourcemaps') // https://github.com/floridoo/gulp-sourcemaps const cssmin = require('gulp-cssmin') // https://github.com/chilijung/gulp-cssmin const uglify = require('gulp-uglify') // https://github.com/terinjokes/gulp-uglify const concat = require('gulp-concat') // https://github.com/contra/gulp-concat // tasks const del = require('del') // https://github.com/sindresorhus/del const eslint = require('gulp-eslint') // https://github.com/adametry/gulp-eslint const bower = require('gulp-bower') // https://github.com/zont/gulp-bower const sass = require('gulp-sass') // https://github.com/dlmanning/gulp-sass const autoprefixer = require('gulp-autoprefixer') // https://github.com/sindresorhus/gulp-autoprefixer const browserify = require('browserify') // https://github.com/substack/node-browserify const watchify = require('watchify') // https://github.com/substack/watchify const source = require('vinyl-source-stream') // https://github.com/hughsk/vinyl-source-stream const buffer = require('vinyl-buffer') // https://github.com/hughsk/vinyl-buffer const babelify = require('babelify') // https://github.com/babel/babelify const lrload = require('livereactload') // https://github.com/milankinen/livereactload const browserSync = require('browser-sync') // https://github.com/Browsersync/browser-sync ``` Utility functions. ```js var env = process.env.NODE_ENV || 'development' var colorLog = (color, message) => { console.log(`[${ clc.blackBright(moment().format('HH:mm:ss')) }] ${ clc[color](message) }`) } var errorLog = (err) => { colorLog('redBright', err.stack) } ``` Configure gulp tasks. * Clean the production files ```js gulp.task('clean', () => del([ './public/**', '!./public', ])) ``` * Code Lint ```js gulp.task('lint', () => gulp.src(['./src/react/**/*.jsx']) .pipe(eslint()) .pipe(eslint.format()) .pipe(eslint.failAfterError()) ) ``` * Install bower dependencies and bundle all plugins ```js gulp.task('bower-install', () => bower()) gulp.task('bower', ['bower-install'], () => { gulp.src([]) .pipe(cssmin()) .pipe(gulpif(env === 'development', sourcemaps.init())) .pipe(concat('plugins.min.css')) .pipe(gulpif(env === 'development', sourcemaps.write('./'))) .pipe(gulp.dest('./public/css/')) gulp.src([]) .pipe(uglify()) .pipe(gulpif(env === 'development', sourcemaps.init())) .pipe(concat('plugins.min.js')) .pipe(gulpif(env === 'development', sourcemaps.write('./'))) .pipe(gulp.dest('./public/js/')) }) ``` * Move static assets to public folder ```js gulp.task('move', () => gulp.src('./assets/**') .pipe(gulp.dest('./public/')) .pipe(browserSync.stream()) ) gulp.task('move:watch', ['move'], () => { gulp.watch(['./assets/**'], (event) => { gulp.src(event.path) .pipe(gulp.dest('./public/')) }) }) ``` * Compile sass into css ```js gulp.task('sass', () => gulp.src('./src/sass/*.scss') .pipe(gulpif(env === 'development', sourcemaps.init())) .pipe(sass({ outputStyle: 'compressed' }).on('error', sass.logError)) .pipe(autoprefixer({ browsers: ['last 2 versions'], cascade: false })) .pipe(rename({ suffix: '.min' })) .pipe(gulpif(env === 'development', sourcemaps.write('./'))) .pipe(gulp.dest('./public/css/')) ) gulp.task('sass:watch', ['sass'], () => { gulp.watch('./src/sass/**/*.scss', ['sass']) }) ``` * Schedule all tasks ```js gulp.task('default', ['bower', 'move', 'sass']) gulp.task('watch', ['browser-sync']) ``` Use gulp. ```sh $ gulp $ gulp watch $ gulp sass # single task ``` ### React [Official Site](https://facebook.github.io/react/) ```auto // main.jsx var React = require('react'); var ReactDOM = require('react-dom'); var App = React.createClass({ render: function() { return ( <div>hello, world</div> ); } }); ReactDOM.render(<App />, document.getElementById('main')); ``` ### Gulp For React * Bundling function ```js var dependencies = Object.keys(require('./package.json').dependencies) var lib_bundler, app_bundler var bundle = (b, output, mangle) => { b.bundle() .on('error', errorLog) .pipe(source(output)) .pipe(buffer()) .pipe(gulpif(env === 'production', uglify({ mangle: mangle }))) .on('error', errorLog) .pipe(gulp.dest('./public/js/')) } ``` * Bundle jsx file and transform to browser compatible scripts ```js gulp.task('react:lib', () => { lib_bundler = browserify({ debug: (env === 'development'), paths: ['./node_modules/'] }) for (var i in dependencies) lib_bundler.require(dependencies[i]) bundle(lib_bundler, 'main.lib.js', false) }) gulp.task('react:app', () => { app_bundler = browserify('./src/react/main.jsx', { cache: {}, packageCache: {}, debug: (env === 'development'), paths: ['./node_modules/'], transform: [ ['babelify', { presets: ['es2015', 'react'] }] ], fullPaths: (env === 'development') }) for (var i in dependencies) app_bundler.external(dependencies[i]) bundle(app_bundler, 'main.min.js', true) }) ``` * Watch changes ```js gulp.task('react:watch', ['react:app'], () => { app_bundler.plugin(lrload) app_bundler.plugin(watchify) app_bundler.on('log', (msg) => { colorLog('yellowBright', msg) }) app_bundler.on('update', (ids) => { bundle(app_bundler, 'main.min.js', true) }) }) ``` ### File Structures ``` ./node-project/ ├── gulpfile.js ├── package.json ├── assets/ | ├── fonts/ | └── img/ ├── node_modules/ ├── public/ | ├── index.html | ├── css/ | ├── fonts/ | ├── img/ | └── js/ └── src/ ├── react/ | ├── actions/ | ├── components/ | ├── stores/ | ├── utils/ | └── main.jsx └── sass/ ├── components/ ├── layout/ ├── plugins/ ├── utils/ └── main.scss ```