Last active
September 15, 2016 08:35
-
-
Save insin/8521968 to your computer and use it in GitHub Desktop.
gulpfile for use with React, with flat imports from uniquely-named modules under /src
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
gulpfile from one of my React applications which has a gulp --production build | |
set up. | |
Assumptions: | |
1. All your own .js/.jsx modules are somewhere under ./src, have unique | |
filenames and use Node.js-style requires WITHOUT any path information, just | |
the name of another module somewhere under ./src | |
2. Dependencies are stored in the following directory structure: | |
./vendor | |
/js - uncompressed / dev builds of JS deps | |
/ min - pre-minified versions of JS deps | |
/css - uncompressed / dev builds of CSS deps | |
/ min - pre-minified versions of CSS deps | |
3. JS and CSS dependency filenames are in dep-name-1.2.3(.ext|.min.ext) format | |
Assumptions specific to the app this was pulled from: | |
1. Things there are only one of: | |
- Single JS entry point in ./src/app.js | |
- Single CSS file in ./public/css/style.css | |
- Single HTML file in ./public/index.html | |
2. Using Bootstrap, with glpyhicon fonts in ./vendor/fonts | |
*/ | |
var gulp = require('gulp') | |
var glob = require('glob') | |
var browserify = require('gulp-browserify') | |
var clean = require('gulp-clean') | |
var concat = require('gulp-concat') | |
var flatten = require('gulp-flatten') | |
var jshint = require('gulp-jshint') | |
var minifyCSS = require('gulp-minify-css') | |
var plumber = require('gulp-plumber') | |
var react = require('gulp-react') | |
var rename = require('gulp-rename') | |
var template = require('gulp-template') | |
var uglify = require('gulp-uglify') | |
var gutil = require('gulp-util') | |
// foo/bar/something-whatevs-1.2.3.blah => something-whatevs | |
function depName(path) { return path.split('/').pop().split(/-\d/).shift() } | |
// Creates a sorter which sorts files acording an object which maps dep names | |
// (see depname()) to orders. | |
function depSorter(order) { | |
return function(a, b) { return order[depName(a)] - order[depName(b)] } | |
} | |
// foo/bar/something-whatevs-1.2.3.blah => something-whatevs-1.2.3.blah | |
function fileName(path) { return path.split('/').pop() } | |
// Creates front-end paths with the given prefix and path file name (see fileName()) | |
function browserPaths(prefix, paths) { | |
return paths.map(function(path) { return prefix + fileName(path) }) | |
} | |
// Props are portion of dependency filenames prior to the version number | |
var jsDepOrder = { | |
jquery: 1 | |
, bootstrap: 2 | |
, react: 3 | |
, validator: 4 | |
} | |
var cssDepOrder = { | |
bootstrap: 1 | |
, 'bootstrap-theme': 2 | |
} | |
// JS files to be copied to /dist | |
var depDistJS = glob.sync(gutil.env.production | |
? './vendor/js/min/*.js' | |
: './vendor/js/*.js').sort(depSorter(jsDepOrder)) | |
var appDistJS = gutil.env.production ? './build/js/app.min.js' : './build/js/app.js' | |
var allDistJS = depDistJS.concat(appDistJS) | |
// Paths to be used as <script> src attributes | |
var headScripts = browserPaths('js/', allDistJS) | |
var appScript = headScripts.pop() | |
// CSS files to be copied to /dist | |
var depDistCSS = glob.sync(gutil.env.production | |
? './vendor/css/min/*.css' | |
: './vendor/css/*.css').sort(depSorter(cssDepOrder)) | |
var appDistCSS = gutil.env.production ? './build/css/style.min.css' : './build/css/style.css' | |
var allDistCSS = depDistCSS.concat(appDistCSS) | |
// Paths to be used as <link> href attributes | |
var headStyles = browserPaths('css/', allDistCSS) | |
// Deletes everything in the build and dist directories | |
gulp.task('clean', function() { | |
return gulp.src(['./build', './dist'], {read: false}) | |
.pipe(clean()) | |
}) | |
// Copies .js files directly into the build modules dir | |
gulp.task('copy-js-src', function() { | |
return gulp.src('./src/**/*.js') | |
.pipe(flatten()) | |
.pipe(gulp.dest('./build/modules')) | |
}) | |
// Compiles .jsx files to .js and copies directly into the build modules dir | |
gulp.task('compile-jsx', function() { | |
return gulp.src('./src/**/*.jsx') | |
.pipe(plumber()) | |
.pipe(react()) | |
.on('error', function(e) { | |
console.error(e.message + '\n in ' + e.fileName) | |
}) | |
.pipe(flatten()) | |
.pipe(gulp.dest('./build/modules')) | |
}) | |
// Lints the build modules dir | |
gulp.task('lint', ['copy-js-src', 'compile-jsx'], function() { | |
return gulp.src('./build/modules/*.js') | |
.pipe(jshint('./.jshintrc')) | |
.pipe(jshint.reporter('jshint-stylish')) | |
}) | |
// Bundles the app into a single file, hooking up the flat requires with same- | |
// named modules in the build modules dir. | |
gulp.task('build-js', ['lint'], function(){ | |
var stream = gulp.src(['./build/modules/app.js']) | |
.pipe(plumber()) | |
.pipe(browserify({ | |
debug: !gutil.env.production | |
})) | |
.on('prebundle', function(bundle) { | |
// Setting cwd as gulp-browserify is forcing browserify's basedir to be | |
// the dir containing the entry file. | |
glob.sync('*.js', {cwd: './build/modules'}).forEach(function(module) { | |
var expose = module.split('.').shift() | |
if (expose == 'app') return | |
bundle.require('./' + module, {expose: expose}) | |
}) | |
}) | |
.on('error', function(e) { | |
console.error(e) | |
}) | |
.pipe(concat('app.js')) | |
.pipe(gulp.dest('./build/js')) | |
if (gutil.env.production) { | |
stream = stream | |
.pipe(rename('app.min.js')) | |
.pipe(uglify()) | |
.pipe(gulp.dest('./build/js')) | |
} | |
return stream | |
}) | |
// Minifies CSS if this is a production build | |
gulp.task('build-css', function() { | |
var stream = gulp.src('./public/css/*.css') | |
.pipe(gulp.dest('./build/css')) | |
if (gutil.env.production) { | |
stream = stream | |
.pipe(minifyCSS()) | |
.pipe(rename({ext: '.min.css'})) | |
.pipe(gulp.dest('./build/css')) | |
} | |
return stream | |
}) | |
// Templates index.html to link to the appropriate resources for the environment | |
// being built for. | |
gulp.task('dist-html', function() { | |
return gulp.src('./public/index.html') | |
.pipe(template({ | |
headScripts: headScripts | |
, appScript: appScript | |
, headStyles: headStyles | |
})) | |
.pipe(gulp.dest('./dist')) | |
}) | |
// Copies built JS and dependencies to /dist | |
gulp.task('dist-js', ['build-js'], function() { | |
return gulp.src(allDistJS) | |
.pipe(gulp.dest('./dist/js')) | |
}) | |
// Copies built CSS and dependencies to /dist | |
gulp.task('dist-css', ['build-css'], function() { | |
return gulp.src(allDistCSS) | |
.pipe(gulp.dest('./dist/css')) | |
}) | |
// Copies images to /dist | |
gulp.task('dist-img', function() { | |
return gulp.src('./public/img/*') | |
.pipe(gulp.dest('./dist/img')) | |
}) | |
// Copies fonts to /dist (for Bootstrap glyphicons) | |
gulp.task('dist-fonts', function() { | |
return gulp.src('./vendor/fonts/*') | |
.pipe(gulp.dest('./dist/fonts')) | |
}) | |
// Rebuild/copy to dist when resources are changed | |
gulp.task('watch', function() { | |
gulp.watch(['./src/**/*.js', './src/**/*.jsx'], ['dist-js']) | |
gulp.watch('./public/css/*.css', ['dist-css']) | |
gulp.watch('./public/img/*', ['dist-img']) | |
gulp.watch('./public/index.html', ['dist-html']) | |
}) | |
gulp.task('default', ['clean'], function() { | |
gulp.start('dist-js', 'dist-css', 'dist-img', 'dist-html', 'dist-fonts', 'watch') | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title></title> | |
<% _.forEach(headStyles, function(href) { %> | |
<link rel="stylesheet" href="<%= href %>"><% }); %> | |
<% _.forEach(headScripts, function(src) { %> | |
<script src="<%= src %>"></script><% }); %> | |
</head> | |
<body> | |
<script src="<%= appScript %>"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"devDependencies": { | |
"browserify": "~3.20.0", | |
"glob": "~3.2.8", | |
"gulp": "~3.5.0", | |
"gulp-browserify": "~0.3.4", | |
"gulp-clean": "~0.2.4", | |
"gulp-concat": "~2.1.7", | |
"gulp-flatten": "0.0.2", | |
"gulp-jshint": "~1.3.4", | |
"gulp-minify-css": "~0.2.0", | |
"gulp-plumber": "~0.5.6", | |
"gulp-react": "~0.1.2", | |
"gulp-rename": "~0.2.2", | |
"gulp-template": "~0.1.1", | |
"gulp-uglify": "~0.2.0", | |
"gulp-util": "~2.2.13", | |
"jshint-stylish": "~0.1.5" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
where does this
gutil.env.production
variable is coming from?