Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bootstrap ui in script file rather than inline #15904

Merged
merged 5 commits into from
Feb 5, 2018

Conversation

epixa
Copy link
Contributor

@epixa epixa commented Jan 8, 2018

There's no good reason to bootstrap the UI within the browser using an
inline script tag rather than a separate dynamically created bootstrap
script.

Having this bootstrapping logic in its own file allows us to cache this
separately from the main HTML payload, and it is required if we want to
disable inline scripts entirely.

The UI bootstrapping logic is now served up on an app-specific .js
endpoint. The URL for the boostrap must contain the app id so that it
can load the relevant app-specific JS bundles on the fly.

The HTTP caching will be invalidated whenever the underlying template
changes, the interpolated data changes, or any translations change.

This is necessary for #2873

@epixa epixa added Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc release_note:enhancement labels Jan 8, 2018
Copy link
Contributor

@spalger spalger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some notes, excited about the direction here

const hash = createHash('sha1');
hash.update(this._rawTemplate);
hash.update(JSON.stringify(this.templateData));
hash.update(JSON.stringify(this.translations));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, why not just hash the result of #getJsFile()? Feels like that is what this method is claiming to do, but is avoiding it for some reason.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I arrived at this current implementation after some refactoring, and it's not ideal.

path: '/bundles/app/{id}/bootstrap.js',
method: 'GET',
async handler(request, reply) {
const { id } = request.params;
Copy link
Contributor

@spalger spalger Jan 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we put everything within the try {} catch {}, and threw the error on 41 rather than passing it directly to reply(), then this handler would have a single flow for errors and would properly route errors if server.getUiAppById() threw, or request.params wasn't defined for some reason.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call

@@ -1,6 +1,7 @@
{
"rootDir": "../../..",
"roots": [
"<rootDir>/src/ui",
Copy link
Contributor

@spalger spalger Jan 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could probably just replace the next line

const boostrap = new AppBootstrap(mockConfig());
const contents = await boostrap.getJsFile();

expect(contents).toContain('translated foo');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the translation for the key foo in the js file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key is foo in the mock template for this test. In the actual template, it is UI-WELCOME_ERROR, which is the translation key for the error message that is shown when bundles fail to load properly: https://github.com/elastic/kibana/blob/master/src/ui/ui_render/views/ui_app.jade#L143

@epixa
Copy link
Contributor Author

epixa commented Jan 8, 2018

@spalger I pushed changes for your feedback

@epixa
Copy link
Contributor Author

epixa commented Jan 9, 2018

This is breaking for the status page. I'll check it out tomorrow.

@epixa epixa removed the blocked label Jan 9, 2018
@epixa
Copy link
Contributor Author

epixa commented Jan 9, 2018

#15880 was merged, so this PR is unblocked

There's no good reason to bootstrap the UI within the browser using an
inline script tag rather than a separate dynamically created bootstrap
script.

Having this bootstrapping logic in its own file allows us to cache this
separately from the main HTML payload, and it is required if we want to
disable inline scripts entirely.
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@epixa
Copy link
Contributor Author

epixa commented Feb 4, 2018

@spalger Sorted out the status page issue and ready for another look.

Copy link
Contributor

@spalger spalger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@spalger spalger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last thing I think

@@ -30,6 +31,38 @@ export function uiRenderMixin(kbnServer, server, config) {
// render all views from ./views
server.setupViews(resolve(__dirname, 'views'));

server.route({
path: '/bundles/app/{id}/bootstrap.js',
method: 'GET',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure this gets config: { auth: false }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. I pushed this up and merged with the latest master.

We do not require auth for the rest of our static JS files, and this
file should not be treated differently than those. That this file is
created dynamically rather than pulled directly from the file system
is just an implementation detail.
@elasticmachine
Copy link
Contributor

💔 Build Failed

@epixa
Copy link
Contributor Author

epixa commented Feb 5, 2018

jenkins, test this

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@epixa
Copy link
Contributor Author

epixa commented Feb 5, 2018

I pinged the visualizations team about that random test failure. It was some threshold-based test failing in a flaky way, so they're looking into it.

@epixa epixa merged commit 2896a13 into elastic:master Feb 5, 2018
@epixa epixa deleted the remove-inline-scripts branch February 5, 2018 21:22
epixa added a commit to epixa/kibana that referenced this pull request Feb 5, 2018
* bootstrap ui in script file rather than inline

There's no good reason to bootstrap the UI within the browser using an
inline script tag rather than a separate dynamically created bootstrap
script.

Having this bootstrapping logic in its own file allows us to cache this
separately from the main HTML payload, and it is required if we want to
disable inline scripts entirely.

* cleanup from review 1

* fix status page bootstrap

* do not require auth for app bootstrap files

We do not require auth for the rest of our static JS files, and this
file should not be treated differently than those. That this file is
created dynamically rather than pulled directly from the file system
is just an implementation detail.
epixa added a commit that referenced this pull request Feb 5, 2018
* bootstrap ui in script file rather than inline

There's no good reason to bootstrap the UI within the browser using an
inline script tag rather than a separate dynamically created bootstrap
script.

Having this bootstrapping logic in its own file allows us to cache this
separately from the main HTML payload, and it is required if we want to
disable inline scripts entirely.

* cleanup from review 1

* fix status page bootstrap

* do not require auth for app bootstrap files

We do not require auth for the rest of our static JS files, and this
file should not be treated differently than those. That this file is
created dynamically rather than pulled directly from the file system
is just an implementation detail.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v6.3.0 v7.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants