Skip to content

Commit 8bb7a43

Browse files
Merge pull request #32 from puzzle-js/feature/on-demand-fragments
Implement on demand client async fragments
2 parents 333d02c + 412ab1a commit 8bb7a43

File tree

5 files changed

+74
-7
lines changed

5 files changed

+74
-7
lines changed

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@puzzle-js/client-lib",
33
"main": "dist/index.js",
4-
"version": "1.4.6",
4+
"version": "1.5.0",
55
"author": "<[email protected]>",
66
"license": "MIT",
77
"repository": {

src/core.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ export class Core extends Module {
3131
});
3232
}
3333

34-
const forcedFragments = Core.__pageConfiguration.fragments.filter(i => i.clientAsync && i.clientAsyncForce);
34+
const fragments = Core.__pageConfiguration.fragments.filter(i => !i.onDemand);
35+
const forcedFragments = fragments.filter(i => i.clientAsync && i.clientAsyncForce);
3536
if (forcedFragments.length) {
3637
forcedFragments.forEach(fragment => Core.asyncLoadFragment(fragment));
3738
}
3839

3940
if (this.isIntersectionObserverSupported()) {
40-
const asyncFragments = Core.__pageConfiguration.fragments.some(i => i.clientAsync);
41+
const asyncFragments = fragments.some(i => i.clientAsync);
4142

4243
if (asyncFragments) {
4344
this.observer = new IntersectionObserver(this.onIntersection.bind(this));
@@ -84,7 +85,7 @@ export class Core extends Module {
8485

8586
@on(EVENT.ON_PAGE_LOAD)
8687
static asyncComponentRender() {
87-
const asyncFragments = Core.__pageConfiguration.fragments.filter(i => i.clientAsync);
88+
const asyncFragments = Core.__pageConfiguration.fragments.filter(i => i.clientAsync && !i.onDemand);
8889

8990
asyncFragments.forEach(fragment => {
9091
if (this.observer) {
@@ -100,7 +101,7 @@ export class Core extends Module {
100101
}
101102

102103
private static asyncLoadFragment(fragment: IPageFragmentConfig) {
103-
if (fragment.asyncLoaded) return;
104+
if (fragment.asyncLoaded) return Promise.resolve();
104105
fragment.asyncLoaded = true;
105106
const queryString = this.prepareQueryString(fragment.attributes);
106107
const key = `${fragment.source}${window.location.pathname}${queryString}`;
@@ -302,6 +303,8 @@ export class Core extends Module {
302303
return this.asyncLoadFragment(fragment);
303304
}
304305
}
306+
307+
return Promise.resolve();
305308
}
306309

307310
private static isIntersectionObserverSupported() {

src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export interface IPageFragmentConfig {
3232
chunked: boolean;
3333
clientAsync: boolean;
3434
clientAsyncForce: boolean | undefined;
35+
onDemand: boolean | undefined;
3536
asyncDecentralized: boolean;
3637
attributes: { [name: string]: string };
3738
source: string | undefined;

test/core.spec.ts

+64-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {PuzzleJs} from "../src/puzzle";
44
import {Core} from "../src/core";
55
import {createPageLibConfiguration} from "./mock";
66
import sinon, { SinonStub } from "sinon";
7-
import {AssetHelper} from "../src/assetHelper";
87
import * as faker from "faker";
98
import {IPageLibAsset, IPageLibConfiguration, IPageLibDependency} from "../src/types";
109
import {RESOURCE_LOADING_TYPE, RESOURCE_TYPE} from "../src/enums";
@@ -203,6 +202,7 @@ describe('Module - Core', () => {
203202
chunked: true,
204203
clientAsync: true,
205204
clientAsyncForce: undefined,
205+
onDemand: undefined,
206206
source: undefined,
207207
asyncDecentralized: false
208208
}],
@@ -256,6 +256,7 @@ describe('Module - Core', () => {
256256
chunked: true,
257257
clientAsync: true,
258258
clientAsyncForce: true,
259+
onDemand: undefined,
259260
source: undefined,
260261
asyncDecentralized: false
261262
}],
@@ -278,4 +279,66 @@ describe('Module - Core', () => {
278279
expect(fetchStub.getCall(0).lastArg.headers).to.haveOwnProperty("originalurl");
279280
expect(stubAsyncRenderResponse.calledOnce).to.eq(true);
280281
});
282+
283+
it('should return a promise object that is resolved if fragment does not exist', () => {
284+
const assets = [] as IPageLibAsset[];
285+
const dependencies = [] as IPageLibDependency[];
286+
const config = {
287+
dependencies,
288+
assets,
289+
fragments: [],
290+
page: 'page',
291+
peers: []
292+
} as IPageLibConfiguration;
293+
294+
Core.config(JSON.stringify(config));
295+
const result = Core.renderAsyncFragment('test');
296+
297+
expect(result).to.be.a('promise');
298+
});
299+
300+
it('should return a promise object that is resolved if fragment is asyncLoaded', () => {
301+
const assets = [
302+
{
303+
name: 'bundle1',
304+
dependent: ['vendor1'],
305+
preLoaded: false,
306+
link: 'bundle1.js',
307+
fragment: 'test',
308+
loadMethod: RESOURCE_LOADING_TYPE.ON_PAGE_RENDER,
309+
type: RESOURCE_TYPE.JS
310+
}
311+
] as IPageLibAsset[];
312+
const dependencies = [
313+
{
314+
name: 'vendor1',
315+
link: 'vendor1.js',
316+
preLoaded: false
317+
}
318+
] as IPageLibDependency[];
319+
const config = {
320+
dependencies,
321+
assets,
322+
fragments: [{
323+
name: 'test',
324+
attributes: {
325+
if: "false"
326+
},
327+
chunked: true,
328+
clientAsync: true,
329+
clientAsyncForce: undefined,
330+
onDemand: undefined,
331+
source: undefined,
332+
asyncDecentralized: false,
333+
asyncLoaded: true
334+
}],
335+
page: 'page',
336+
peers: []
337+
} as IPageLibConfiguration;
338+
339+
Core.config(JSON.stringify(config));
340+
const result = Core.renderAsyncFragment('test');
341+
342+
expect(result).to.be.a('promise');
343+
});
281344
});

0 commit comments

Comments
 (0)