Using gulp-minify-html and gulp-html-replace together - gulp

I am using Gulp with gulp-minify-html and gulp-html-replace:
var minifyhtml = require('gulp-minify-html');
var htmlreplace = require('gulp-html-replace');
var dev_paths = {
HTML: dev + '/**/*.html'
};
var prod_paths = {
RELATIVE_CSS: ['css/bootstrap.css', 'css/font-awesome.css', 'css/c3.css', 'css/main.css'],
};
//Compress HTML
gulp.task('minify-html', function () {
var opts = {
empty: true,
comments: true
};
return gulp.src(dev_paths.HTML)
.pipe(minifyhtml(opts))
.pipe(gulp.dest(prod + '/'));
});
//Add call to the JS and CSS in the HTML files
gulp.task('replace-files', function() {
gulp.src(dev_paths.HTML)
.pipe(htmlreplace({
'css': prod_paths.RELATIVE_CSS,
'js': 'js/script.js'
}))
.pipe(gulp.dest('public/prod/'));
});
gulp.task('prod',['replace-files','minify-html'], function(){
})
However, the HTML doesn't replace the CSS and JS files I specified with task replace-files. When I run gulp without the task minify-html, it works fine though.
Does anyone knows why using both tasks replace-files and minify-html together is not working?
Thank you.

As the tasks run in parallel it is likely the 'minify-html' task is running before the 'replace-files' task is complete.
Try using run-sequence to ensure the tasks run in the required order.

Related

Gulpfile end of task with two different operations

I am kind of lacking imagination on that one.
My goal is to retrieve a json object so I can run a replace string on all the files I want to translate, I have looked into a lot of translation libraries but this way is the best i can think of for my use.
Anyway my issue here is Once I got my json object, I have to run on all the files and when it is done, finish the task 'trad'.
I have done some research and tried a lot of things but there is something that I miss, something that I didn't understood about the good way to do that ?
Please help !
gulp.task('trad', gulp.series( 'createTradFile', 'copyBeforeTrad', function( done ) {
var data = require('gulp-data');
var path = require('path');
var fs = require('fs');
var replace2 = require('gulp-string-replace');
var transObj = null;
var translateAll = function()
{
var files = gulp.src(['fr/**/*.html', 'fr/**/*.js']);
for (var k in transObj)
{
if (transObj[k].ID)
{
console.log("TRAD " + transObj[k].ID + " TO " + transObj[k].LANG1);
files.pipe(replace2(new RegExp('\\+' + transObj[k].ID + '\\+', 'g'),
transObj[k].LANG1,
{'logs': {'enabled': true}}))
.pipe(chmod(755));
}
}
files.pipe(gulp.dest("fr"))
.on('end', done);
};
gulp.src('distTemp/wording.json')
.pipe(data(function(file) {
transObj = JSON.parse( fs.readFileSync('distTemp/' + path.basename(file.path)));
console.log("TRAD first part OK");
translateAll();
}));
}));
So this code will translate like I want it too, but the task does not end :
[16:38:34] The following tasks did not complete: trad, <anonymous>
[16:38:34] Did you forget to signal async completion?
So, after a bit of research I found this ( almost crappy ) solution, which do the trick ( please answer if you hava a better solution )
var transObj = null;
gulp.task("retrieveTradObject", function(){
var data = require('gulp-data');
var path = require('path');
var fs = require('fs');
return gulp.src('distTemp/wording.json')
.pipe(data(function(file) {
transObj = JSON.parse( fs.readFileSync('distTemp/' + path.basename(file.path)));
console.log("TRAD first part OK");
}));
});
gulp.task('trad', gulp.series( 'createTradFile', 'copyBeforeTrad', 'retrieveTradObject', function( done ) {
var replace2 = require('gulp-string-replace');
var files = gulp.src(['fr/**/*.html', 'fr/**/*.js']);
for (var k in transObj)
{
if (transObj[k].ID)
{
console.log("TRAD " + transObj[k].ID + " TO " + transObj[k].LANG1);
files = files.pipe(replace2(new RegExp('\\+' + transObj[k].ID + '\\+', 'g'),
transObj[k].LANG1,
{'logs': {'enabled': true}}))
.pipe(chmod(755));
}
}
files.pipe(gulp.dest("fr"));
return files;
}));
So main idea here was to separate the two promises into task ( mainly for a better understanding of the code for later ) and then to do the files = files.pipe( ... ) Which is explained here : How to create repeating pipe in gulp?
Hope this can help !
I'm not sure I understand the question 100% so I'll take the dv's, but are talking about something like gulp-run-sequence?
You can do all sorts of tasking stuff like this
var gulp = require('gulp');
//webp images for optimization on some browsers
const webp = require('gulp-webp');
//responsive images!
var responsive = require('gulp-responsive-images');
//gulp delete for cleaning
var del = require('del');
//run sequence to make sure each gulp command completes in the right order.
var runSequence = require('run-sequence');
// =======================================================================//
// ! Default and bulk tasks //
// =======================================================================//
//default runs when the user types 'gulp' into CLI
//first clean is ran, then webp, then the rest are ran async.
//If you want something ran after, you can add something like 'example'
gulp.task('default',function(callback){
runSequence('clean','webp',['responsive-jpg','responsive-webp','copy-data','copy-sw'],'example'),callback
});
// =======================================================================//
// Images and fonts //
// =======================================================================//
gulp.task('responsive-jpg',function(){
gulp.src('src/images/*')
.pipe(responsive({
'*.jpg':[
{width:1600, suffix: '_large_1x', quality:40},
{width:800, suffix: '_medium_1x', quality:70},
{width:550, suffix: '_small_1x', quality:100}
]
}))
.pipe(gulp.dest('build/images'));
});
gulp.task('responsive-webp',function(){
gulp.src('src/images/*')
.pipe(responsive({
'*.webp':[
{width:1600, suffix: '_large_1x', quality:40},
{width:800, suffix: '_medium_1x', quality:70},
{width:550, suffix: '_small_1x', quality:80}
]
}))
.pipe(gulp.dest('build/images'));
});
gulp.task('webp', () =>
gulp.src('src/images/*.jpg')
.pipe(webp())
.pipe(gulp.dest('src/images'))
);
gulp.task('copy-data', function () {
gulp.src('./src/data/*.json')
.pipe(gulp.dest('./build/data'));
});
gulp.task('copy-sw', function () {
gulp.src('./src/sw.js')
.pipe(gulp.dest('./build/'));
});
In my example here, I clear out old files, then I convert any images that need to be converted to webp, then I async the tasks that can be run together. You can do this in any arrangement you need. You could create then a gulp task that even points to two gulp run sequence tasks to double down on the effectiveness.

