Skip to content

Instantly share code, notes, and snippets.

@davisford
Last active November 11, 2020 07:09
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davisford/fab56fc45594bc996fd1 to your computer and use it in GitHub Desktop.
Save davisford/fab56fc45594bc996fd1 to your computer and use it in GitHub Desktop.
Updated build system for Ionic Framework
{
"directory": "bower_components"
}
{
"message": "this file lives at ./src/config.json and allows you to inject different server urls for different build TARGET",
"staging": {
"url": "http://staging.example.com"
},
"production": {
"url": "http://prod.example.com"
}
}
/* jshint node: true */
'use strict';
var gulp = require('gulp'),
angularFilesort = require('gulp-angular-filesort'),
bower = require('bower'),
bowerFiles = require('main-bower-files'),
concat = require('gulp-concat'),
debug = require('gulp-debug'),
del = require('del'),
gutil = require('gulp-util'),
htmlmin = require('gulp-htmlmin'),
jshint = require('gulp-jshint'),
minifyCss = require('gulp-minify-css'),
ngAnnotate = require('gulp-ng-annotate'),
ngHtml2Js = require('gulp-ng-html2js'),
notify = require('gulp-notify'),
queue = require('streamqueue'),
rename = require('gulp-rename'),
replace = require('gulp-replace'),
sass = require('gulp-sass'),
sh = require('shelljs'),
sourcemaps = require('gulp-sourcemaps'),
uglify = require('gulp-uglify');
gutil.log('Gulpfile is starting...');
var target = 'development',
appConfig = JSON.parse(require('fs').readFileSync('./src/config.json')),
verbose = false;
if (!process.env.TARGET) {
gutil.log(gutil.colors.red.underline.bold('NO TARGET SPECIFIED, so the default is TARGET=development'));
gutil.log('If you are building for', gutil.colors.cyan.underline('staging'), 'or', gutil.colors.blue.underline('production'), 'you should specify', gutil.colors.red.bold('TARGET={staging | production}'));
} else {
target = process.env.TARGET;
}
function getLocalIp () {
var interfaces = require('os').networkInterfaces();
for (var dev in interfaces) {
var iface = interfaces[dev];
for (var i=0; i < iface.length; i++) {
var alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
return alias.address;
}
}
}
}
/**
* Filter an array of files according to file type
*
* @param {Array} files
* @param {String} extension
* @return {Array}
*/
function fileTypeFilter (files, extension) {
var regExp = new RegExp('\\.' + extension + '$');
return files.filter(regExp.test.bind(regExp));
}
gulp.task('default', ['index', 'ionic-sass', 'sass', 'jshint', 'js', 'replace-ip', 'vendor', 'templates', 'fonts']);
gulp.task('clean', function () {
del(['./www/**', '!./www', '!./www/.gitignore']);
});
gulp.task('index', function () {
gulp.src('./src/index.html')
.pipe(gulp.dest('./www'));
});
gulp.task('replace-ip', ['js'], function () {
var url;
switch(target) {
case 'development':
url = 'http://' + getLocalIp() + ':3000'; break;
case 'staging':
// fall thru
case 'production':
url = appConfig[target].url; break;
default:
throw new Error('No TARGET configured or it is misconfigured ', target);
}
gutil.log(gutil.colors.red.underline.bold('App will try to connect to the server at', url));
return gulp.src('./www/js/app.min.js')
.pipe(replace(/REPLACE_TOKEN/g, url))
.pipe(gulp.dest('./www/js'));
});
/*
| ----------------- SASS -------------------
*/
gulp.task('ionic-sass', function () {
return gulp.src('./src/styles/ionic-overrides/*.scss', { base: './src/styles/ionic-overrides'})
.pipe(debug({title: 'ionic-sass'}))
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(sass())
.pipe(minifyCss({keepSpecialComments: 0}))
.pipe(rename({extname: '.min.css'}))
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./www/css'));
});
gulp.task('sass', function () {
return gulp.src(['./src/styles/**/*.scss', '!./src/styles/ionic-overrides/**'])
.pipe(debug({title: 'sass'}))
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(concat('app.css'))
.pipe(sass())
.pipe(minifyCss({keepSpecialComments: 0}))
.pipe(rename({extname: '.min.css'}))
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./www/css'));
});
/*
| ----------------- JavaScript -------------------
*/
gulp.task('vendor', function () {
var files = bowerFiles({paths: './', debugging: verbose}),
vendorJs = fileTypeFilter(files, 'js'),
q = new queue({objectMode: true});
q.queue(gulp.src(vendorJs)
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(concat('vendor.js'))
.pipe(uglify())
.pipe(rename({extname: '.min.js'}))
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./www/js'))
);
return q.done();
});
gulp.task('jshint', function () {
return gulp.src(['./src/js/**/*.js'])
.pipe(debug({title: 'jshint'}))
.pipe(jshint('./.jshintrc'));
});
gulp.task('js', function () {
return gulp.src(['./src/**/*.js'])
.pipe(debug({title: 'js'}))
.pipe(angularFilesort())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(concat('app.js'))
.pipe(ngAnnotate({add: true, single_quotes: true, stats: true, sourcemap: true}))
.on('error', notify.onError('Error: <%= error.message %>'))
.pipe(uglify())
.on('error', notify.onError('Error: <%= error.message %>'))
.pipe(rename({extname: '.min.js'}))
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./www/js'));
});
/*
| ----------------- Templates -------------------
*/
gulp.task('templates', function () {
return gulp.src('./src/**/*.tpl.html')
.pipe(debug({title: 'templates'}))
.pipe(htmlmin({ collapseWhitespace: true }))
.pipe(ngHtml2Js({ moduleName: 'templates' }))
.pipe(concat('templates.js'))
.pipe(ngAnnotate())
.pipe(rename({ extname: '.min.js' }))
.pipe(uglify())
.pipe(gulp.dest('./www/js/'));
});
/*
| ----------------- Fonts -------------------
*/
gulp.task('fonts', function () {
return gulp.src([
'./bower_components/ionic/fonts/**/*.{ttf,woff,eot,svg}',
'./src/assets/fonts/**/*.{ttf,woff,eot,svg}'
])
.pipe(debug({title: 'fonts'}))
.pipe(gulp.dest('./www/assets/fonts'));
});
gulp.task('watch', function () {
gulp.watch('./src/styles/**/*{sass,scss}', ['ionic-sass', 'sass']);
gulp.watch('./src/**/*.js', ['jshint', 'js', 'replace-ip']);
gulp.watch('./bower_components/**/*.js', ['vendor']);
gulp.watch('./src/**/*.tpl.html', ['templates']);
});
/*
| ----------------- this was in original Ionic gulpfile.js -------------------
*/
gulp.task('install', ['git-check'], function() {
return bower.commands.install()
.on('log', function(data) {
gutil.log('bower', gutil.colors.cyan(data.id), data.message);
});
});
gulp.task('git-check', function(done) {
if (!sh.which('git')) {
console.log(
' ' + gutil.colors.red('Git is not installed.'),
'\n Git, the version control system, is required to download Ionic.',
'\n Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
'\n Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
);
process.exit(1);
}
done();
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title>YOUR APP NAME HERE</title>
<link href='css/ionic.app.min.css' rel='stylesheet'>
<link href='css/vendor.min.css' rel='stylesheet'>
<link href='css/app.min.css' rel='stylesheet'>
<script src='js/vendor.min.js'></script>
<script src='cordova.js'></script>
<script src='js/templates.min.js'></script>
<script src='js/app.min.js'></script>
</head>
<body ng-app="starter">
<ion-nav-bar class="bar-dark">
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</body>
</html>
I execute the build like this, for development:
$ gulp; ionic serve -l -c -s
This works with live-reload and will attempt to connect to the backend server at the localhost's IP
This will build for production url and emulate in iOS
$ TARGET=production gulp; ionic emulate ios -l -c -s
This will build for staging url and emulate in iOS
$ TARGET=staging gulp; ionic emulate ios -l -c -s
{
"name": "your-app-name",
"app_id": "",
"gulpStartupTasks": [
"watch"
],
"watchPatterns": [
"www/**/*"
]
}
{
"name": "your-app-name-here",
"version": "1.0.0",
"description": "your-description-here",
"repository": {
"type": "git",
"url": "git@path-to-repo.git"
},
"dependencies": {},
"devDependencies": {
"bower": "^1.3.3",
"del": "^1.1.1",
"gulp": "^3.8.10",
"gulp-angular-filesort": "^1.0.4",
"gulp-concat": "^2.4.3",
"gulp-debug": "^2.0.0",
"gulp-htmlmin": "^1.0.0",
"gulp-jshint": "^1.9.0",
"gulp-minify-css": "^0.3.13",
"gulp-ng-annotate": "^0.5.0",
"gulp-ng-html2js": "^0.1.8",
"gulp-notify": "^2.1.0",
"gulp-rename": "^1.2.0",
"gulp-replace": "^0.5.2",
"gulp-sass": "^0.7.3",
"gulp-sourcemaps": "^1.3.0",
"gulp-uglify": "^1.1.0",
"gulp-util": "^3.0.2",
"gulp-watch": "^4.0.2",
"jshint-stylish": "^1.0.0",
"main-bower-files": "^2.5.0",
"shelljs": "^0.3.0",
"streamqueue": "^0.1.1"
}
}
// showing the source directory structure
$tree ./src
./src
├── assets
│   ├── fonts
│   │   ├── icomoon.eot
│   │   ├── icomoon.svg
│   │   ├── icomoon.ttf
│   │   └── icomoon.woff
│   └── img
│   └── ionic.png
├── config.json
├── index.html
├── js
│   ├── app.js
│   ├── controllers.js
│   └── services.js
├── styles
│   ├── app.scss
│   └── ionic-overrides
│   └── ionic.app.scss
└── templates
├── forgot-password.tpl.html
├── login.tpl.html
├── tab-alerts.tpl.html
├── tab-dash-filter.tpl.html
├── tab-dash.tpl.html
└── tabs.tpl.html
7 directories, 18 files
// showing the www directory structure; this is the minified, production build
$tree ./www
./www
├── assets
│   └── fonts
│   ├── icomoon.eot
│   ├── icomoon.svg
│   ├── icomoon.ttf
│   ├── icomoon.woff
│   ├── ionicons.eot
│   ├── ionicons.svg
│   ├── ionicons.ttf
│   └── ionicons.woff
├── css
│   ├── app.min.css
│   ├── ionic.app.min.css
│   └── vendor.min.css
├── index.html
├── js
│   ├── app.min.js
│   ├── templates.min.js
│   └── vendor.min.js
└── maps
├── app.min.css.map
├── app.min.js.map
├── ionic.app.min.css.map
└── vendor.min.js.map
5 directories, 19 files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment