# NTUOSC Build System
20160603 [<i class="fa fa-github"></i> Elantris](https://github.com/Elantris)
Note: https://hackmd.io/s/N1ERJm5Ux
###### tags: `2016` `ntuosc` `javascript`
## Setup
Install latest npm, bower, pnpm, gulp in global
```
sudo npm install -g npm bower pnpm gulp
```
Find a place to clone the [repository](https://github.com/Elantris/ntuosc-course-20160603) and install dependencies
```
git clone git@github.com:Elantris/ntuosc-course-20160603.git
cd ntuosc-course-20160603
pnpm install
```
## Front-end Tools
### Pug
HTML Template Engine
[Language Reference](http://jade-lang.com)
`index.pug`
```jade
doctype html
html(lang="en")
head
meta(charset="UTF-8")
title NTUOSC Course 20160603
body
.container
h1 Color Thief
#color-thief
```
Use cli command to compile `.pug` file
```shell
$ npm install pug-cli -g
$ pug [options] [dir|file ...]
```
[Pug's CLI GitHub](https://github.com/pugjs/pug-cli)
### Sass
CSS Extension Language
[Official Site](http://sass-lang.com)
`main.scss`
```scss
body {
background: #eee;
}
.center {
text-align: center;
}
.row {
margin-bottom: 64px;
}
```
Use cli command to compile `.scss` file
```shell
$ gem install sass
$ sass main.scss > main.css
```
### React
JavaScript Framework
[Official Site](https://facebook.github.io/react/)
`main.jsx`
```jsx
var React = require('react');
var ReactDOM = require('react-dom');
var colorThief = new ColorThief();
var ColorBlock = React.createClass({
render: function() {
return (
<div>Color Block</div>
);
}
});
var ColorThiefContainer = React.createClass({
getInitialState: function() {
return {};
},
handleFile: function() {},
handleLoad: function() {},
render: function() {
return (
<div>Color Thief</div>
);
}
});
ReactDOM.render(<ColorThiefContainer />, document.getElementById('color-thief'));
```
Use cli command to compile `.jsx` file
```shell
$ npm install --save react react-dom babelify babel-preset-react
$ browserify -t [ babelify ] main.js -o bundle.js
```
## Gulp
Build System
[Official Site](http://gulpjs.com)
### File Structure
```
.
├── bower.json
├── bower_components
├── gulpfile.js
├── index.html
├── node_modules
├── package.json
└── src
├── scripts
│ └── main.jsx
├── styles
│ └── main.scss
└── views
└── index.pug
```
### Include dependencies
`gulpfile.js`
```js
var fs = require('fs');
var gulp = require('gulp'); // https://github.com/gulpjs/gulp
var moment = require('moment'); // https://github.com/moment/moment/
var clc = require('cli-color'); // https://github.com/medikoo/cli-color
var rename = require('gulp-rename'); // https://github.com/hparra/gulp-rename
var sourcemaps = require('gulp-sourcemaps'); // https://github.com/floridoo/gulp-sourcemaps
var gulpif = require('gulp-if'); // https://github.com/robrich/gulp-if
var production = (process.env.NODE_ENV === 'production');
```
### Colorful Log
```js
function colorLog(color, message) {
console.log('[%s] %s',
clc.blackBright(moment().format('HH:mm:ss')),
clc[color](message)
);
}
function errorLog(err) {
colorLog('redBright', err.stack);
}
```
### Task: Concat Libraries
```js
var cssmin = require('gulp-cssmin'); // https://github.com/chilijung/gulp-cssmin
var uglify = require('gulp-uglify'); // https://github.com/terinjokes/gulp-uglify
var concat = require('gulp-concat'); // https://github.com/contra/gulp-concat
gulp.task('move', function() {
gulp.src([
'./bower_components/skeleton/css/normalize.css',
'./bower_components/skeleton/css/skeleton.css',
])
.pipe(concat('lib.min.css'))
.pipe(cssmin())
.pipe(gulp.dest('./public/css/'));
gulp.src([
'./node_modules/jquery/dist/jquery.min.js',
'./node_modules/color-thief/js/color-thief.js',
])
.pipe(concat('lib.min.js'))
.pipe(uglify({ mangle: false }))
.pipe(gulp.dest('./public/js/'));
});
```
`gulp.src`: select files
### Task: Compile Pug
```js
var pug = require('gulp-pug'); // https://github.com/jamen/gulp-pug
gulp.task('pug', function() {
gulp.src('./src/views/*.pug')
.pipe(pug())
.pipe(gulp.dest('./'));
});
gulp.task('pug:watch', ['pug'], function() {
gulp.watch('./src/views/**/*.pug', ['pug', reload]);
});
```
`gulp.watch`: watch files changed
### Task: Compile Sass
```js
'use strict';
var sass = require('gulp-sass'); // https://github.com/dlmanning/gulp-sass
gulp.task('sass', function() {
gulp.src('./src/styles/*.scss')
.pipe(gulpif(production, sourcemaps.init()))
.pipe(sass({ outputStyle: 'compressed' }).on('error', sass.logError))
.pipe(gulpif(production, sourcemaps.write()))
.pipe(rename({ suffix: '.min' }))
.pipe(gulp.dest('./public/css/'));
});
gulp.task('sass:watch', ['sass'], function() {
gulp.watch('./src/styles/**/*.scss', ['sass', reload]);
});
```
### Task: Compile JSX
```js
var browserify = require('browserify'); // https://github.com/substack/node-browserify
var watchify = require('watchify'); // https://github.com/substack/watchify
var source = require('vinyl-source-stream'); // https://github.com/hughsk/vinyl-source-stream
var buffer = require('vinyl-buffer'); // https://github.com/hughsk/vinyl-buffer
var reactify = require('reactify'); // https://github.com/andreypopp/reactify
var b = browserify('./src/scripts/main.jsx', {
cache: {},
packageCache: {},
debug: !production,
transform: [reactify]
});
gulp.task('react', function() {
bundle();
});
gulp.task('react:watch', ['react'], function() {
b.plugin(watchify);
b.on('log', function(msg) {
colorLog('yellowBright', msg);
reload();
});
b.on('update', bundle);
});
function bundle() {
b.bundle()
.on('error', errorLog)
.pipe(source('main.min.js'))
.pipe(buffer())
.pipe(gulpif(production, uglify()))
.on('error', errorLog)
.pipe(gulp.dest('./public/js/'));
}
```
### Task: BrowserSync
```js
var browserSync = require('browser-sync').create(); // https://github.com/Browsersync/browser-sync
var reload = browserSync.reload;
gulp.task('browser-sync', function() {
browserSync.init({
server: {
baseDir: "./"
}
});
});
gulp.task('watch', ['pug:watch', 'sass:watch', 'react:watch', 'browser-sync']);
```
### Task: Default
```js
gulp.task('default', ['move', 'pug', 'sass', 'react']);
```
### Run scripts
Run default task and specific task
```
gulp
gulp react
```
Inside the package.json
```json
{
"scripts": {
"start": "pnpm install && bower install && NODE_ENV=production gulp",
"test": "NODE_ENV=production gulp watch",
"build:all": "NODE_ENV=production gulp"
}
}
```
Run npm script
```
npm start
npm test
npm run build:all
```