gangle
Version:
GANGLE! is the most over opinionated Javascript build system and webserver ever. It watches your JS files, concats them to the folder it expects and runs browser-sync to watch your changes and auto refresh the browser.
174 lines (149 loc) • 7.5 kB
JavaScript
#!/usr/bin/env node
////////////////////////////////////////////////////////////////////////////////////////////////
// GANGLE! is the most over opinionated Javascript build system and webserver ever. It watches
// your JS files, concats them to the folder it expects and runs borwser-sync to watch your
// changes and auto refresh the browser. It's nuts, but for every day light use, it's cool.
////////////////////////////////////////////////////////////////////////////////////////////////
var fs = require('fs');
var watch = require('node-watch');
var browserSync = require("browser-sync").create('gangle');
'use strict'
// Let's create some variables that we can use to store program state
var directoryList = ['./'];
var filesToConcat = [];
var distributionDirectory = './dist';
var fileBuffers = [];
// We need to know which directories to include - this needs to be read from a file though TODO.
var excludedDirectories = ['./.git','./node_modules','./dist'];
// HOW IT ALL HANGS TOGETHER
// OK, let's start everything off by setting up the directories to watch, once this is
// done, we call the success of the promise, create a list of folders to watch, and when these
// are all executed, we start the server.
console.log('-------------------------------------');
console.log('Gangle Started. ')
console.log('-------------------------------------');
GetDirectories('./')
.then(function () {
var promiseQueue = [];
directoryList.forEach(dir => {
promiseQueue.push(WatchFolder(dir));
});
// Bundle these promises together before we start the server to ensure all
// work has been done before serving files.
Promise.all(promiseQueue).then(foldersWatched => {
console.log(foldersWatched);
StartBrowserSync();
})
.catch(error => {
console.log('ERROR BAD! ', error);
});
})
.catch(error => {
console.log('ERRORZ! ', error);
});
////////////////////////////////////////////////////////////////////////////////////////////////
// Setup a watcher on a particular folder,
// TO DO : this will read the gangle.config.js configuration file for files to ignore
////////////////////////////////////////////////////////////////////////////////////////////////
function WatchFolder (folderToWatch) {
return new Promise(function executePromise (resolve, reject) {
fs.watch(folderToWatch, {encoding: 'buffer'}, (eventType, filename) => {
if (filename && filename != 'all.min.js') {
CleanFolders()
.then(function (ok){
// Concatenate the files to disk
GetFileBuffers()
.then(function (e){
var p = fs.writeFileSync(distributionDirectory + '/all.min.js', Buffer.concat(fileBuffers));
browserSync.reload();
});
});
}
});
resolve('Watching folder: ' + folderToWatch);
});
}
// Reads the contents of the watched filed.
function GetFileBuffers () {
return new Promise(function (resolve, reject) {
console.log('Getting buffers...', filesToConcat)
filesToConcat.map(function (file) {
var fileContent = fs.readFileSync(file);
var newline = new Buffer('\n');
fileBuffers.push(fileContent);
fileBuffers.push(newline);
});
resolve();
})
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Ensures that the dist folder is created and cleared before the build cycle
////////////////////////////////////////////////////////////////////////////////////////////////
function CleanFolders () {
return new Promise(function (resolve, reject) {
// Create the distribution directory.
if (!fs.existsSync(distributionDirectory)){
fs.mkdirSync(distributionDirectory);
}
if (fs.existsSync(distributionDirectory + '/all.min.js')){
fs.unlinkSync(distributionDirectory + '/all.min.js');
}
resolve('Clean up completed.......!');
})
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Traverse the directory tree and add all directories to a list to watch, returns a
// promise so that we can perform this action async without blocking
////////////////////////////////////////////////////////////////////////////////////////////////
function GetDirectories (dir) {
return new Promise(function executePromise (resolve, reject) {
var files = fs.readdirSync(dir);
if (excludedDirectories.indexOf(dir) == -1) {
// Take each file that is in the files list, and check if they are a directory, if they are
// add them to the watch list, if not, we want to run the function to see if we want to add the file.
files.map(function (file) {
// If the current file is a directory and not in the excluded or watch list already
if (fs.statSync(dir + '/' + file).isDirectory() && directoryList.indexOf(dir + file) == -1 && excludedDirectories.indexOf(dir + file) == -1) {
// Add the directory to the watch list and let's look up in that directory
directoryList.push(dir + '/' + file);
GetDirectories(dir + '/' + file)
.then(function () {
})
.catch(err => {
console.log('FATAL EVIL ERROR! ', error);
});
}
else {
AddFilesToConcatList(dir, file);
}
});
}
resolve();
});
};
////////////////////////////////////////////////////////////////////////////////////////////////
// Starts up browser sync
////////////////////////////////////////////////////////////////////////////////////////////////
function StartBrowserSync () {
console.log('-------------------------------------');
console.log('Gangle Starting Browser Sync.')
console.log('-------------------------------------');
// Initialise Browser sync now
browserSync.init({
server: ".",
port: 9001
}, function () {
console.log('-------------------------------------');
console.log('Gangle Complete, ready to code :)')
console.log('-------------------------------------');
});
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Runs the rules on whether to add the file to the list to concat.
////////////////////////////////////////////////////////////////////////////////////////////////
function AddFilesToConcatList (dir, file) {
if (file.indexOf('.js') > 0 && file.indexOf('.json') == -1&& file.indexOf('all.min.js') == -1 && filesToConcat.indexOf(dir + '/' + file) == -1) {
console.log('+ ' + dir + '/' + file) ;
filesToConcat.push(dir + '/' + file);
}
};