Skip to content

Commit

Permalink
fix: bundles will be serve better while developing
Browse files Browse the repository at this point in the history
  • Loading branch information
gerard2perez committed Sep 20, 2017
1 parent 35e3dc8 commit 5dbaa08
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 124 deletions.
21 changes: 12 additions & 9 deletions koaton
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#!/usr/bin/env node
process.env.NODE_ENV = process.argv.indexOf('-p') > -1 || process.argv.indexOf('--production') > -1 ? 'production' : 'development';
process.env.DEBUG = 'koaton';
// require('./lib');
require('babel-register')({
babelrc: false,
plugins: [
'babel-plugin-transform-koaton-es6-modules'
]
});
require('./src');

if (__dirname.indexOf('Development') > -1) {
require('babel-register')({
babelrc: false,
plugins: [
'babel-plugin-transform-koaton-es6-modules'
]
});
require('./src');
} else {
require('./lib');
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"make-help": "node help2md.js"
},
"dependencies": {
"babel-plugin-transform-koaton-es6-modules": "^1.0.0",
"chokidar": "^1.5.0",
"cmd-line": "^1.0.2",
"colors": "^1.1.2",
Expand All @@ -38,12 +39,11 @@
"inflection": "^1.12.0",
"less": "^2.7.1",
"less-plugin-clean-css": "^1.5.1",
"node-notifier": "^5.0.2",
"node-notifier": "^5.1.2",
"node-sass": "^4.5.0",
"node-sass-css-importer": "0.0.3",
"passport-local": "^1.0.0",
"uglify-js": "^3.0.27",
"babel-plugin-transform-koaton-es6-modules": "^1.0.0",
"upath": "^1.0.0"
},
"devDependencies": {
Expand Down
5 changes: 3 additions & 2 deletions src/commands/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { sync as glob } from 'glob';
import copystatic from '../support/CopyStatic';
import utils from '../utils';
import Command from 'cmd-line/lib/Command';
import BundleItem from '../support/BundleItem';
import BundleItem from 'koaton/support/BundleItem';
// import spin from '../spinner';
import { buildNginx } from '../functions/nginx';
import { buildAllImages } from '../functions/imagecompressor';
Expand Down Expand Up @@ -142,6 +142,7 @@ async function buildJS (target, bundle, development, onlypaths, logger) {
let error = [];
process.stdout.write(`Building ${target} `);
let start = process.hrtime();
console.log(BundleItem);
const ITEM = scfg.bundles[target] || new BundleItem(target, []);
ITEM.clear();
utils.writeuseslog = logger;
Expand Down Expand Up @@ -197,7 +198,7 @@ async function buildJS (target, bundle, development, onlypaths, logger) {
if (error.length > 0) {
console.log(error.join('\n'));
}
return AllFiles;
return {[target]: AllFiles};
};

export { buildCSS, buildJS };
Expand Down
3 changes: 3 additions & 0 deletions src/commands/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,10 @@ export default (new Command(__filename, 'Runs your awsome Koaton applicaction es
WatchFileToCopy();
await WactchAndCompressImages();
}
console.log(0);
await Events('pre', 'build');
await Events('pre', 'ember_build');
console.log(0);
let buildingAppsEmber = Object.entries(embercfg).map(([app, cfg]) => (new EmberBuilder(app, 'development', cfg)));
screen.line1(true);
const building = spinner();
Expand All @@ -137,6 +139,7 @@ export default (new Command(__filename, 'Runs your awsome Koaton applicaction es
});
await Events('post', 'ember_build');
return Events('pre', 'serve').then(() => {
console.log(0);
return new Promise(function (resolve, reject) {
let server = deamon(resolve, reject, EmberPids, nginxbuilt);
/* istanbul ignore next */
Expand Down
67 changes: 64 additions & 3 deletions src/support/BundleItem.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import * as path from 'upath';
import { watch as Watch } from 'chokidar';
import { buildCSS, buildJS } from '../commands/build';

const builder = {
css: buildCSS,
js: buildJS
};
const bundletemplates = {
'.css': (file) => {
return `<link rel='stylesheet' href='${file}'>`;
Expand All @@ -17,13 +23,33 @@ const bundletemplates = {
* @param {string|string[]} source File(s) that will be bundled.
*/
export default class BundleItem {
async build (logger) {
try {
this.sources.forEach(f => {
this.watcher.unwatch(f);
});
} catch (Ex) { }
let data = await builder[this.kind](this.file, this, configuration.server.env === 'development', false, logger);
let sources = [];
let files = [];
for (const key in data) {
files.push(key);
sources = sources.concat(data[key]);
}
this.sources = sources;
sources.forEach(f => {
this.watcher.add(f);
});
return files;
}
valueOf () {
return this.file;
}
constructor (target, source) {
constructor (target, source, watch = false) {
this.sources = [];
Object.defineProperty(this, 'kind', {
enumerable: false,
value: target.replace(path.trimExt(target), '')
value: target.replace(path.trimExt(target), '').replace('.', '')
});
Object.defineProperty(this, 'file', {
enumerable: true,
Expand All @@ -34,16 +60,51 @@ export default class BundleItem {
enumerable: false,
value: source instanceof Array ? source : (source ? [source] : [])
});
if (watch) {
this.watcher = new Watch(this.content, {
persistent: true,
ignoreInitial: true,
alwaysStat: false,
awaitWriteFinish: {
stabilityThreshold: 300,
pollInterval: 100
}
});
}
}
watch (fn) {
if (!this.watcher) {
this.watcher = new Watch(this.content, {
persistent: true,
ignoreInitial: true,
alwaysStat: false,
awaitWriteFinish: {
stabilityThreshold: 300,
pollInterval: 100
}
});
this.content.forEach(f => {
this.watcher.unwatch(f);
});
}
this.watchfn = fn;
this.watcher.on('change', fn);
}
add (item) {
if (this.content.indexOf(item) === -1) {
this.content.push(item);
}
return this;
}
remove (item) {
if (this.content.indexOf(item) > -1) {
this.content.splice(this.content.indexOf(item), 1);
}
return this;
}
clear () {
while (this.content.length > 0) {
this.content.pop();
this.watcher.unwatch(this.content.pop());
}
return this;
}
Expand Down
184 changes: 76 additions & 108 deletions src/support/CheckBundles.js
Original file line number Diff line number Diff line change
@@ -1,128 +1,96 @@
import spin from '../spinner';
import * as fs from 'fs-extra';
import livereload from '../utils/livereload';
import mkdir from '../utils/mkdir';
import canAccess from '../utils/canAccess';
import notifier from './Notifier';
import BundleItem from './BundleItem';
import {buildCSS, buildJS} from '../commands/build';
import {watch as Watch} from 'chokidar';
import * as path from 'upath';
import { hasChanged, getDiferences } from './DetectChangesInArray';
import { watch as Watch } from 'chokidar';
import { resolve } from 'path';
import hasfile from '../utils/hasfile';

let allBundles = {};
let hashes = {};
const spinner = spin();
let BundleMappings = {}, production;
const DetectChanges = async function () {
console.log(arguments);
const newconf = requireNoCache(ProyPath('config', 'bundles.js')).default;
for (const bundle of Object.keys(newconf)) {
newconf[bundle] = new BundleItem(bundle, newconf[bundle]);
function reloadFiles (bundle, files) {
for (const file of files) {
livereload.reload(`/${bundle.kind}/${file}`);
notifier('Koaton', `Reloading /${bundle.kind}/${file}`);
}
}
async function onChange (bundle, file) {
let filepath = resolve(file);
let newhash = await hasfile(file);
if (newhash !== hashes[filepath]) {
hashes[filepath] = newhash;
reloadFiles(bundle, await bundle.build());
}
}
async function makehashes (files) {
for (const file of files) {
hashes[resolve(file)] = await hasfile(file);
}
}
async function DetectChanges (changed) {
const newconf = requireNoCache(ProyPath('config', 'bundles.js')).default;
for (const bundle of Object.keys(newconf)) {
let mustrebuild = false;
if (allBundles[bundle]) {
let current = allBundles[bundle].content;
let incoming = newconf[bundle];
let added = incoming.filter(o => { return current.indexOf(o) === -1; });
let removed = current.filter(o => { return incoming.indexOf(o) === -1; });
for (const add of added) {
mustrebuild = true;
allBundles[bundle].add(add);
hashes[resolve(add)] = await hasfile(add);
}
let branches = Object.keys(newconf).concat(Object.keys(configuration.bundles));
branches = branches.filter((f, i) => branches.indexOf(f) === i);
for (const branch of branches) {
if (hasChanged(configuration.bundles[branch], newconf[branch])) {
let _new = newconf[branch] ? newconf[branch].content : undefined;
let _old = configuration.bundles[branch] ? configuration.bundles[branch].content : undefined;
let differences = getDiferences(_old, _new);
let reload = differences.added[0];
if (differences.deleted) {
const bundle = scfg.bundles[branch];
for (const target of bundle) {
let wtc = path.basename(target);
BundleMappings[wtc].Watcher.close();
delete BundleMappings[wtc];
}
console.log(`UnWatching ${branch}`);
} else if (differences.isnew) {
await getMapping(newconf[branch]);
console.log(`Watching ${branch}`);
console.log(differences.added);
} else {
BundleMappings[branch].Watcher.unWatch(differences.removed);
BundleMappings[branch].Watcher.add(differences.added);
console.log('touching', reload);
fs.closeSync(fs.openSync(reload, 'a'));
}
}
for (const remove of removed) {
mustrebuild = true;
allBundles[bundle].remove(remove);
delete hashes[resolve(remove)];
}
configuration.bundles = newconf;
},
RebuildAndReload = async function (bundle, compiledFile, sources, build) {
let target = await build(bundle.file, bundle, !production);
let files = [];
for (const file of scfg.bundles[bundle.file].content) {
files.push(file);
livereload.reload(file);
} else {
mustrebuild = true;
allBundles[bundle] = new BundleItem(bundle, newconf[bundle], true);
allBundles[bundle].watch(onChange.bind(null, allBundles[bundle]));
scfg.bundles.add(bundle, []);
}
notifier('Koaton', `Reloading ${bundle.file} -> ${files.join(',')}`);
},
logger = function (msg) {
spinner.update(msg.replace(/\n|\t/igm, ''));
},
getMapping = async function getMapping (bundle) {
if (bundle.kind === '.css') {
let buildresult;
buildresult = await buildCSS(bundle.file, bundle, !production, production && !(canAccess(ProyPath('public', 'css', bundle))), logger);
for (const b of Object.keys(buildresult)) {
BundleMappings[b] = {
Target: b,
Source: buildresult[b],
Bundle: bundle,
Build: buildCSS,
Watcher: new Watch(buildresult[b], {
persistent: true,
ignoreInitial: true,
alwaysStat: false,
awaitWriteFinish: {
stabilityThreshold: 300,
pollInterval: 100
}
})
};
}
allBundles[bundle].isUpdating = true;
if (mustrebuild) {
reloadFiles(allBundles[bundle], await allBundles[bundle].build());
}
}
for (const bundle in allBundles) {
if (!allBundles[bundle].isUpdating) {
allBundles[bundle].watcher.close();
delete allBundles[bundle];
scfg.bundles.remove(bundle);
} else {
BundleMappings[bundle.file] = {
Target: bundle.file,
Bundle: bundle,
Source: bundle.content,
Build: buildJS,
Watcher: new Watch(await buildJS(bundle.file, bundle, !production, production && !canAccess(ProyPath('public', 'js', bundle)), logger), {
persistent: true,
ignoreInitial: true,
alwaysStat: false,
awaitWriteFinish: {
stabilityThreshold: 300,
pollInterval: 100
}
})
};
allBundles[bundle].isUpdating = false;
}
};
}
}
function logger (msg) {
spinner.update(msg.replace(/\n|\t/igm, ''));
}
const bWatcher = new Watch(ProyPath('config', 'bundles.js'), {
persistent: true,
ignoreInitial: true,
alwaysStat: false,
awaitWriteFinish: {
stabilityThreshold: 300,
pollInterval: 100
}
});
bWatcher.on('change', DetectChanges);
async function checkbundles () {
spinner.start(50, 'Building Bundles'.green, undefined, process.stdout.columns);
await mkdir(ProyPath('public', 'css'), null);
await mkdir(ProyPath('public', 'js'), null);
production = scfg.env === 'production';
const bWatcher = new Watch(ProyPath('config', 'bundles.js'), {
persistent: true,
ignoreInitial: true,
alwaysStat: false,
awaitWriteFinish: {
stabilityThreshold: 300,
pollInterval: 100
}
});
bWatcher.on('change', DetectChanges);
for (const bundle of configuration.bundles) {
await getMapping(bundle);
}
makeObjIterable(BundleMappings);
if (!production) {
for (const element of BundleMappings) {
let rebuild = RebuildAndReload.bind(null, element.Bundle, element.Target, element.Sources, element.Build);
element.Watcher.on('change', rebuild);
}
let b = allBundles[bundle.file] = new BundleItem(bundle.file, bundle.content, true);
await b.build(logger);
b.watch(onChange.bind(null, b));
makehashes(b.sources);
}
spinner.end(` ${__ok.green} Bundles Built`);
return true;
Expand Down
Loading

0 comments on commit 5dbaa08

Please sign in to comment.