Gulp default task unable to compress after copy

At first I thought this was related to dependency of tasks so I went with run-sequence and even tried defining dependencies within tasks themselves. But I cannot get the compress task to run after copy. Or, even if it says it did finish the compress task, the compression only works if I run compress in the task runner inside visual studio by itself. What else can I try to get it to compress after copy?
/// <binding BeforeBuild='default' />
/*
This file is the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. https://go.microsoft.com/fwlink/?LinkId=518007
*/
var gulp = require("gulp");
var debug = require("gulp-debug");
var del = require("del");
var uglify = require("gulp-uglify");
var pump = require("pump");
var runSequence = require("run-sequence");
var paths = {
bower: "./bower_components/",
lib: "./Lib/"
};
var modules = {
"store-js": ["store-js/dist/store.legacy.js"],
"bootstrap-select": [
"bootstrap-select/dist/css/bootstrap-select.css",
"bootstrap-select/dist/js/bootstrap-select.js",
"bootstrap-select/dist/js/i18n/*.min.js"
]
}
gulp.task("default", function (cb) {
runSequence("clean", ["copy", "compress"], cb);
});
gulp.task("clean",
function () {
return del.sync(["Lib/**", "!Lib", "!Lib/ReadMe.md"]);
});
gulp.task("compress",
function (cb) {
pump([
gulp.src(paths.lib + "**/*.js"),
uglify(),
gulp.dest(paths.lib)
], cb);
});
gulp.task("copy",
function (cb) {
prefixPathToModules();
copyModules();
cb();
});
function prefixPathToModules() {
for (var moduleIndex in modules) {
for (var fileIndex in modules[moduleIndex]) {
modules[moduleIndex][fileIndex] = paths.bower + modules[moduleIndex][fileIndex];
}
}
}
function copyModules() {
for (var files in modules) {
gulp.src(modules[files], { base: paths.bower })
.pipe(gulp.dest(paths.lib));
}
}
You use run-sequence and your code
runSequence("clean", ["copy", "compress"], cb);
run in such order
clean
copy and compress in parallel // that's why your code compresses nothing, because you have not copied files yet
cb
Write like this and compress will be after copy
runSequence("clean", "copy", "compress", cb);
I am not familiar with runSequence. But why don't you try the following. By this way your default task depends on compress and compress depends on copy. So, 'copy' will run first and then 'compress'
gulp.task('default', ['copy','compress'], function(cb){});
gulp.task('compress',['copy'], function(cb){});
Gulp returns a steam , since you are calling it in a for loop the stream is returned during the first iteration itself.
Update your copyModule to the following and you can try either runSequence like posted by Kirill or follow my approach
function copyModules() {
var inputFileArr = [];
for (var files in modules) {
inputFileArr = inputFileArr.concat(modules[files]);
};
return gulp.src(inputFileArr, { base: paths.bower })
.pipe(gulp.dest(paths.lib));
}

