jsgui3-server 0.0.82 → 0.0.83

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.
Files changed (52) hide show
  1. package/README.md +8 -1
  2. package/bundler/bundle.js +11 -0
  3. package/bundler/bundler.js +9 -0
  4. package/bundler/js-bundler.js +189 -0
  5. package/bundler/webpage-bundler.js +284 -0
  6. package/bundler/website-bundler.js +23 -0
  7. package/controls/README.md +8 -0
  8. package/controls/page/admin.js +75 -0
  9. package/controls/panel/admin.js +11 -0
  10. package/examples/controls/html-server-combo-box.js +5 -5
  11. package/examples/html-server.js +3 -0
  12. package/examples/square_box.js +35 -0
  13. package/examples/square_box_client.js +91 -0
  14. package/module.js +6 -0
  15. package/{single-control-server.js → old/_single-control-server.js} +157 -96
  16. package/old/single-control-server.js +108 -158
  17. package/{single-page-app.js → old/single-page-app.js} +2 -0
  18. package/{examples/demos → old}/square_box.js +1 -1
  19. package/package.json +10 -9
  20. package/page-context.js +1 -1
  21. package/publishing/http-css-publisher.js +0 -0
  22. package/publishing/{function-publisher.js → http-function-publisher.js} +11 -1
  23. package/publishing/http-html-page-publisher.js +5 -0
  24. package/publishing/http-html-publisher.js +25 -0
  25. package/publishing/http-jpeg-publisher.js +0 -0
  26. package/publishing/http-js-publisher.js +25 -0
  27. package/publishing/{observable-publisher.js → http-observable-publisher.js} +12 -6
  28. package/publishing/http-png-publisher.js +0 -0
  29. package/publishing/http-publisher.js +52 -0
  30. package/publishing/{resource-publisher.js → http-resource-publisher.js} +20 -1
  31. package/publishing/http-svg-publisher.js +0 -0
  32. package/publishing/http-webpage-publisher.js +112 -0
  33. package/publishing/http-website-publisher.js +262 -0
  34. package/publishing/notes.md +1 -0
  35. package/resources/README.md +16 -0
  36. package/resources/_old_website-resource.js +507 -0
  37. package/resources/compile/server-resource-compilation.js +41 -0
  38. package/resources/data-resource.js +8 -0
  39. package/resources/fs-resource.js +2 -4
  40. package/resources/notes.txt +11 -0
  41. package/resources/server-installed-tools.js +29 -0
  42. package/resources/server-resource-pool.js +1 -55
  43. package/resources/website-css-resource.js +1 -1
  44. package/resources/website-javascript-resource.js +165 -34
  45. package/resources/website-resource.js +52 -296
  46. package/resources/website-static-html-resource.js +0 -1
  47. package/resources/website-template-html-resource.js +231 -0
  48. package/roadmap.md +46 -0
  49. package/server.js +699 -17
  50. package/website/webpage.js +169 -0
  51. package/website/website-group.js +16 -0
  52. package/website/website.js +227 -0
package/README.md CHANGED
@@ -1,3 +1,10 @@
1
1
  # Jsgui3 Server
2
2
 
