Demonstrate lazy-loading for Webpack-bundled KO components

This commit is contained in:
SteveSandersonMS
2016-03-08 17:03:09 +00:00
parent 25ba7986d8
commit 11d4873164
5 changed files with 36 additions and 4 deletions

View File

@@ -3,6 +3,7 @@ import 'bootstrap/dist/css/bootstrap.css';
import './css/site.css';
import * as ko from 'knockout';
import { createHistory } from 'history';
import './webpack-component-loader';
// Load and register the <app-root> component
ko.components.register('app-root', require('./components/app-root/app-root').default);

View File

@@ -1,5 +1,6 @@
import * as ko from 'knockout';
import { Route, Router } from '../../router';
import navMenu from '../nav-menu/nav-menu';
// Declare the client-side routing configuration
const routes: Route[] = [
@@ -18,10 +19,13 @@ class AppRootViewModel {
this.route = this._router.currentRoute;
// Load and register all the KO components needed to handle the routes
ko.components.register('nav-menu', require('../nav-menu/nav-menu').default);
ko.components.register('home-page', require('../home-page/home-page').default);
ko.components.register('counter-example', require('../counter-example/counter-example').default);
ko.components.register('fetch-data', require('../fetch-data/fetch-data').default);
// The optional 'bundle?lazy!' prefix is a Webpack feature that causes the referenced modules
// to be split into separate files that are then loaded on demand.
// For docs, see https://github.com/webpack/bundle-loader
ko.components.register('nav-menu', navMenu);
ko.components.register('home-page', require('bundle?lazy!../home-page/home-page'));
ko.components.register('counter-example', require('bundle?lazy!../counter-example/counter-example'));
ko.components.register('fetch-data', require('bundle?lazy!../fetch-data/fetch-data'));
}
// To support hot module replacement, this method unregisters the router and KO components.

View File

@@ -11,5 +11,6 @@
<li><strong>Client-side navigation</strong>. For example, click <em>Counter</em> then <em>Back</em> to return here.</li>
<li><strong>Webpack dev middleware</strong>. In development mode, there's no need to run the <code>webpack</code> build tool. Your client-side resources are dynamically built on demand. Updates are available as soon as you modify any file.</li>
<li><strong>Hot module replacement</strong>. In development mode, you don't even need to reload the page after making most changes. Within seconds of saving changes to files, your Knockout app will be rebuilt and a new instance injected is into the page.</li>
<li><strong>Code splitting and lazy loading</strong>. KO components may optionally be bundled individually and loaded on demand. For example, the code and template for 'Counter' is not loaded until you navigate to it..</li>
<li><strong>Efficient production builds</strong>. In production mode, development-time features are disabled, and the <code>webpack</code> build tool produces minified static CSS and JavaScript files.</li>
</ul>

View File

@@ -0,0 +1,25 @@
import * as ko from 'knockout';
// This Knockout component loader integrates with Webpack's lazy-loaded bundle feature.
// Having this means you can optionally declare components as follows:
// ko.components.register('my-component', require('bundle?lazy!../some-path-to-a-js-or-ts-module'));
// ... and then it will be loaded on demand instead of being loaded up front.
ko.components.loaders.unshift({
loadComponent: (name, componentConfig, callback) => {
if (typeof componentConfig === 'function') {
// It's a lazy-loaded Webpack bundle
(componentConfig as any)(loadedModule => {
// Handle TypeScript-style default exports
if (loadedModule.__esModule && loadedModule.default) {
loadedModule = loadedModule.default;
}
// Pass the loaded module to KO's default loader
ko.components.defaultLoader.loadComponent(name, loadedModule, callback);
});
} else {
// It's something else - let another component loader handle it
callback(null);
}
}
});

View File

@@ -19,6 +19,7 @@
"webpack-hot-middleware": "^2.7.1"
},
"dependencies": {
"bundle-loader": "^0.5.4",
"crossroads": "^0.12.2",
"domain-task": "^1.0.0",
"es6-promise": "^3.1.2",