Gulp error: The following tasks did not complete: Did you forget to signal async completion?

I have the following gulpfile.js, which I'm executing via the command line gulp message:
var gulp = require('gulp');
gulp.task('message', function() {
console.log("HTTP Server Started");
});
I'm getting the following error message:
[14:14:41] Using gulpfile ~\Documents\node\first\gulpfile.js
[14:14:41] Starting 'message'...
HTTP Server Started
[14:14:41] The following tasks did not complete: message
[14:14:41] Did you forget to signal async completion?
I'm using gulp 4 on a Windows 10 system. Here is the output from gulp --version:
[14:15:15] CLI version 0.4.0
[14:15:15] Local version 4.0.0-alpha.2
Since your task might contain asynchronous code you have to signal gulp when your task has finished executing (= "async completion").
In Gulp 3.x you could get away without doing this. If you didn't explicitly signal async completion gulp would just assume that your task is synchronous and that it is finished as soon as your task function returns. Gulp 4.x is stricter in this regard. You have to explicitly signal task completion.
You can do that in six ways:
1. Return a Stream
This is not really an option if you're only trying to print something, but it's probably the most frequently used async completion mechanism since you're usually working with gulp streams. Here's a (rather contrived) example demonstrating it for your use case:
var print = require('gulp-print');
gulp.task('message', function() {
return gulp.src('package.json')
.pipe(print(function() { return 'HTTP Server Started'; }));
});
The important part here is the return statement. If you don't return the stream, gulp can't determine when the stream has finished.
2. Return a Promise
This is a much more fitting mechanism for your use case. Note that most of the time you won't have to create the Promise object yourself, it will usually be provided by a package (e.g. the frequently used del package returns a Promise).
gulp.task('message', function() {
return new Promise(function(resolve, reject) {
console.log("HTTP Server Started");
resolve();
});
});
Using async/await syntax this can be simplified even further. All functions marked async implicitly return a Promise so the following works too (if your node.js version supports it):
gulp.task('message', async function() {
console.log("HTTP Server Started");
});
3. Call the callback function
This is probably the easiest way for your use case: gulp automatically passes a callback function to your task as its first argument. Just call that function when you're done:
gulp.task('message', function(done) {
console.log("HTTP Server Started");
done();
});
4. Return a child process
This is mostly useful if you have to invoke a command line tool directly because there's no node.js wrapper available. It works for your use case but obviously I wouldn't recommend it (especially since it's not very portable):
var spawn = require('child_process').spawn;
gulp.task('message', function() {
return spawn('echo', ['HTTP', 'Server', 'Started'], { stdio: 'inherit' });
});
5. Return a RxJS Observable.
I've never used this mechanism, but if you're using RxJS it might be useful. It's kind of overkill if you just want to print something:
var of = require('rxjs').of;
gulp.task('message', function() {
var o = of('HTTP Server Started');
o.subscribe(function(msg) { console.log(msg); });
return o;
});
6. Return an EventEmitter
Like the previous one I'm including this for completeness sake, but it's not really something you're going to use unless you're already using an EventEmitter for some reason.
gulp.task('message3', function() {
var e = new EventEmitter();
e.on('msg', function(msg) { console.log(msg); });
setTimeout(() => { e.emit('msg', 'HTTP Server Started'); e.emit('finish'); });
return e;
});
An issue with Gulp 4.
For solving this problem try to change your current code:
gulp.task('simpleTaskName', function() {
// code...
});
for example into this:
gulp.task('simpleTaskName', async function() {
// code...
});
or into this:
gulp.task('simpleTaskName', done => {
// code...
done();
});
You need to do one thing:
Add async before function.
const gulp = require('gulp');
gulp.task('message', async function() {
console.log("Gulp is running...");
});
THIS WORKED!
The latest update on Feb 18, 2021, I found the problem after using the elder solution below, then I have fixed it by using the following instead for the next gulp version.
File: Package.json
...,
"devDependencies": {
"del": "^6.0.0",
"gulp": "^4.0.2",
},
...
File: gulpfile.js Example
const {task} = require('gulp');
const del = require('del');
async function clean() {
console.log('processing ... clean');
return del([__dirname + '/dist']);
}
task(clean)
...
Elder Version
gulp.task('script', done => {
// ... code gulp.src( ... )
done();
});
gulp.task('css', done => {
// ... code gulp.src( ... )
done();
});
gulp.task('default', gulp.parallel(
'script',
'css'
)
);
I was getting this same error trying to run a very simple SASS/CSS build.
My solution (which may solve this same or similar errors) was simply to add done as a parameter in the default task function, and to call it at the end of the default task:
// Sass configuration
var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task('sass', function () {
gulp.src('*.scss')
.pipe(sass())
.pipe(gulp.dest(function (f) {
return f.base;
}))
});
gulp.task('clean', function() {
})
gulp.task('watch', function() {
gulp.watch('*.scss', ['sass']);
})
gulp.task('default', function(done) { // <--- Insert `done` as a parameter here...
gulp.series('clean','sass', 'watch')
done(); // <--- ...and call it here.
})
Hope this helps!
This is an issue when migrating from gulp version 3 to 4, Simply you can add a parameter done to the call back function , see example,
const gulp = require("gulp")
gulp.task("message", function(done) {
console.log("Gulp is running...")
done()
});
I cannot claim to be very knowledgeable on this but I had the same problem and have resolved it.
There is a 7th way to resolve this, by using an async function.
Write your function but add the prefix async.
By doing this Gulp wraps the function in a promise, and the task will run without errors.
Example:
async function() {
// do something
};
Resources:
Last section on the Gulp page Async Completion: Using async/await.
Mozilla async functions docs.
You need to do two things:
Add async before function.
Start your function with return.
var gulp = require('gulp');
gulp.task('message', async function() {
return console.log("HTTP Server Started");
});
Workaround: We need to call the callback functions (Task and Anonymous):
function electronTask(callbackA)
{
return gulp.series(myFirstTask, mySeccondTask, (callbackB) =>
{
callbackA();
callbackB();
})();
}
Basically v3.X was simpler but v4.x is strict in these means of synchronous & asynchronous tasks.
The async/await is pretty simple & helpful way to understand the workflow & issue.
Use this simple approach
const gulp = require('gulp')
gulp.task('message',async function(){
return console.log('Gulp is running...')
})
Here you go: No synchronous tasks.
No synchronous tasks
Synchronous tasks are no longer supported. They often led to subtle mistakes that were hard to debug, like forgetting to return your streams from a task.
When you see the Did you forget to signal async completion? warning, none of the techniques mentioned above were used. You'll need to use the error-first callback or return a stream, promise, event emitter, child process, or observable to resolve the issue.
Using async/await
When not using any of the previous options, you can define your task as an async function, which wraps your task in a promise. This allows you to work with promises synchronously using await and use other synchronous code.
const fs = require('fs');
async function asyncAwaitTask() {
const { version } = fs.readFileSync('package.json');
console.log(version);
await Promise.resolve('some result');
}
exports.default = asyncAwaitTask;
My solution: put everything with async and await gulp.
async function min_css() {
return await gulp
.src(cssFiles, { base: "." })
.pipe(concat(cssOutput))
.pipe(cssmin())
.pipe(gulp.dest("."));
}
async function min_js() {
return await gulp
.src(jsFiles, { base: "." })
.pipe(concat(jsOutput))
.pipe(uglify())
.pipe(gulp.dest("."));
}
const min = async () => await gulp.series(min_css, min_js);
exports.min = min;
Solution is simple, but I outline the changes I made, the error I was getting, my gulpfile before and after, and the package versions--therefore making it appear very long.
I solved this by following the directions of multiple previous answers, in addition to following the error outputted when I would save my .scss file.
In short:
I changed how gulp-sass was imported—see (A)
I changed all functions to ASYNC functions—see (B)
(A) Changes made to gulp-sass import:
Before: var sass = require('gulp-sass)
After: var sass = require('gulp-sass')(require('sass'));
(B) Simply convert functions to ASYNC—
What my gulpfile looked like before:
'use strict';
// dependencies
var gulp = require('gulp');
var sass = require('gulp-sass');
var minifyCSS = require('gulp-clean-css');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var changed = require('gulp-changed');
var SCSS_SRC = './src/Assets/scss/**/*.scss';
var SCSS_DEST = './src/Assets/css';
function compile_scss() {
return gulp.src(SCSS_SRC)
.pipe(sass().on('error', sass.logError))
.pipe(minifyCSS())
.pipe(rename({ suffix: '.min' }))
.pipe(changed(SCSS_DEST))
.pipe(gulp.dest(SCSS_DEST));
}
function watch_scss() {
gulp.watch(SCSS_SRC, compile_scss);
}
gulp.task('default', watch_scss); //Run tasks
exports.compile_scss = compile_scss;
exports.watch_scss = watch_scss;
What my gulpfile looked like after:
'use strict';
// dependencies
var gulp = require('gulp');
//var sass = require('gulp-sass');
var sass = require('gulp-sass')(require('sass'));
var minifyCSS = require('gulp-clean-css');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var changed = require('gulp-changed');
var SCSS_SRC = './src/Assets/scss/**/*.scss';
var SCSS_DEST = './src/Assets/css';
async function compile_scss() {
return gulp.src(SCSS_SRC)
.pipe(sass().on('error', sass.logError))
.pipe(minifyCSS())
.pipe(rename({ suffix: '.min' }))
.pipe(changed(SCSS_DEST))
.pipe(gulp.dest(SCSS_DEST));
}
async function watch_scss() {
gulp.watch(SCSS_SRC, compile_scss);
}
gulp.task('default', watch_scss); // Run tasks
exports.compile_scss = compile_scss;
exports.watch_scss = watch_scss;
Package Versions:
"gulp": "^4.0.2",
"gulp-changed": "^4.0.3",
"gulp-rename": "^2.0.0",
"gulp-uglify": "^3.0.2",
"gulp-clean-css": "^4.3.0",
"gulp-sass": "^5.0.0",
"sass": "^1.38.0"
Error I was getting:
Error in plugin "gulp-sass"
Message:
gulp-sass 5 does not have a default Sass compiler; please set one yourself.
Both the `sass` and `node-sass` packages are permitted.
For example, in your gulpfile:
var sass = require('gulp-sass')(require('sass'));
[14:00:37] The following tasks did not complete: default, compile_scss
[14:00:37] Did you forget to signal async completion?
I got that solved, It's Pretty simple just add the below code snippet.
var gulp = require('gulp');
gulp.task('message', async function() {
console.log("HTTP Server Started");
});
I was struggling with this recently, and found the right way to create a default task that runs sass then sass:watch was:
gulp.task('default', gulp.series('sass', 'sass:watch'));
In gulp version 4 and over, it is required that all gulp tasks tell Gulp where the task will end. We do this by calling a function that is passed as the first argument in our task function
var gulp = require('gulp');
gulp.task('first_task', function(callback) {
console.log('My First Task');
callback();
})
Add done as a parameter in default function. That will do.
For those who are trying to use gulp for swagger local deployment, following code will help
var gulp = require("gulp");
var yaml = require("js-yaml");
var path = require("path");
var fs = require("fs");
//Converts yaml to json
gulp.task("swagger", done => {
var doc = yaml.safeLoad(fs.readFileSync(path.join(__dirname,"api/swagger/swagger.yaml")));
fs.writeFileSync(
path.join(__dirname,"../yourjsonfile.json"),
JSON.stringify(doc, null, " ")
);
done();
});
//Watches for changes
gulp.task('watch', function() {
gulp.watch('api/swagger/swagger.yaml', gulp.series('swagger'));
});
For me the issue was different: Angular-cli was not installed (I installed a new Node version using NVM and simply forgot to reinstall angular cli)
You can check running "ng version".
If you don't have it just run "npm install -g #angular/cli"
I know the problem was presented 6 years ago but probabily you missed return in your function.
I fixed this issue this morning with eslint, that gave me the same message after running "gulp lint" in my working directory.
Example:
function runLinter(callback)
{
return src(['**/*.js', '!node_modules/**'])
.pipe(eslint())
.on('end', ()=>
{
callback();
});
}
exports.lint = runLinter;
So I got the same error with Gulp 4, but the solution was different. I had the error:
"Did you forget to signal async completion?"
but before the error it also says:
"gulp-sass no longer has a default Sass compiler; please set one yourself"
I completely missed that part at first.
So I had this in the gulfile.js:
const sass = require('gulp-sass')
This should be changed to:
const sass = require('gulp-sass')(require('sass'));
Now it works.

Gulp use changed-in-place with multiple tasks that depend on each other

I'm using the gulp-changed-in-place package to only run certain Gulp tasks with the files that have changed (https://github.com/alexgorbatchev/gulp-changed-in-place). I'm having an issue where I only want to run my linting and code style tasks on changed files to speed up development time.
My current setup is as follows:
var gulp = require('gulp');
var changedInPlace = require('gulp-changed-in-place');
var eslint = require('gulp-eslint');
var jscs = require('gulp-jscs');
var config = {
paths: {
js: './app/**/*.js'
}
}
gulp.task('jscs', function() {
return gulp.src(config.paths.js)
.pipe(changedInPlace())
.pipe(jscs())
.pipe(jscs.reporter())
.pipe(jscs.reporter('fail'));
});
gulp.task('lint', ['jscs'], function() {
return gulp.src(config.paths.js)
.pipe(changedInPlace())
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});
gulp.task('js', ['lint'], function() {
// do some stuff
});
gulp.task('watch', function() {
gulp.watch(config.paths.js, ['js']);
});
The issue is probably pretty obvious. The js task has a dependency on the lint task which itself has a dependency on the jscs task - so the jscs task runs first. It accesses changedInPlace() which causes the cache to get updated and therefore the changedInPlace() call from the lint task doesn't think anything has changed and doesn't check the files I expect.
Has anyone used this package with this issue and do you have any suggestions on what to do? Also open to other ways of accomplishing the task - only running the js task on changed files.

Unexpected end of input prelude.js

I am trying to work to replicate a problem I am having adding React to an existing application. Unfortunately, at the moment I am running into a completely different problem simply trying to reproduce the original problem.
The basic structure is a new base module compiled by browserify that is then concatenated with the existing module which bootsraps the application for now.
var gulp = require('gulp');
var browserify = require('browserify');
var reactify = require('reactify');
var source = require('vinyl-source-stream');
var concat = require('gulp-concat');
gulp.task('default', ['browserify', 'concat']);
gulp.task('browserify', function(){
return browserify({
entries: ['./src/app.js'],
transform: [["reactify", {"es6": true}]],
extensions: ['.jsx'],
debug: true,
standalone: 'App'
}).bundle()
.pipe(source('browserifyPackage.js'))
.pipe(gulp.dest('./oldSrc'));
})
gulp.task('concat', ['browserify'], function(){
return gulp.src(['./oldSrc/browserifyPackage.js', './oldSrc/app.js'])
.pipe(concat('app.js'))
.pipe(gulp.dest('./'));
})
the new module is pretty simple
window.React = require('react');
module.exports = {
TodoSection: require('./todoSection')
}
And then the old app looks like this
_.extend(App, (function(){
return { init: function(){
React.render(new App.TodoSection(), document.getElementById('body'));
}}
}))
window.addEventListener('load', function() { App.init(); }, false).
When I try to use this file though I get an "Unexpected end of line" from within prelude.js in browserify. I don't see an obvious problem, but I am obviously missing something.
The complete example project can be found on Github
The issue is probably the period at the end of this line:
window.addEventListener('load', function() { App.init(); }, false).