From 7d8191ee37a4e085d23217f85e41f4da4c9e4069 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 8 Oct 2015 12:43:55 +0200 Subject: update web builds, use watchify --- web/gulpfile.js | 278 ++++++++++++++++++++++---------------------------------- 1 file changed, 108 insertions(+), 170 deletions(-) (limited to 'web/gulpfile.js') diff --git a/web/gulpfile.js b/web/gulpfile.js index b05998d3..83893c91 100644 --- a/web/gulpfile.js +++ b/web/gulpfile.js @@ -4,11 +4,12 @@ var packagejs = require('./package.json'); var conf = require('./conf.js'); // Sorted alphabetically! +var babelify = require('babelify'); var browserify = require('browserify'); var gulp = require("gulp"); var concat = require('gulp-concat'); var connect = require('gulp-connect'); -var jshint = require("gulp-jshint"); +var eslint = require('gulp-eslint'); var less = require("gulp-less"); var livereload = require("gulp-livereload"); var minifyCSS = require('gulp-minify-css'); @@ -18,26 +19,16 @@ var plumber = require("gulp-plumber"); var react = require("gulp-react"); var rename = require("gulp-rename"); var replace = require('gulp-replace'); -var rev = require("gulp-rev"); var sourcemaps = require('gulp-sourcemaps'); -var uglify = require('gulp-uglify'); +var gutil = require("gulp-util"); var _ = require('lodash'); var map = require("map-stream"); var reactify = require('reactify'); +var uglifyify = require('uglifyify'); var buffer = require('vinyl-buffer'); var source = require('vinyl-source-stream'); var transform = require('vinyl-transform'); - -// FIXME: react-with-addons.min.js for prod use issue -// FIXME: Sourcemap URLs don't work correctly. -// FIXME: Why don't we use gulp-rev's manifest feature? - -var manifest = { - "vendor.css": "vendor.css", - "app.css": "app.css", - "vendor.js": "vendor.js", - "app.js": "app.js", -}; +var watchify = require('watchify'); var vendor_packages = _.difference( _.union( @@ -47,45 +38,7 @@ var vendor_packages = _.difference( conf.js.vendor_excludes ); - -// Custom linting reporter used for error notify -var jsHintErrorReporter = function(){ - return map(function (file, cb) { - if (file.jshint && !file.jshint.success) { - file.jshint.results.forEach(function (err) { - if (err) { - var msg = [ - path.basename(file.path), - 'Line: ' + err.error.line, - 'Reason: ' + err.error.reason - ]; - notify.onError( - "Error: <%= error.message %>" - )(new Error(msg.join("\n"))); - } - }); - } - cb(null, file); - }) -}; - -function save_rev(){ - return map(function(file, callback){ - if (file.revOrigBase){ - manifest[path.basename(file.revOrigPath)] = path.basename(file.path); - } - callback(null, file); - }) -} - -var dont_break_on_errors = function(){ - return plumber( - function(error){ - notify.onError("Error: <%= error.message %>").apply(this, arguments); - this.emit('end'); - } - ); -}; +var handleError = {errorHandler: notify.onError("Error: <%= error.message %>")}; /* * Sourcemaps are a wonderful way to develop directly from the chrome devtools. @@ -94,193 +47,178 @@ var dont_break_on_errors = function(){ * a single misbehaving transform breaks everything. * Thus, we just manually fix all paths. */ -//Normalize \ to / on Windows. -function unixStylePath(filePath) { - return filePath.split(path.sep).join('/'); -} -// Hijack the sourceRoot attr to do our transforms -function fixSourceMapPaths(file){ +function fixSourceMaps(file) { file.sourceMap.sources = file.sourceMap.sources.map(function (x) { - return unixStylePath(path.relative(".", x)); + return path.relative(".", x).split(path.sep).join('/'); }); return "/"; } // Browserify fails for paths starting with "..". -function fixBrowserifySourceMapPaths(file){ - file.sourceMap.sources = file.sourceMap.sources.map(function (x) { - return x.replace("src/js/node_modules","node_modules"); +function fixBrowserifySourceMaps(file) { + file.sourceMap.sources = file.sourceMap.sources.map((x) => { + return x.replace("src/js/node_modules", "node_modules"); }); - return fixSourceMapPaths(file); + return fixSourceMaps(file); +} +function fixLessSourceMaps(file) { + file.sourceMap.sources = file.sourceMap.sources.map((x) => { + if(!x.startsWith("..")){ + return "../src/css/" + x; + } + return x.replace("src/js/node_modules", "node_modules"); + }); + return fixSourceMaps(file); } -gulp.task("fonts", function () { - return gulp.src(conf.fonts) - .pipe(gulp.dest(conf.static + "/fonts")) -}); - -function styles_dev(files) { - return (gulp.src(files) - .pipe(dont_break_on_errors()) +function styles(files, dev){ + return gulp.src(files) + .pipe(dev ? plumber(handleError) : gutil.noop()) .pipe(sourcemaps.init()) .pipe(less()) - .pipe(sourcemaps.write(".", {sourceRoot: fixSourceMapPaths})) + .pipe(dev ? gutil.noop() : minifyCSS()) + .pipe(sourcemaps.write(".", {sourceRoot: fixLessSourceMaps})) .pipe(gulp.dest(conf.static)) - .pipe(livereload({ auto: false }))); + .pipe(livereload({auto: false})); } -gulp.task("styles-app-dev", function(){ - styles_dev(conf.css.app); +gulp.task("styles-app-dev", function () { + styles(conf.css.app, true); }); -gulp.task("styles-vendor-dev", function(){ - styles_dev(conf.css.vendor); +gulp.task("styles-vendor-dev", function () { + styles(conf.css.vendor, true); }); - - -function styles_prod(files) { - return (gulp.src(files) - .pipe(less()) - .pipe(minifyCSS()) - .pipe(rev()) - .pipe(save_rev()) - .pipe(gulp.dest(conf.static)) - .pipe(livereload({ auto: false }))); -} -gulp.task("styles-app-prod", function(){ - styles_prod(conf.css.app); +gulp.task("styles-app-prod", function () { + styles(conf.css.app, false); }); -gulp.task("styles-vendor-prod", function(){ - styles_prod(conf.css.vendor); +gulp.task("styles-vendor-prod", function () { + styles(conf.css.app, false); }); -function vendor_stream(debug){ - var vendor = browserify(vendor_packages, {debug: debug}); - _.each(vendor_packages, function(v){ - vendor.require(v); +function buildScript(bundler, filename, dev) { + if (dev) { + bundler = watchify(bundler); + } else { + bundler = bundler.transform({global: true}, uglifyify); + } + + function rebundle() { + return bundler.bundle() + .pipe(dev ? plumber(handleError) : gutil.noop()) + .pipe(source('bundle.js')) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(rename(filename)) + .pipe(sourcemaps.write('.', {sourceRoot: fixBrowserifySourceMaps})) + .pipe(gulp.dest(conf.static)) + .pipe(livereload({auto: false})); + } + + // listen for an update and run rebundle + bundler.on('update', rebundle); + bundler.on('log', gutil.log); + + // run it once the first time buildScript is called + return rebundle(); +} + +function vendor_stream(dev) { + var bundler = browserify({ + entries: [], + debug: true, + cache: {}, // required for watchify + packageCache: {} // required for watchify }); - return vendor.bundle() - .pipe(source("dummy.js")) - .pipe(rename("vendor.js")); + for (var vp of vendor_packages) { + bundler.require(vp); + } + return buildScript(bundler, "vendor.js", dev); } -gulp.task("scripts-vendor-dev", function (){ - return vendor_stream(false) - .pipe(gulp.dest(conf.static)); +gulp.task("scripts-vendor-dev", function () { + return vendor_stream(true); }); -gulp.task("scripts-vendor-prod", function(){ - return vendor_stream(false) - .pipe(buffer()) - .pipe(uglify()) - .pipe(rev()) - .pipe(save_rev()) - .pipe(gulp.dest(conf.static)); +gulp.task("scripts-vendor-prod", function () { + return vendor_stream(false); }); - -function app_stream(debug) { - var browserified = transform(function(filename) { - var b = browserify(filename, {debug: debug}); - _.each(vendor_packages, function(v){ - b.external(v); - }); - b.transform(reactify); - return b.bundle(); +function app_stream(dev) { + var bundler = browserify({ + entries: [conf.js.app], + debug: true, + cache: {}, // required for watchify + packageCache: {} // required for watchify }); - - return gulp.src([conf.js.app], {base: "."}) - .pipe(dont_break_on_errors()) - .pipe(browserified) - .pipe(sourcemaps.init({ loadMaps: true })) - .pipe(rename("app.js")); + for (var vp of vendor_packages) { + bundler.external(vp); + } + bundler = bundler.transform(babelify).transform(reactify); + return buildScript(bundler, "app.js", dev); } - gulp.task('scripts-app-dev', function () { - return app_stream(true) - .pipe(sourcemaps.write('./', {sourceRoot: fixBrowserifySourceMapPaths})) - .pipe(gulp.dest(conf.static)) - .pipe(livereload({ auto: false })); + return app_stream(true); }); - gulp.task('scripts-app-prod', function () { - return app_stream(true) - .pipe(buffer()) - .pipe(uglify()) - .pipe(rev()) - .pipe(sourcemaps.write('./', {sourceRoot: fixBrowserifySourceMapPaths})) - .pipe(save_rev()) - .pipe(gulp.dest(conf.static)); + return app_stream(false); }); -gulp.task("jshint", function () { - return gulp.src(conf.js.jshint) - .pipe(dont_break_on_errors()) - .pipe(react()) - .pipe(jshint()) - .pipe(jshint.reporter("jshint-stylish")) - .pipe(jsHintErrorReporter()); +gulp.task("eslint", function () { + return gulp.src(conf.js.eslint) + .pipe(plumber(handleError)) + .pipe(eslint()) + .pipe(eslint.format()) }); -gulp.task("copy", function(){ +gulp.task("copy", function () { return gulp.src(conf.copy, {base: conf.src}) .pipe(gulp.dest(conf.static)); }); -function templates(){ + +gulp.task('templates', function(){ return gulp.src(conf.templates, {base: conf.src}) - .pipe(replace(/\{\{\{(\S*)\}\}\}/g, function(match, p1) { - return manifest[p1]; - })) .pipe(gulp.dest(conf.dist)); -} -gulp.task('templates', templates); +}); gulp.task("peg", function () { return gulp.src(conf.peg, {base: conf.src}) - .pipe(dont_break_on_errors()) + .pipe(plumber(handleError)) .pipe(peg()) .pipe(gulp.dest("src/")); }); -gulp.task('connect', function() { - if(conf.connect){ - connect.server({ - port: conf.connect.port - }); - } -}); - gulp.task( "dev", [ - "fonts", "copy", "styles-vendor-dev", "styles-app-dev", "scripts-vendor-dev", "peg", "scripts-app-dev", - ], - templates + "templates" + ] ); gulp.task( "prod", [ - "fonts", "copy", "styles-vendor-prod", "styles-app-prod", "scripts-vendor-prod", "peg", "scripts-app-prod", - ], - templates + "templates" + ] ); -gulp.task("default", ["dev", "connect"], function () { +gulp.task("default", ["dev"], function () { livereload.listen({auto: true}); gulp.watch(["src/css/vendor*"], ["styles-vendor-dev"]); - gulp.watch(conf.peg, ["peg", "scripts-app-dev"]); - gulp.watch(["src/js/**"], ["scripts-app-dev", "jshint"]); gulp.watch(["src/css/**"], ["styles-app-dev"]); + gulp.watch(conf.templates, ["templates"]); + gulp.watch(conf.peg, ["peg"]); + gulp.watch(["src/js/**"], ["eslint"]); + // other JS is handled by watchify. gulp.watch(conf.copy, ["copy"]); }); -- cgit v1.2.3