Skip to content

Commit 11d4873

Browse files
Demonstrate lazy-loading for Webpack-bundled KO components
1 parent 25ba798 commit 11d4873

File tree

5 files changed

+36
-4
lines changed

5 files changed

+36
-4
lines changed

templates/KnockoutSpa/ClientApp/boot.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'bootstrap/dist/css/bootstrap.css';
33
import './css/site.css';
44
import * as ko from 'knockout';
55
import { createHistory } from 'history';
6+
import './webpack-component-loader';
67

78
// Load and register the <app-root> component
89
ko.components.register('app-root', require('./components/app-root/app-root').default);

templates/KnockoutSpa/ClientApp/components/app-root/app-root.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as ko from 'knockout';
22
import { Route, Router } from '../../router';
3+
import navMenu from '../nav-menu/nav-menu';
34

45
// Declare the client-side routing configuration
56
const routes: Route[] = [
@@ -18,10 +19,13 @@ class AppRootViewModel {
1819
this.route = this._router.currentRoute;
1920

2021
// Load and register all the KO components needed to handle the routes
21-
ko.components.register('nav-menu', require('../nav-menu/nav-menu').default);
22-
ko.components.register('home-page', require('../home-page/home-page').default);
23-
ko.components.register('counter-example', require('../counter-example/counter-example').default);
24-
ko.components.register('fetch-data', require('../fetch-data/fetch-data').default);
22+
// The optional 'bundle?lazy!' prefix is a Webpack feature that causes the referenced modules
23+
// to be split into separate files that are then loaded on demand.
24+
// For docs, see https://github.com/webpack/bundle-loader
25+
ko.components.register('nav-menu', navMenu);
26+
ko.components.register('home-page', require('bundle?lazy!../home-page/home-page'));
27+
ko.components.register('counter-example', require('bundle?lazy!../counter-example/counter-example'));
28+
ko.components.register('fetch-data', require('bundle?lazy!../fetch-data/fetch-data'));
2529
}
2630

2731
// To support hot module replacement, this method unregisters the router and KO components.

templates/KnockoutSpa/ClientApp/components/home-page/home-page.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ <h1>Hello, world!</h1>
1111
<li><strong>Client-side navigation</strong>. For example, click <em>Counter</em> then <em>Back</em> to return here.</li>
1212
<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>
1313
<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>
14+
<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>
1415
<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>
1516
</ul>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as ko from 'knockout';
2+
3+
// This Knockout component loader integrates with Webpack's lazy-loaded bundle feature.
4+
// Having this means you can optionally declare components as follows:
5+
// ko.components.register('my-component', require('bundle?lazy!../some-path-to-a-js-or-ts-module'));
6+
// ... and then it will be loaded on demand instead of being loaded up front.
7+
ko.components.loaders.unshift({
8+
loadComponent: (name, componentConfig, callback) => {
9+
if (typeof componentConfig === 'function') {
10+
// It's a lazy-loaded Webpack bundle
11+
(componentConfig as any)(loadedModule => {
12+
// Handle TypeScript-style default exports
13+
if (loadedModule.__esModule && loadedModule.default) {
14+
loadedModule = loadedModule.default;
15+
}
16+
17+
// Pass the loaded module to KO's default loader
18+
ko.components.defaultLoader.loadComponent(name, loadedModule, callback);
19+
});
20+
} else {
21+
// It's something else - let another component loader handle it
22+
callback(null);
23+
}
24+
}
25+
});

templates/KnockoutSpa/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"webpack-hot-middleware": "^2.7.1"
2020
},
2121
"dependencies": {
22+
"bundle-loader": "^0.5.4",
2223
"crossroads": "^0.12.2",
2324
"domain-task": "^1.0.0",
2425
"es6-promise": "^3.1.2",

0 commit comments

Comments
 (0)