Skip to content

Instantly share code, notes, and snippets.

@artemgurzhii
Last active December 24, 2017 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artemgurzhii/9f56401a227eaffd094205e1c7b0fdcb to your computer and use it in GitHub Desktop.
Save artemgurzhii/9f56401a227eaffd094205e1c7b0fdcb to your computer and use it in GitHub Desktop.
JS dynamic Code Splitting
import {
Router
} from './helpers/router/lib';
const router = new Router({
mode: 'history',
root: '/'
});
router
.add(/posts/, () => {
// Those files will be executed only on the routes, which urls match `/posts/` regexp.
Promise.all([
import('./controllers/posts'),
import('./controllers/comments')
]).then(([Posts, Comments]) => {
new Posts.default(),
new Comments.default()
})
}).add(() => {
// This file will be executed on all routes.
import('./controllers/application').then(Application => new Application.default);
})
.listen()
.exec();
// This code is tooked directly from my projects and can(should) be customized for your use.
//==================
// Used for the implicity
// Can be replaced with:
// isPresent(obj) && isPresent(obj.key) -> obj && obj.key
import { isPresent } from '../../is/lib';
/**
* Routing system for the app.
*
* @class
* @classdesc Routing system.
*
* @example
* new Router({ mode: 'history', root: '/' });
*/
export default class Router {
constructor(options) {
this._routes = [];
this._mode = (
isPresent(options) && options.mode === 'history' && isPresent(history.pushState)
) ? 'history' : 'hash';
this._root = options && options.root ? options.root : '/';
}
/**
* @description Get current route.
*
* @return {String} Current route
*/
get() {
let route = '';
if (this._mode === 'history') {
const URI = decodeURI(window.location.pathname + window.location.search);
route = this.removeSlashes(URI).replace(/\?(.*)$/, '');
if (this._root !== '/') {
route = route.replace(this._root, '');
}
} else {
const match = window.location.href.match(/#(.*)$/);
route = match ? match[1] : '';
}
return this.removeSlashes(route);
}
/**
* @description Removes slashes from the beggining and the end.
*
* @param {String} path - Path from which to remove slashed.
* @return {String} Cleared path without slashes.
*/
removeSlashes(path) {
return path
.toString()
.replace(/\/$/, '')
.replace(/^\//, '');
}
/**
* @description Add a new route to handle.
*
* @param {Object} pattern - Pattern to which route should match.
* @return {This}
*/
add(pattern, handler) {
if (typeof pattern === 'function') {
handler = pattern;
pattern = '';
}
this._routes.push({
pattern,
handler
});
return this;
}
/**
* @description Remove route from router.
*
* @param {String|Object} param - Route to remove.
* @return {This}
*/
remove(param) {
this._routes.forEach((route, i) => {
if (route.handler === param || route.pattern.toString() === param.toString()) {
this._routes.splice(i, 1);
return this;
}
});
return this;
}
/**
* @description Drop all router settings.
*
* @return {This}
*/
clean() {
this._routes = [];
this._mode = null;
this._root = '/';
return this;
}
/**
* @description Execute code for special router
*
* @param {String} path - Path which code to execute
* @return {This}
*/
exec(path = this.get()) {
this._routes.forEach(route => {
const match = path.match(route.pattern);
if (isPresent(match)) {
match.shift();
route.handler.apply({}, match);
return this;
}
});
return this;
}
/**
* @description Listen for the page path change.
*
* @return {This}
*/
listen() {
let current = this.get();
clearInterval(this.interval);
this.interval = setInterval(() => {
if (current !== this.get()) {
current = this.get();
this.exec(current);
}
}, 50);
return this;
}
/**
* @description Navigate to other route.
*
* @param {String} [path=''] - Path to which navigate.
* @return {This}
*/
navigateTo(path = '') {
if (this._mode === 'history') {
history.pushState(null, null, this._root + this.removeSlashes(path));
} else {
window.location.href = `${window.location.href.replace(/#(.*)$/, '')}#${path}`;
}
return this;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment