bigpipe-util 0.2.12 → 0.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -124
- package/{src → dist}/BigPipe.js +148 -170
- package/dist/Pagelet.js +111 -0
- package/dist/Primer.js +117 -0
- package/{src → dist}/ServerJS.js +40 -40
- package/dist/async/AsyncDOM.js +58 -0
- package/{src → dist}/async/AsyncRequest.js +182 -210
- package/dist/async/AsyncResponse.js +28 -0
- package/dist/core/$.js +9 -0
- package/{src → dist}/core/Arbiter.js +53 -53
- package/{src → dist}/core/DOM.js +39 -41
- package/{src → dist}/core/Dialog.js +129 -142
- package/dist/core/Parent.js +39 -0
- package/dist/core/ReloadPage.js +15 -0
- package/dist/core/ServerRedirect.js +14 -0
- package/{src → dist}/core/copyProperties.js +32 -31
- package/dist/core/onAfterLoad.js +18 -0
- package/{src → dist}/core/replaceTransportMarkers.js +32 -27
- package/{src → dist}/core/waitForLoad.js +13 -24
- package/package.json +21 -2
- package/.editorconfig +0 -9
- package/CHANGELOG.md +0 -105
- package/bigpipe.svg +0 -13
- package/src/Pagelet.js +0 -131
- package/src/Primer.js +0 -160
- package/src/async/AsyncDOM.js +0 -53
- package/src/async/AsyncResponse.js +0 -21
- package/src/core/$.js +0 -3
- package/src/core/Parent.js +0 -38
- package/src/core/ReloadPage.js +0 -9
- package/src/core/ServerRedirect.js +0 -7
- package/src/core/onAfterLoad.js +0 -13
package/README.md
CHANGED
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
<img src="bigpipe.svg" alt="BigPipe logo">
|
|
2
|
-
|
|
3
|
-
This library currently implements small part of [Facebook BigPipe][blog] so far, but the advantage is to efficiently insert/replace content and work with the DOM. It is also possible to easily call JavaScript modules from PHP.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## 👀 Demo App
|
|
7
|
-
Try the app with [live demo](http://bigpipe.xf.cz).
|
|
8
|
-
|
|
9
|
-
## 📕 Full documentation
|
|
10
|
-
https://richarddobron.github.io/bigpipe-php/
|
|
11
|
-
|
|
12
|
-
## ℹ️ Requirements
|
|
13
|
-
* PHP 7.1 or higher
|
|
14
|
-
* Webpack
|
|
15
|
-
|
|
16
|
-
## 📦 Installation
|
|
17
|
-
Follow these steps to install and set up:
|
|
18
|
-
|
|
19
|
-
### 1. Install composer package:
|
|
20
|
-
```shell
|
|
21
|
-
$ composer require richarddobron/bigpipe
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### 2. Install npm package:
|
|
25
|
-
```shell
|
|
26
|
-
$ npm install bigpipe-util
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### 3. Add the following to /path/to/resources/js/app.js:
|
|
30
|
-
```javascript
|
|
31
|
-
import Primer from 'bigpipe-util/
|
|
32
|
-
|
|
33
|
-
Primer();
|
|
34
|
-
|
|
35
|
-
window.require = (modulePath) => {
|
|
36
|
-
return modulePath.startsWith('bigpipe-util/')
|
|
37
|
-
? require('bigpipe-util/' + modulePath.substring(13) + '.js').default
|
|
38
|
-
: require('./' + modulePath).default;
|
|
39
|
-
};
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### 4. Add these lines to the page footer:
|
|
43
|
-
```html
|
|
44
|
-
<script>
|
|
45
|
-
(new (require("bigpipe-util/
|
|
46
|
-
</script>
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## 🛜 Request API
|
|
50
|
-
|
|
51
|
-
```javascript
|
|
52
|
-
import AsyncRequest from 'bigpipe-util/
|
|
53
|
-
|
|
54
|
-
const request = (new AsyncRequest('/ajax/remove.php'))
|
|
55
|
-
// or .setURI('/ajax/remove.php')
|
|
56
|
-
.setMethod('POST')
|
|
57
|
-
.setData({
|
|
58
|
-
param: 'value',
|
|
59
|
-
})
|
|
60
|
-
.setInitialHandler(() => {
|
|
61
|
-
// pre-request callback function
|
|
62
|
-
})
|
|
63
|
-
.setHandler((jsonResponse) => {
|
|
64
|
-
// A function to be called if the request succeeds
|
|
65
|
-
})
|
|
66
|
-
.setErrorHandler((xhr) => {
|
|
67
|
-
// A function to be called if the request fails
|
|
68
|
-
})
|
|
69
|
-
.setFinallyHandler((xhr) => {
|
|
70
|
-
// after request callback function
|
|
71
|
-
})
|
|
72
|
-
.send();
|
|
73
|
-
|
|
74
|
-
if (OH_NOES_WE_NEED_TO_CANCEL_RIGHT_NOW_OR_ELSE) {
|
|
75
|
-
request.abort();
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
# ⚡️ What all can be Ajaxifed?
|
|
80
|
-
|
|
81
|
-
## 🔗 Links
|
|
82
|
-
```html
|
|
83
|
-
<a href="#"
|
|
84
|
-
ajaxify="/ajax/remove.php"
|
|
85
|
-
rel="async">Remove Item</a>
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## 📝 Forms
|
|
89
|
-
```html
|
|
90
|
-
<form action="/submit.php"
|
|
91
|
-
method="POST"
|
|
92
|
-
rel="async">
|
|
93
|
-
<input name="user">
|
|
94
|
-
<input type="submit" name="Done">
|
|
95
|
-
</form>
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## 💬 Dialogs
|
|
99
|
-
```html
|
|
100
|
-
<a href="#"
|
|
101
|
-
ajaxify="/ajax/modal.php"
|
|
102
|
-
rel="dialog">Open Modal</a>
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## 🌟 Inspiration
|
|
106
|
-
|
|
107
|
-
BigPipe is inspired by Facebook's BigPipe. For more details
|
|
108
|
-
read their blog post: [Pipelining web pages for high performance][blog].
|
|
109
|
-
|
|
110
|
-
## 💡 Motivation
|
|
111
|
-
|
|
112
|
-
There is a large number of PHP projects for which moving to modern frameworks like Laravel Livewire, React, Vue.js (and many more!) could be very challenging.
|
|
113
|
-
|
|
114
|
-
The purpose of this library is to rapidly reduce the continuously repetitive code to work with the DOM and improve the communication barrier between PHP and JavaScript.
|
|
115
|
-
|
|
116
|
-
## 🤝 Contributing
|
|
117
|
-
|
|
118
|
-
We welcome contributions! If you'd like to help improve this project, feel free to open an issue or submit a pull request.
|
|
119
|
-
|
|
120
|
-
## 📜 License
|
|
121
|
-
|
|
122
|
-
The MIT License (MIT). Please see [License File](LICENSE) for more information.
|
|
123
|
-
|
|
124
|
-
[blog]: https://www.facebook.com/notes/facebook-engineering/bigpipe-pipelining-web-pages-for-high-performance/389414033919
|
|
1
|
+
<img src="bigpipe.svg" alt="BigPipe logo">
|
|
2
|
+
|
|
3
|
+
This library currently implements small part of [Facebook BigPipe][blog] so far, but the advantage is to efficiently insert/replace content and work with the DOM. It is also possible to easily call JavaScript modules from PHP.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## 👀 Demo App
|
|
7
|
+
Try the app with [live demo](http://bigpipe.xf.cz).
|
|
8
|
+
|
|
9
|
+
## 📕 Full documentation
|
|
10
|
+
https://richarddobron.github.io/bigpipe-php/
|
|
11
|
+
|
|
12
|
+
## ℹ️ Requirements
|
|
13
|
+
* PHP 7.1 or higher
|
|
14
|
+
* Webpack
|
|
15
|
+
|
|
16
|
+
## 📦 Installation
|
|
17
|
+
Follow these steps to install and set up:
|
|
18
|
+
|
|
19
|
+
### 1. Install composer package:
|
|
20
|
+
```shell
|
|
21
|
+
$ composer require richarddobron/bigpipe
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. Install npm package:
|
|
25
|
+
```shell
|
|
26
|
+
$ npm install bigpipe-util
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 3. Add the following to /path/to/resources/js/app.js:
|
|
30
|
+
```javascript
|
|
31
|
+
import Primer from 'bigpipe-util/dist/Primer';
|
|
32
|
+
|
|
33
|
+
Primer();
|
|
34
|
+
|
|
35
|
+
window.require = (modulePath) => {
|
|
36
|
+
return modulePath.startsWith('bigpipe-util/')
|
|
37
|
+
? require('bigpipe-util/' + modulePath.substring(13) + '.js').default
|
|
38
|
+
: require('./' + modulePath).default;
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 4. Add these lines to the page footer:
|
|
43
|
+
```html
|
|
44
|
+
<script>
|
|
45
|
+
(new (require("bigpipe-util/dist/ServerJS"))).handle(<?=json_encode(\dobron\BigPipe\BigPipe::jsmods())?>);
|
|
46
|
+
</script>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 🛜 Request API
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
import AsyncRequest from 'bigpipe-util/dist/AsyncRequest';
|
|
53
|
+
|
|
54
|
+
const request = (new AsyncRequest('/ajax/remove.php'))
|
|
55
|
+
// or .setURI('/ajax/remove.php')
|
|
56
|
+
.setMethod('POST')
|
|
57
|
+
.setData({
|
|
58
|
+
param: 'value',
|
|
59
|
+
})
|
|
60
|
+
.setInitialHandler(() => {
|
|
61
|
+
// pre-request callback function
|
|
62
|
+
})
|
|
63
|
+
.setHandler((jsonResponse) => {
|
|
64
|
+
// A function to be called if the request succeeds
|
|
65
|
+
})
|
|
66
|
+
.setErrorHandler((xhr) => {
|
|
67
|
+
// A function to be called if the request fails
|
|
68
|
+
})
|
|
69
|
+
.setFinallyHandler((xhr) => {
|
|
70
|
+
// after request callback function
|
|
71
|
+
})
|
|
72
|
+
.send();
|
|
73
|
+
|
|
74
|
+
if (OH_NOES_WE_NEED_TO_CANCEL_RIGHT_NOW_OR_ELSE) {
|
|
75
|
+
request.abort();
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
# ⚡️ What all can be Ajaxifed?
|
|
80
|
+
|
|
81
|
+
## 🔗 Links
|
|
82
|
+
```html
|
|
83
|
+
<a href="#"
|
|
84
|
+
ajaxify="/ajax/remove.php"
|
|
85
|
+
rel="async">Remove Item</a>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 📝 Forms
|
|
89
|
+
```html
|
|
90
|
+
<form action="/submit.php"
|
|
91
|
+
method="POST"
|
|
92
|
+
rel="async">
|
|
93
|
+
<input name="user">
|
|
94
|
+
<input type="submit" name="Done">
|
|
95
|
+
</form>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 💬 Dialogs
|
|
99
|
+
```html
|
|
100
|
+
<a href="#"
|
|
101
|
+
ajaxify="/ajax/modal.php"
|
|
102
|
+
rel="dialog">Open Modal</a>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## 🌟 Inspiration
|
|
106
|
+
|
|
107
|
+
BigPipe is inspired by Facebook's BigPipe. For more details
|
|
108
|
+
read their blog post: [Pipelining web pages for high performance][blog].
|
|
109
|
+
|
|
110
|
+
## 💡 Motivation
|
|
111
|
+
|
|
112
|
+
There is a large number of PHP projects for which moving to modern frameworks like Laravel Livewire, React, Vue.js (and many more!) could be very challenging.
|
|
113
|
+
|
|
114
|
+
The purpose of this library is to rapidly reduce the continuously repetitive code to work with the DOM and improve the communication barrier between PHP and JavaScript.
|
|
115
|
+
|
|
116
|
+
## 🤝 Contributing
|
|
117
|
+
|
|
118
|
+
We welcome contributions! If you'd like to help improve this project, feel free to open an issue or submit a pull request.
|
|
119
|
+
|
|
120
|
+
## 📜 License
|
|
121
|
+
|
|
122
|
+
The MIT License (MIT). Please see [License File](LICENSE) for more information.
|
|
123
|
+
|
|
124
|
+
[blog]: https://www.facebook.com/notes/facebook-engineering/bigpipe-pipelining-web-pages-for-high-performance/389414033919
|
package/{src → dist}/BigPipe.js
RENAMED
|
@@ -1,170 +1,148 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
this.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
return
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
link.onerror = () => self.fileLoaded(name);
|
|
150
|
-
document.head.appendChild(link);
|
|
151
|
-
} else if (type === 'js') {
|
|
152
|
-
const script = document.createElement('script');
|
|
153
|
-
script.src = file;
|
|
154
|
-
script.onload = () => self.fileLoaded(name);
|
|
155
|
-
script.onerror = () => self.fileLoaded(name);
|
|
156
|
-
document.body.appendChild(script);
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
onComplete() {
|
|
161
|
-
this.phase = RESOURCE_PHASE.LOADED;
|
|
162
|
-
this.callbacks.forEach(callback => callback(this));
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
attachToPagelet(callback) {
|
|
166
|
-
this.callbacks.push(callback);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
}
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.RESOURCE_PHASE = exports.PAGELET_PHASE = exports.BIGPIPE_PHASE = void 0;
|
|
7
|
+
const BIGPIPE_PHASE = exports.BIGPIPE_PHASE = Object.freeze({
|
|
8
|
+
WAITING: 0,
|
|
9
|
+
READY_FOR_JS: 1,
|
|
10
|
+
LOADING_JS: 2,
|
|
11
|
+
COMPLETE: 3
|
|
12
|
+
});
|
|
13
|
+
const RESOURCE_PHASE = exports.RESOURCE_PHASE = Object.freeze({
|
|
14
|
+
PENDING: 0,
|
|
15
|
+
LOADING: 1,
|
|
16
|
+
LOADED: 2
|
|
17
|
+
});
|
|
18
|
+
const PAGELET_PHASE = exports.PAGELET_PHASE = Object.freeze({
|
|
19
|
+
ARRIVE_START: 0,
|
|
20
|
+
LOADING_CSS: 1,
|
|
21
|
+
DISPLAY_START: 2,
|
|
22
|
+
DISPLAY_END: 3,
|
|
23
|
+
ARRIVE_END: 4
|
|
24
|
+
});
|
|
25
|
+
let instance = null;
|
|
26
|
+
class BigPipe {
|
|
27
|
+
pageletResources = new Map();
|
|
28
|
+
pagelets = new Map();
|
|
29
|
+
phase = BIGPIPE_PHASE.WAITING;
|
|
30
|
+
constructor() {
|
|
31
|
+
if (instance) {
|
|
32
|
+
return instance;
|
|
33
|
+
}
|
|
34
|
+
instance = this;
|
|
35
|
+
}
|
|
36
|
+
onPageletArrive(pageletData) {
|
|
37
|
+
const Pagelet = require('./Pagelet').default;
|
|
38
|
+
if (pageletData.is_last) {
|
|
39
|
+
this.setPhase(BIGPIPE_PHASE.READY_FOR_JS);
|
|
40
|
+
}
|
|
41
|
+
const pagelet = new Pagelet(pageletData);
|
|
42
|
+
this.registerPagelet(pagelet);
|
|
43
|
+
pagelet.start();
|
|
44
|
+
}
|
|
45
|
+
fileLoaded(filename) {
|
|
46
|
+
const resource = this.pageletResources.get(filename);
|
|
47
|
+
if (resource) {
|
|
48
|
+
resource.onComplete();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
registerPagelet(pagelet) {
|
|
52
|
+
this.pagelets.set(pagelet.id, pagelet);
|
|
53
|
+
}
|
|
54
|
+
areAllPageletsReady() {
|
|
55
|
+
if (this.pagelets.size === 0) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return Array.from(this.pagelets.values()).every(pagelet => pagelet.phase >= PAGELET_PHASE.ARRIVE_END);
|
|
59
|
+
}
|
|
60
|
+
pageletDisplayed() {
|
|
61
|
+
if (!this.areAllPageletsReady()) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (this.phase === BIGPIPE_PHASE.READY_FOR_JS) {
|
|
65
|
+
this.loadJSResources();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
setPhase(newPhase) {
|
|
69
|
+
this.phase = newPhase;
|
|
70
|
+
}
|
|
71
|
+
loadJSResources() {
|
|
72
|
+
this.setPhase(BIGPIPE_PHASE.LOADING_JS);
|
|
73
|
+
const jsResources = this.getResourcesByType('js');
|
|
74
|
+
jsResources.forEach(resource => {
|
|
75
|
+
resource.startLoading();
|
|
76
|
+
});
|
|
77
|
+
this.notifyPageletsWithoutResources();
|
|
78
|
+
if (jsResources.length === 0) {
|
|
79
|
+
this.notifyAllPagelets();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
getResourcesByType(type) {
|
|
83
|
+
return Array.from(this.pageletResources.values()).filter(resource => resource.type === type);
|
|
84
|
+
}
|
|
85
|
+
notifyPageletsWithoutResources() {
|
|
86
|
+
this.pagelets.forEach(pagelet => {
|
|
87
|
+
if (pagelet.jsResources.size === 0) {
|
|
88
|
+
pagelet.onJsFinished();
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
notifyAllPagelets() {
|
|
93
|
+
this.pagelets.forEach(pagelet => {
|
|
94
|
+
pagelet.onJsFinished();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
extractFilename(filePath) {
|
|
98
|
+
const match = /([^/]+)$/.exec(filePath);
|
|
99
|
+
return match ? match[1] : filePath;
|
|
100
|
+
}
|
|
101
|
+
pageletResourceFactory(file, type) {
|
|
102
|
+
const name = this.extractFilename(file);
|
|
103
|
+
let resource = this.pageletResources.get(name);
|
|
104
|
+
if (!resource) {
|
|
105
|
+
resource = this.createResource(file, name, type);
|
|
106
|
+
this.pageletResources.set(name, resource);
|
|
107
|
+
}
|
|
108
|
+
return resource;
|
|
109
|
+
}
|
|
110
|
+
createResource(file, name, type) {
|
|
111
|
+
const self = this;
|
|
112
|
+
return {
|
|
113
|
+
file,
|
|
114
|
+
name,
|
|
115
|
+
type,
|
|
116
|
+
phase: RESOURCE_PHASE.PENDING,
|
|
117
|
+
callbacks: [],
|
|
118
|
+
startLoading() {
|
|
119
|
+
if (this.phase !== RESOURCE_PHASE.PENDING) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.phase = RESOURCE_PHASE.LOADING;
|
|
123
|
+
if (type === 'css') {
|
|
124
|
+
const link = document.createElement('link');
|
|
125
|
+
link.rel = 'stylesheet';
|
|
126
|
+
link.href = file;
|
|
127
|
+
link.onload = () => self.fileLoaded(name);
|
|
128
|
+
link.onerror = () => self.fileLoaded(name);
|
|
129
|
+
document.head.appendChild(link);
|
|
130
|
+
} else if (type === 'js') {
|
|
131
|
+
const script = document.createElement('script');
|
|
132
|
+
script.src = file;
|
|
133
|
+
script.onload = () => self.fileLoaded(name);
|
|
134
|
+
script.onerror = () => self.fileLoaded(name);
|
|
135
|
+
document.body.appendChild(script);
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
onComplete() {
|
|
139
|
+
this.phase = RESOURCE_PHASE.LOADED;
|
|
140
|
+
this.callbacks.forEach(callback => callback(this));
|
|
141
|
+
},
|
|
142
|
+
attachToPagelet(callback) {
|
|
143
|
+
this.callbacks.push(callback);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.default = BigPipe;
|
package/dist/Pagelet.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "PAGELET_PHASE", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _BigPipe.PAGELET_PHASE;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
exports.default = void 0;
|
|
13
|
+
var _BigPipe = _interopRequireWildcard(require("./BigPipe"));
|
|
14
|
+
var _ServerJS = _interopRequireDefault(require("./ServerJS"));
|
|
15
|
+
var _AsyncDOM = _interopRequireDefault(require("./async/AsyncDOM"));
|
|
16
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
18
|
+
const serverJS = new _ServerJS.default();
|
|
19
|
+
const asyncDOM = new _AsyncDOM.default();
|
|
20
|
+
const bigPipe = new _BigPipe.default();
|
|
21
|
+
function areAllResourcesLoaded(resources) {
|
|
22
|
+
if (resources.size === 0) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
return Array.from(resources.values()).every(resource => resource.phase === _BigPipe.RESOURCE_PHASE.LOADED);
|
|
26
|
+
}
|
|
27
|
+
class Pagelet {
|
|
28
|
+
cssResources = new Map();
|
|
29
|
+
jsResources = new Map();
|
|
30
|
+
id = '';
|
|
31
|
+
phase = _BigPipe.PAGELET_PHASE.ARRIVE_START;
|
|
32
|
+
constructor(pageletData) {
|
|
33
|
+
this.bigPipe = bigPipe;
|
|
34
|
+
this.id = pageletData.id;
|
|
35
|
+
this.phase = _BigPipe.PAGELET_PHASE.ARRIVE_START;
|
|
36
|
+
this.domops = pageletData.domops;
|
|
37
|
+
this.jsmods = pageletData.jsmods;
|
|
38
|
+
this.css = pageletData.css;
|
|
39
|
+
this.js = pageletData.js;
|
|
40
|
+
this.cssResources = new Map();
|
|
41
|
+
this.jsResources = new Map();
|
|
42
|
+
}
|
|
43
|
+
isComplete() {
|
|
44
|
+
return this.phase === _BigPipe.PAGELET_PHASE.ARRIVE_END;
|
|
45
|
+
}
|
|
46
|
+
setPhase(phase) {
|
|
47
|
+
this.phase = phase;
|
|
48
|
+
}
|
|
49
|
+
start() {
|
|
50
|
+
if (this.phase !== _BigPipe.PAGELET_PHASE.ARRIVE_START) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (this.css.length > 0) {
|
|
54
|
+
this.css.forEach(cssFile => {
|
|
55
|
+
const cssResource = this.bigPipe.pageletResourceFactory(cssFile, 'css');
|
|
56
|
+
this.attachCssResource(cssResource);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (this.js.length > 0) {
|
|
60
|
+
this.js.forEach(jsFile => {
|
|
61
|
+
const jsResource = this.bigPipe.pageletResourceFactory(jsFile, 'js');
|
|
62
|
+
this.attachJsResource(jsResource);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (this.cssResources.size > 0) {
|
|
66
|
+
this.setPhase(_BigPipe.PAGELET_PHASE.LOADING_CSS);
|
|
67
|
+
this.cssResources.forEach(resource => {
|
|
68
|
+
resource.startLoading();
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
this.setContent();
|
|
72
|
+
this.onJsFinished();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
attachCssResource(resource) {
|
|
76
|
+
resource.attachToPagelet(() => this.onCssFinished(resource));
|
|
77
|
+
this.cssResources.set(resource.file, resource);
|
|
78
|
+
}
|
|
79
|
+
attachJsResource(resource) {
|
|
80
|
+
resource.attachToPagelet(() => this.onJsFinished());
|
|
81
|
+
this.jsResources.set(resource.file, resource);
|
|
82
|
+
}
|
|
83
|
+
onJsFinished() {
|
|
84
|
+
if (this.isComplete()) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!areAllResourcesLoaded(this.jsResources)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.processJsMods();
|
|
91
|
+
this.setPhase(_BigPipe.PAGELET_PHASE.ARRIVE_END);
|
|
92
|
+
}
|
|
93
|
+
processJsMods() {
|
|
94
|
+
serverJS.handle(this.jsmods);
|
|
95
|
+
}
|
|
96
|
+
onCssFinished() {
|
|
97
|
+
if (!areAllResourcesLoaded(this.cssResources)) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.setContent();
|
|
101
|
+
}
|
|
102
|
+
setContent() {
|
|
103
|
+
this.setPhase(_BigPipe.PAGELET_PHASE.DISPLAY_START);
|
|
104
|
+
if (this.domops) {
|
|
105
|
+
asyncDOM.invoke(this.domops);
|
|
106
|
+
}
|
|
107
|
+
this.setPhase(_BigPipe.PAGELET_PHASE.DISPLAY_END);
|
|
108
|
+
this.bigPipe.pageletDisplayed(this);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.default = Pagelet;
|