ANDRIY DACENKO
SOFTWARE ENGINEER
November 4, 2015
JS & FRONT-END AUTOMATION
PAINLESS DEVELOPMENT
JS MENTORING 2015
FRONT-END
ENVIRONMENT
ITS ALL ABOUT
Compile
Minify
Optimize
Test
PACKAGE MANAGERS
MANAGE NODE
# nvm - node version manager
$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash
$ nvm install iojs
$ nvm install node
$ nvm alias default node
$ nvm use default
# .nvmrc
v0.12.7
- Install nvm
- Set default v4.1.1
- Set v0.12.7 for
current project
TEMPLATING
Mustache
handlebars
_.templates
EJS
Hello {{name}}
You have just won {{value}} dollars!
{{#in_ca}}
Well, {{taxed_value}} dollars, after taxes.
{{/in_ca}}
{
"name": "Chris",
"value": 10000,
"taxed_value": 10000 - (10000 * 0.4),
"in_ca": true
}
Mustache.render(view, data);
Hello {{name}}
You have just won {{value}} dollars!
{{#if in_ca}}
Well, {{taxed_value}} dollars, after taxes.
{{/if}}
{
"name": "Chris",
"value": 10000,
"taxed_value": 10000 - (10000 * 0.4),
"in_ca": true
}
Handlebars.compile(view)(data);
Hello <%= name %>
You have just won <%= value %> dollars!
<% if(in_ca) { %>
Well, <%= taxed_value $> dollars, after taxes.
<% } %>
{
"name": "Chris",
"value": 10000,
"taxed_value": 10000 - (10000 * 0.4),
"in_ca": true
}
_.template(view)(data);
Hello <%= name %>
You have just won <%= value %> dollars!
<% if(in_ca) { %>
Well, <%= taxed_value $> dollars, after taxes.
<% } %>
{
"name": "Chris",
"value": 10000,
"taxed_value": 10000 - (10000 * 0.4),
"in_ca": true
}
new EJS({text: view}).render(data);
EJS
<% Embedded JavaScript %>
CSS
Sass
LESS
Stylus
PostCSS
@mixin border-radius($radius...) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
border-radius: $radius;
}
@import "vendor";
body {
font: 12px Helvetica, Arial, sans-serif;
}
a.button {
@include border-radius(5px);
}
.border-radius {
-webkit-border-radius: @arguments;
-moz-border-radius: @arguments;
border-radius: @arguments;
}
@import "vendor";
body {
font: 12px Helvetica, Arial, sans-serif;
}
a.button {
.border-radius(5px);
}
border-radius()
-webkit-border-radius arguments
-moz-border-radius arguments
border-radius arguments
@import 'vendor'
body
font 12px Helvetica, Arial, sans-serif
a.button
border-radius 5px
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
border-radius: $radius;
}
@import "vendor";
body {
font: 12px Helvetica, Arial, sans-serif;
}
a.button {
@include border-radius(5px);
}
POSTCSS
TASK
-
Init package.json
-
Create index.js
-
Install PostCSS
-
Install autoprefixer plugin
-
Run PostCSS
Estimates: 10 min
JAVASCRIPT
Concat
Browserify
Webpack
System.js
$ npm install -g browserify
// main.js
var unique = require('uniq');
var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];
console.log(unique(data));
$ npm i uniq --save
$ browserify main.js -o bundle.js
$ npm install webpack -g
// main.js
var unique = require('uniq');
var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];
console.log(unique(data));
$ npm i uniq
$ webpack ./entry.js bundle.js
WEBPACK
// webpack.config.js
module.exports = {
entry: './main.js',
output: {
path: './build',
publicPath: 'http://mycdn.com/',
filename: 'bundle.js'
},
module: {
loaders: [
{ test: /\.less$/, loader: 'style!css!less' },
{ test: /\.css$/, loader: 'style!css' },
{ test: /\.png$/, loader: 'url-loader?limit= 8192' }
]
}
};
$ npm install jspm -g
// main.js
import 'util';
const data = [1, 2, 2, 3, 4, 5, 5, 5, 6];
console.log(unique(data));
$ jspm i npm:uniq
$ jspm bundle-sfx main
JSPM
TASK
-
Install jspm
-
Install lodash in project
-
Add your own js code
-
Run build of jspm
Estimates: 10 min
TEST
Mocha
Jasmine
Karma
Protractor
$ npm install -g mocha
// test/test.js
var assert = require('assert');
describe('Array', function() {
describe('#indexOf()', function () {
it('should return -1 when value is not present', function () {
assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));
});
});
});
# continous testing
$ mocha -w
$ mocha
Array
#indexOf()
✓ should return -1 when the value is not present
1 passing (9ms)
$ npm install -g jasmine-node
// test/test.spec.js
describe('Array', function() {
describe('#indexOf()', function () {
it('should return -1 when value is not present', function () {
expect([1,2,3].indexOf(5)).toEqual(-1);
expect([1,2,3].indexOf(0)).toEqual(-1);
});
});
});
# continous testing
$ jasmine test --watch
$ jasmine test
Array - 4 ms
#indexOf() - 4 ms
should return -1 when value is not present - 3 ms
Finished in 0.01 seconds
1 test, 2 assertions, 0 failures, 0 skipped
$ npm install -g karma-cli
# Install plugins
$ npm install karma-jasmine karma-phantomjs-launcher --save-dev
// karma.conf.js
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: [...],
//...
});
};
# watch mode
$ karma start
$ karma start --single-run
[karma]: No captured browser, open http://localhost:9876/
[karma]: Karma v0.13.14 server started at http://localhost:9876/
[launcher]: Starting browser PhantomJS
Executed 1 of 1 SUCCESS (0.004 secs / 0.001 secs)
$ npm install -g protractor
$ webdriver-manager update
$ webdriver-manager start
describe('angularjs homepage todo list', function() {
it('should add a todo', function() {
browser.get('https://angularjs.org');
element(by.model('todoList.todoText'))
.sendKeys('write first protractor test');
element(by.css('[value="add"]')).click();
var todoList = element.all(
by.repeater('todo in todoList.todos')
);
expect(todoList.count()).toEqual(3);
expect(todoList.get(2).getText())
.toEqual('write first protractor test');
// You wrote your first test, cross it off the list
todoList.get(2).element(by.css('input')).click();
var completedAmount = element.all(by.css('.done-true'));
expect(completedAmount.count()).toEqual(2);
});
});
TASK
-
Install mocha
-
Create test folder
-
Add simple test
-
Run build test using mocha
Estimates: 10 min
CUSTOM TASKS
Sprites
Livereload
Minification
CSS
Deploy
Release
Semver
Server
Static
TOOLS
YO!
$ npm i -g yo generator-webapp
$ yo webapp
GENERATOR
$ npm install -g generator-generator
# generate generator
$ yo generator
.
├── generators
│ └── app
│ ├── index.js
│ └── templates
│ ├── _bower.json
│ ├── _package.json
│ ├── editorconfig
│ └── jshintrc
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .jshintrc
├── .travis.yml
├── .yo-rc.json
├── package.json
├── README.md
└── test
└── test-app.js
GRUNT
module.exports = function(grunt) {
grunt.initConfig({
jshint: {
files: ['**.js'],
options: JSON.parse(require('fs').readFileSync('./.jshinrc'))
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
};
PLUGINS
FLOW
GULP
var jshint = require('gulp-jshint');
var gulp = require('gulp');
gulp.task('jshint', function() {
return gulp.src('**.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
PLUGINS
FLOW
NPM
"devDependencies": {
"jshint": "latest",
},
"scripts": {
"lint": "jshint **.js"
}
PLUGINS
FLOW
NPM CONFIG
// package.json
{
"name": "epam-mentoring",
"config": {
"autoprefixer": "latest",
"cssmin": "latest",
"reporter": "xunit"
},
"scripts": {
"build:css": "autoprefixer -b 'last 2 versions' <
assets/styles/main.css | cssmin > dist/main.css",
"test": "mocha test/ --reporter $npm_package_config_reporter"
"test:dev": "npm run test --epam-mentoring:reporter=spec"
}
}
$ npm config set epam-mentoring:reporter spec
TASK
-
Add test run script
-
Add `jspm install` before build
-
Add build:css
-
Add build:js
-
Run build:* in parallel
Estimates: 10 min
CI
Test
Release
Deploy
TRAVIS
CONFIG
language: node_js
node_js:
- '0.12'
- '4'
- '5'
before_install:
- npm install -g npm
install:
- npm install -g bower
DEPLOY & RELEASE
deploy:
- provider: heroku
api_key "YOUR HEROKU API KEY"
- provider: releases
api-key: "GITHUB OAUTH TOKEN"
file: "FILE TO UPLOAD"
skip_cleanup: true
on:
tags: true
HA
Simple web page about
- stack used
- code coverage report
Stack
-
Use any pre-/post- processor for CSS
-
Use any JS build tool
-
Use any Task runner
-
Use any Test framework/runner
-
Use Travis to deploy / release or both
Q&A Time
ANDRIY DACENKO
SOFTWARE ENGINEER
November 4, 2015
JS & FRONT-END AUTOMATION
PAINLESS DEVELOPMENT
JS & Front-End automation
By Andrew Dacenko
JS & Front-End automation
EPAM: JS Mentoring program Kyiv.2015-06. Lecture20: JS and Front-End automation
- 1,348