3
- This module covers functionality that enables the application to be served to clients.
3
+ This module covers functionality that enables the application to be served to clients.
4
+
5
+ 2022: Seems as though the server could be bundled with a few useful / essential compilers.
6
+
7
+ // Just running the Server without a website set up could be a way to test the compilers and data transformers.
8
+ // Would then be able to publish access to the compilers using the server mechanisms.
9
+
10
+
@@ -0,0 +1,11 @@
1
+ // Could make this a Collection?
2
+
3
+ const {Collection} = require('jsgui3-html');
4
+
5
+ class Bundle extends Collection {
6
+ constructor(spec = {}) {
7
+ super(spec);
8
+ }
9
+ }
10
+
11
+ module.exports = Bundle;
@@ -0,0 +1,9 @@
1
+ const {Evented_Class} = require('jsgui3-html');
2
+
3
+ class Bundler extends Evented_Class {
4
+ constructor(spec = {}) {
5
+ super(spec);
6
+ }
7
+ }
8
+
9
+ module.exports = Bundler;
@@ -0,0 +1,189 @@
1
+ const Bundler = require('./bundler');
2
+ const Bundle = require('./bundle');
3
+ const {obs, prom_or_cb} = require('fnl');
4
+ const {tof} = require('jsgui3-html');
5
+ const fnlfs = require('fnlfs');
6
+ const browserify = require('browserify');
7
+ const babel = require('@babel/core');
8
+ const stream_to_array = require('stream-to-array');
9
+ const util = require('util');
10
+ const Stream = require('stream');
11
+ // Will put the JS together. Maybe images?
12
+
13
+ // Will put the JS together. Maybe images?
14
+ // Get everything ready to serve.
15
+
16
+ // Would need a JS file that contains refs to all of the components used.
17
+ // Examine what is in the website and what JS it needs.
18
+
19
+ // Should be customisable which system gets used to make the bundle.
20
+ // eg babel or esbuild. Browserify still seems to work on code here at least, but esbuild seems better.
21
+
22
+ // JS bundling will become a bit more advanced in this server. Similar principles.
23
+
24
+ // JS_Bundler reporting css that gets found while bundling JS would make sense.
25
+
26
+
27
+
28
+
29
+
30
+ const bundle_js = (js_file_path, options = {}, callback) => {
31
+
32
+ // Returning an observable and not using a callback would work best.
33
+
34
+ const res = obs((next, complete, error) => {
35
+
36
+ let a = arguments;
37
+ if (typeof a[2] === 'function') {
38
+ callback = a[2];
39
+
40
+ options.include_sourcemaps = true;
41
+ }
42
+
43
+ (async () => {
44
+ // options
45
+ // may want a replacement within the client-side code.
46
+ // Can we call browserify on the code string?
47
+ // Creating a modified copy of the file would do.
48
+ // Load the file, modify it, save it under a different name
49
+
50
+ let s = new Stream.Readable(),
51
+ path = require('path').parse(js_file_path);
52
+
53
+ let fileContents = await fnlfs.load(js_file_path);
54
+
55
+ // Modify the original file contents so that only client-side parts appear?
56
+ // Could be done by programatically removing a whole code block, what to do if it is run on the server.
57
+
58
+
59
+ //console.log('1) fileContents.length', fileContents.length);
60
+ // are there any replacements to do?
61
+ // options.replacements
62
+
63
+ if (options.js_mode === 'debug') {
64
+ options.include_sourcemaps = true;
65
+ }
66
+ if (options.js_mode === 'compress' || options.js_mode === 'mini') {
67
+ options.include_sourcemaps = false;
68
+ options.babel = 'mini';
69
+ }
70
+
71
+ //console.log('options.babel', options.babel);
72
+
73
+ if (options.replace) {
74
+ let s_file_contents = fileContents.toString();
75
+ //console.log('s_file_contents', s_file_contents);
76
+ each(options.replace, (text, key) => {
77
+ //console.log('key', key);
78
+ //console.log('text', text);
79
+ let running_fn = '(' + text + ')();'
80
+ //console.log('running_fn', running_fn);
81
+ s_file_contents = s_file_contents.split(key).join(running_fn);
82
+ })
83
+ fileContents = Buffer.from(s_file_contents);
84
+ //console.log('2) fileContents.length', fileContents.length);
85
+ }
86
+ // Then we can replace some of the file contents with specific content given when we tall it to serve that file.
87
+ // We have a space for client-side activation.
88
+ s.push(fileContents);
89
+ s.push(null);
90
+
91
+ //let include_sourcemaps = true;
92
+
93
+ let b = browserify(s, {
94
+ basedir: path.dir,
95
+ //builtins: false,
96
+ builtins: ['buffer', 'process'],
97
+ 'debug': options.include_sourcemaps
98
+ });
99
+
100
+ // May be able to better put the bundle stream info into the observable results.
101
+
102
+ let parts = await stream_to_array(b.bundle());
103
+
104
+ const buffers = parts
105
+ .map(part => util.isBuffer(part) ? part : Buffer.from(part));
106
+ let buf_js = Buffer.concat(buffers);
107
+ let str_js = buf_js.toString();
108
+
109
+ let babel_option = options.babel
110
+ //console.log('babel_option', babel_option);
111
+ if (babel_option === 'es5') {
112
+
113
+ let o_transform = {
114
+ "presets": [
115
+ "es2015",
116
+ "es2017"
117
+ ],
118
+ "plugins": [
119
+ "transform-runtime"
120
+ ] //,
121
+ //'sourceMaps': 'inline'
122
+ };
123
+
124
+ if (options.include_sourcemaps) o_transform.sourceMaps = 'inline';
125
+ let res_transform = babel.transform(str_js, o_transform);
126
+ //console.log('res_transform', res_transform);
127
+ //console.log('Object.keys(res_transform)', Object.keys(res_transform));
128
+ let jst_es5 = res_transform.code;
129
+ //let {jst_es5, map, ast} = babel.transform(str_js);
130
+ //console.log('jst_es5.length', jst_es5.length);
131
+ buf_js = Buffer.from(jst_es5);
132
+ } else if (babel_option === 'mini') {
133
+ /*
134
+ let o_transform = {
135
+ presets: ["minify"]//,
136
+ //'sourceMaps': 'inline'
137
+ };
138
+ */
139
+ let o_transform = {
140
+ "presets": [
141
+ ["minify", {
142
+ //"mangle": {
143
+ //"exclude": ["MyCustomError"]
144
+ //},
145
+ //"unsafe": {
146
+ // "typeConstructors": false
147
+ //},
148
+ //"keepFnName": true
149
+ }]
150
+ ],
151
+ //plugins: ["minify-dead-code-elimination"]
152
+ };
153
+ if (options.include_sourcemaps) o_transform.sourceMaps = 'inline';
154
+
155
+ let res_transform = babel.transform(str_js, o_transform);
156
+ buf_js = Buffer.from(res_transform.code);
157
+ } else {
158
+ buf_js = Buffer.from(str_js);
159
+ }
160
+
161
+ complete(buf_js);
162
+ })();
163
+
164
+ })
165
+ if (callback) {
166
+ res.on('complete', (value) => {
167
+ callback(null, value);
168
+ });
169
+ res.on('error', err => {
170
+ callback(err);
171
+ })
172
+ } else {
173
+ return res;
174
+ }
175
+ // An observable would be better as result could include status messages (with their timings).
176
+
177
+ //return prom_or_cb((resolve, reject) => {
178
+
179
+ //}, callback);
180
+ }
181
+
182
+ class JS_Bundler extends Bundler {
183
+ constructor(spec = {}) {
184
+ super(spec);
185
+ }
186
+ }
187
+
188
+ JS_Bundler.bundle_js = bundle_js;
189
+ module.exports = JS_Bundler;
@@ -0,0 +1,284 @@
1
+ const Bundler = require('./bundler');
2
+
3
+ const JS_Bundler = require('./js-bundler');
4
+
5
+ const Bundle = require('./bundle');
6
+ const {obs, prom_or_cb} = require('fnl');
7
+ const fnlfs = require('fnlfs');
8
+ const {tof, HTML_Document, Client_HTML_Document, Control} = require('jsgui3-html');
9
+ const util = require('util');
10
+ const Server_Page_Context = require('./../page-context');
11
+ // Will put the JS together. Maybe images?
12
+ // Get everything ready to serve.
13
+ const browserify = require('browserify');
14
+ const babel = require('@babel/core');
15
+ const stream_to_array = require('stream-to-array');
16
+
17
+ // Maybe some web pages should be unbundlable? Or we note that they are dynamic (somehow).
18
+ // Perhaps another fn should do that check. Don't assume all pages will bundle OK. Could raise obs error if needed.
19
+
20
+ // Bundling CSS from a JS page.
21
+
22
+ // const bundle_js_to_css
23
+
24
+
25
+ // Maybe best to move to a JS Bundler.
26
+
27
+ // CSS bundler too
28
+ // Could consult JS source files. Could use the JS bundler to get css from JS.
29
+
30
+ // Creating working bundles from JS (and other) source files seems like an important task.
31
+
32
+ const {bundle_js} = JS_Bundler;
33
+
34
+
35
+ const bundle_web_page = (webpage, options = {}) => {
36
+ const {content} = webpage;
37
+
38
+ let {disk_path_client_js} = options;
39
+ //if (options.js_client) js_client_disk_path =
40
+
41
+ // Then depending on the content type
42
+
43
+
44
+ const t_content = tof(content);
45
+
46
+ //console.log('content', content);
47
+ //console.log('t_content', t_content);
48
+
49
+ return obs((next, complete, error) => {
50
+ const res = new Bundle();
51
+
52
+ // The observable could / should return updates along the way, things that contribute to the full result.
53
+
54
+ if (t_content === 'string') {
55
+ // Hardly anything to bundle. No JS required, so it seems.
56
+ // Maybe put it inside a basic JSGUI page control...?
57
+
58
+ // Page may still have a title.
59
+ const html = `<html><head><title>${webpage.title}</title></head><body>${content}</body></html>`;
60
+ const buff = Buffer.from(html, "utf-8");
61
+
62
+ // and value with different types of compression....
63
+ // worth having them ready.
64
+ res.push({
65
+ 'path': webpage.path,
66
+ 'value': buff,
67
+ 'content-type': 'text/html'
68
+ });
69
+ complete(res);
70
+
71
+ } if (t_content === 'control') {
72
+ //console.log ('content.context', content.context);
73
+ //console.log('content', content);
74
+
75
+ // May need to clone this control, putting it into new contexts.
76
+ // Or render it with a temporary context?
77
+
78
+ // Controls with temportary contexts could be useful.
79
+
80
+
81
+
82
+ if (content instanceof Control) {
83
+ //console.log('content is control');
84
+ //console.log('content.constructor.name', content.constructor.name);
85
+ if (content instanceof HTML_Document) {
86
+ console.log('content is an html document');
87
+
88
+ throw 'NYI';
89
+ } else {
90
+
91
+ // create an HTML document
92
+ // then put this control (or a clone of it) inside that HTML document.
93
+
94
+ // We may be changing the construction / rendering order here.
95
+ // Seem to be doing more construction of controls without a Page_Context.
96
+ // That page_context may only be important at a later stage.
97
+
98
+ // Some pages will render differently depending on when they are rendered.
99
+ // That may be why a server would need to individually build each page.
100
+ // Eg if there is SSR of latest news items.
101
+
102
+ // Question of pre-rendering or rendering on each page request.
103
+ // Maybe we don't bundle it if it includes dynamic content.
104
+ // Though we would need to bundle the JS.
105
+
106
+ // Could create a new page context.
107
+
108
+ //const cloned_content = content.clone();
109
+
110
+ // Should be able to clone a control?
111
+
112
+ //console.log('cloned_content', cloned_content);
113
+
114
+
115
+ // The page context may not have a request and response.
116
+ // For bundling, won't have one (unless one were made).
117
+
118
+ // Creating the JS bundle...
119
+
120
+ // Make it require jsgui-html for the moment.
121
+ // Requiring specific JS of the client control may make more sense....
122
+
123
+ // First let's bundle the JS.
124
+ // Or get the JS bundle for 'jsgui3-html'.
125
+
126
+ // js.serve_package('/js/app.js', js_client, o_serve_package, (err, served) => {
127
+ // maybe should make a JS_Bundler class.
128
+
129
+ // May need to be told earlier what file path we are using for the client js bundle.
130
+
131
+ const diskpath_js_client = disk_path_client_js || require.resolve('jsgui3-html');
132
+ //const diskpath_js_client = require.resolve('./../controls/page/admin.js');
133
+
134
+ // Bundle js could be an observable
135
+ // So when it finds CSS, it can output that.
136
+ // A Control's CSS property, within the JS definition.
137
+ // That can be output to a CSS file, copied or removed from the JS file.
138
+
139
+
140
+
141
+
142
+ bundle_js(diskpath_js_client, {
143
+ 'js_mode': 'mini',
144
+ 'babel': 'mini'
145
+ }, (err, res_bundle_js) => {
146
+ if (err) {
147
+ console.trace();
148
+ throw err;
149
+ } else {
150
+ //console.log('res_bundle_js', res_bundle_js);
151
+
152
+ res.push({
153
+ 'path': webpage.path + 'js/app.js',
154
+ 'value': res_bundle_js,
155
+ 'content-type': 'text/javascript'
156
+ });
157
+
158
+ const spc = new Server_Page_Context({
159
+ //request:
160
+ });
161
+
162
+
163
+ const doc = new Client_HTML_Document({
164
+ context: spc
165
+ });
166
+ doc.include_js('/js/app.js');
167
+ doc.body.add(content);
168
+
169
+ // Getting it to load the JS would be nice...
170
+ // But maybe only do it automatically if it's an active document.
171
+ // If it's just generated JS then best not to bundle JS to load.
172
+
173
+ // Could also make smaller bundles for some specific parts of the app. Could improve speed.
174
+ //console.log('doc.html', doc.html);
175
+ const buff_html = Buffer.from(doc.html, "utf-8");
176
+ // But add the client-side stuff to that doc.
177
+
178
+ // Remember, this part is about bundling rather than serving.
179
+
180
+ res.push({
181
+ 'path': webpage.path,
182
+ 'value': buff_html,
183
+ 'content-type': 'text/html'
184
+ });
185
+ //console.log('pre complete bundlejs');
186
+ //console.log('res.length()', res.length());
187
+ complete(res);
188
+ }
189
+ });
190
+
191
+ // Need to create a new control
192
+
193
+ //throw 'NYI';
194
+ }
195
+ } else {
196
+ throw 'NYI';
197
+ }
198
+ } else {
199
+
200
+ console.log('t_content', t_content);
201
+
202
+ if (t_content === 'function') {
203
+
204
+ const spc = new Server_Page_Context({
205
+ //request:
206
+ });
207
+
208
+ const Ctrl = content;
209
+ const ctrl = new Ctrl({
210
+ 'context': spc
211
+ });
212
+
213
+ if (ctrl instanceof HTML_Document) {
214
+ console.trace();
215
+ throw 'NYI';
216
+ } else {
217
+
218
+
219
+ const diskpath_js_client = disk_path_client_js || require.resolve('jsgui3-html');
220
+ //const diskpath_js_client = require.resolve('./../controls/page/admin.js');
221
+
222
+ bundle_js(diskpath_js_client, {
223
+ 'js_mode': 'mini',
224
+ 'babel': 'mini'
225
+ }, (err, res_bundle_js) => {
226
+ if (err) {
227
+ console.trace();
228
+ throw err;
229
+ } else {
230
+ //console.log('res_bundle_js', res_bundle_js);
231
+
232
+ res.push({
233
+ 'path': webpage.path + 'js/app.js',
234
+ 'value': res_bundle_js,
235
+ 'content-type': 'text/javascript'
236
+ });
237
+
238
+ const doc = new Client_HTML_Document({
239
+ context: spc
240
+ });
241
+ doc.include_js('/js/app.js');
242
+ doc.body.add(ctrl);
243
+
244
+ // Getting it to load the JS would be nice...
245
+ // But maybe only do it automatically if it's an active document.
246
+ // If it's just generated JS then best not to bundle JS to load.
247
+
248
+ // Could also make smaller bundles for some specific parts of the app. Could improve speed.
249
+ //console.log('doc.html', doc.html);
250
+ const buff_html = Buffer.from(doc.html, "utf-8");
251
+
252
+ res.push({
253
+ 'path': webpage.path,
254
+ 'value': buff_html,
255
+ 'content-type': 'text/html'
256
+ });
257
+ //console.log('pre complete bundlejs');
258
+ //console.log('res.length()', res.length());
259
+ complete(res);
260
+ }
261
+ });
262
+ }
263
+
264
+ } else if (false) {
265
+ console.trace();
266
+ throw 'NYI';
267
+ } else {
268
+ console.trace();
269
+ throw 'NYI';
270
+ }
271
+ }
272
+ });
273
+ //throw 'NYI';
274
+ }
275
+
276
+ class Webpage_Bundler extends Bundler {
277
+ constructor(spec = {}) {
278
+ super(spec);
279
+ }
280
+ }
281
+
282
+ Webpage_Bundler.bundle_web_page = bundle_web_page;
283
+
284
+ module.exports = Webpage_Bundler;
@@ -0,0 +1,23 @@
1
+ const Bundler = require('./bundler');
2
+ const Bundle = require('./bundle');
3
+ const {obs} = require('fnl');
4
+ const {tof} = require('jsgui3-html');
5
+
6
+ // Get everything ready to serve.
7
+
8
+ // Would need a JS file that contains refs to all of the components used.
9
+ // Examine what is in the website and what JS it needs.
10
+
11
+ // Bundling up the contents of a small/medium website so that contents are compressed and ready to serve.
12
+ // Could be useful for deploying to Android / iOS devices, maybe as apps.
13
+
14
+
15
+
16
+ class Website_Bundler extends Bundler {
17
+ constructor(spec = {}) {
18
+ super(spec);
19
+ }
20
+ }
21
+
22
+
23
+ module.exports = Website_Bundler;
@@ -0,0 +1,8 @@
1
+ Controls for use by the Server Application.
2
+
3
+ Possibly exclusively by the Server Admin functionality.
4
+
5
+ // /admin/status may require auth.
6
+
7
+ // status (read only)
8
+ // admin
@@ -0,0 +1,75 @@
1
+ const jsgui = require('jsgui3-html');
2
+
3
+ const Standard_Web_Page = jsgui.controls.Standard_Web_Page;
4
+
5
+ const Panel = jsgui.controls.Panel;
6
+
7
+ class Admin_Web_Page extends Standard_Web_Page {
8
+ constructor(spec) {
9
+ super(spec);
10
+
11
+ // a .text property of h1 etc would help.
12
+
13
+ const h1 = new jsgui.h1({
14
+ context: this.context//,
15
+ //text: 'jsgui3 Server Admin'
16
+ })
17
+ h1.add('jsgui3 Server Admin');
18
+ this.body.add(h1);
19
+
20
+
21
+ const main_panel = new Panel({
22
+ context: this.context,
23
+ class: 'main panel'
24
+ });
25
+
26
+ this.body.add(main_panel);
27
+
28
+
29
+ // Add a panel where the work takes place.
30
+ // Perhaps do more work on Panel as some kind of example?
31
+
32
+ // Want panels inside a panel, with them movable and resizable.
33
+ // A kind of snapping too, fitting some standard sizes.
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+ // Have some kinds of admin controls.
42
+ // Admin basic info panel.
43
+ // Expandable windows would be nice
44
+ // status <> detiled info and control
45
+ // Resources
46
+
47
+ // Admin_Resources_Panel
48
+
49
+ // Admin_Panel
50
+
51
+ // Admin_Web_Panel ???
52
+
53
+ // Want a flexible kind of web panel,
54
+ // Does not have to be server specific.
55
+ // Just have the things really only for the server here.
56
+
57
+ // Add Flexi_Panel
58
+ // or Multi_Grid_Panel
59
+ // Whatever advanced panel system it is (for now).
60
+
61
+
62
+
63
+
64
+
65
+ // Divide the screen / window into grid of 10 * 6 squares?
66
+ // Then could snap various components to those sizes.
67
+
68
+
69
+
70
+
71
+
72
+ }
73
+ }
74
+
75
+ module.exports = Admin_Web_Page;
@@ -0,0 +1,11 @@
1
+ const jsgui = require('jsgui3-html');
2
+
3
+ class Admin_Panel extends jsgui.controls.Panel {
4
+ constructor(spec) {
5
+ super(spec);
6
+ }
7
+ }
8
+
9
+ module.exports = Admin_Panel;
10
+
11
+
@@ -11,12 +11,12 @@
11
11
  // Some of the wiring could be done automatically.
12
12
  //
13
13
 
14
- var jsgui = require('../server/server');
15
- var Combo_Box = jsgui.Combo_Box;
14
+ var Server = require('../../server');
15
+ var Combo_Box = Server.HTML.Combo_Box;
16
16
 
17
- var Server = jsgui.Server;
17
+ //var Server = jsgui.Server;
18
18
  var port = 80;
19
- var Server_Page_Context = Server.Page_Context;
19
+ var Server_Page_Context = Server.Server_Page_Context;
20
20
 
21
21
  var server = new Server({
22
22
  routes: {
@@ -65,7 +65,7 @@ routing_tree.set('/', function(req, res) {
65
65
  'resource_pool': resource_pool
66
66
  });
67
67
  // Page_Bounds_Specifier
68
- var hd = new jsgui.Client_HTML_Document({
68
+ var hd = new Server.HTML.Client_HTML_Document({
69
69
  'context': server_page_context
70
70
  });
71
71
  hd.include_client_css();
@@ -65,6 +65,9 @@ routing_tree.set('/', function(req, res) {
65
65
  'context': server_page_context
66
66
  });
67
67
 
68
+
69
+ // Probably needs to create the app bundle.
70
+
68
71
  hd.include_client_css();
69
72
  hd.include_js('/js/app-bundle.js');
70
73