Skip to content

Browser support config#3609

Merged
arikfr merged 7 commits into
masterfrom
browser
Mar 27, 2019
Merged

Browser support config#3609
arikfr merged 7 commits into
masterfrom
browser

Conversation

@ranbena

@ranbena ranbena commented Mar 19, 2019

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • Feature

Fixes #3579

Description

Using browserslist to define which browser versions Redash supports.
List established from minimum "Async function" browser feature support (caniuse).

// package.json
"browserslist": [
  "Edge >= 15",
  "Firefox >= 52",
  "Chrome >= 55",
  "Safari >= 10.1",
  "iOS >= 10.3",
  "Opera >= 42",
  "op_mob >= 46",
  "android >= 67",
  "and_chr >= 71",
  "and_ff >= 64",
  "and_uc >= 11.8",
  "samsung >= 6.2"
]

This list allows us to utilize some powerful tools (all adhering to list automatically):

  • Babel transpiler 🚯

    • js reduced by 2k (comparing app.js on netlify preview)
    • css no change (autoprefix still must use -ms for Edge browser)
    • although babel should drop "async func" and "arrow func" polyfills according to this list - it doesn't. So I excluded these explicitly in .babelrc.
  • Eslint rule - error on unsupported browser feature usage 👮

    • Also available with stylelint but doesn't support less file so whatever man.
  • Outdated browser detection with browserslist-useragent only IE for now🚦

    • redirecting to a dedicated "browser not supported" static page (TBD).

@ghost ghost assigned ranbena Mar 19, 2019
@ghost ghost added the in progress label Mar 19, 2019
@ranbena
ranbena requested review from arikfr and kravets-levko March 19, 2019 22:34
Comment thread client/app/components/app-view/index.js Outdated

if (!matchesUA(navigator.userAgent, { allowHigherVersions: true })) {
// TODO: create "browser outdated" page and redirect to it
console.log('Your browser is outdated', resolveUserAgent(navigator.userAgent));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is this the place (and method) to put the redirect?

@kravets-levko kravets-levko Mar 20, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yes, it's the right place. And probably you don't need a page for redirect: create a component with message or whatever, and conditionally show it instead of <div ng-view>

@ranbena ranbena Mar 20, 2019

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But then we're still running potentially unsupported js for that page, which might fail it.
If we early redirect to a static html page, we don't have to worry about it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If you detect UA on client-side - you always have a chance to run unsupported code. If you'll change app-view/template.html to something like this - no change it will render header/footer/page:

<div ng-if="$ctrl.isBrowserSupported">
  <!-- original template here -->
</div>
<div ng-if="!$ctrl.isBrowserSupported">
  Error! Error!!!! Unsupported browser!!!!111
</div>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It's important that app-view component itself shouldn't use any unsupported features, as well as all code it uses via imports.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sounds easy and simple.
I'll do that and also add a cypress test to make sure it doesn't break.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@kravets-levko does this make sense? (I'd rather it have it's own template)

export default function init(ngModule) {
  ngModule.factory(
    '$exceptionHandler',
    () => function exceptionHandler(exception) {
      handler.process(exception);
    },
  );

  const isBrowserSupported = someCheck(...);
  ngModule.component('appView', {
    template: isBrowserSupported ? template : notSupportedTemplate,
    controller: isBrowserSupported ? AppViewComponent : NotSupportedCtrl,
  });
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@ranbena Yes, it's probably even better 👍

@ranbena ranbena mentioned this pull request Mar 20, 2019
1 task
@arikfr

arikfr commented Mar 20, 2019 via email

Copy link
Copy Markdown
Member

@ranbena

ranbena commented Mar 20, 2019

Copy link
Copy Markdown
Contributor Author

I think the initial approach of redirect is the correct one.

Best practice would be to determine and redirect in static.py.

@routes.route(org_scoped_rule('/<path:path>'))
@routes.route(org_scoped_rule('/'))
@supported_browser_required  <--
@login_required
def index(**kwargs):
    return render_index()

but that would require re-implementing browserlist-useragent in Python (currently available only in js and ruby).

But going with JS has a clear problem - it's not a standalone file, but a js module.

Options:

  1. Back down and import it into app-view.js.
  2. Implement it in python (and perhaps contribute to the open source project)
  3. Reimplement as standalone js file to be loaded in index.html.

None are perfect, my personal pref is #2 (although not my comfort zone).
Wdyt @arikfr?

@arikfr

arikfr commented Mar 20, 2019

Copy link
Copy Markdown
Member

Best practice would be to determine and redirect in static.py.

We should avoid depending on our Python server, as ultimately I want to decouple serving the frontend client from the backend server. We already do this decoupling with the preview builds, which are served 100% by Netlify.

So we're left with 1 & 3, and I think option 3 is the most robust option.

@arikfr

arikfr commented Mar 20, 2019

Copy link
Copy Markdown
Member

Eslint rule - error on unsupported browser feature usage 👮

If we only use browser supported features, what does Babel transpile?

@ranbena

ranbena commented Mar 20, 2019

Copy link
Copy Markdown
Contributor Author

If we only use browser supported features, what does Babel transpile?

It's a good question and I'd like to know as well. My understanding is that it does not polyfill all features and if a feature is polyfilled (either with dedicated babel plugin / npm package / own util) we need to be explicitly define it to be excluded from the linter.

For instance, if we'd still be targeting IE we'd get a lint error on using Promise but could polyfill it with dedicated package.

@ranbena

ranbena commented Mar 21, 2019

Copy link
Copy Markdown
Contributor Author

What I want to do

Generate browserslist-useragent.js file that suits old browsers to be loaded in client/app/index.html.

The plan

Define an npm script unsupported:build which transpiles the browserslist-useragent npm package with a dedicated babel config into a single file.

@arikfr

  1. Does this make sense?
  2. Can babel cli transpile a node module with its dependencies? Or can webpack be used to so that?
  3. How do you provide babel with a preset override? (e.g. targets: [ "ie": 8 ])

@arikfr

arikfr commented Mar 21, 2019 via email

Copy link
Copy Markdown
Member

@ranbena
ranbena marked this pull request as ready for review March 21, 2019 08:25
@ranbena

ranbena commented Mar 21, 2019

Copy link
Copy Markdown
Contributor Author

Tested the redirect method in IE10 and 11 but the rest later this week (with windows machine).

Comment thread client/app/index.html
onIE();
}
</script>
<!--[if IE]><script>onIE()</script><![endif]-->

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@ranbena ranbena changed the title Browser support config (wip) Browser support config Mar 21, 2019
@ranbena

ranbena commented Mar 26, 2019

Copy link
Copy Markdown
Contributor Author

@arikfr made html page static, no template. Lmk if this is what you meant.

@ranbena

ranbena commented Mar 26, 2019

Copy link
Copy Markdown
Contributor Author

Damnit, another codeclimate eslint plugin problem..
Might have to do with eslint channel compatibility 😒
@arikfr any reason not to switch to CircleCI step instead (assuming it's problem free)?

@ranbena

ranbena commented Mar 26, 2019

Copy link
Copy Markdown
Contributor Author

Also, @arikfr I put the redirect script in index.html and multi_org.html (dunno what that is).
Should I put it in signed_out.html (a main template) as well?

@ranbena

ranbena commented Mar 26, 2019

Copy link
Copy Markdown
Contributor Author

@arikfr I don't get the pep8 error here - there are actually 2 lines..

Comment thread package.json
}
},
"//": "browserslist set to 'Async functions' compatibility",
"browserslist": [

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How about using configuration like we had before (> 0.5%, last 2 versions, Firefox ESR, ie 11, not dead) so we don't have to update this list everytime browser versions update? I mean not necessarily the same one, but along the lines of > 0.5%, last 2 versions etc instead of hardcoded versions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

so we don't have to update this list every time browser versions update

Why would you need to? We should revisit this list when:

  1. There are lower browser versions we would like to support. Won't happen cause we've looked at the browser stats.
  2. As a performance optimization to lower app.js file size. That can be done periodically.

instead of hardcoded version

The advantage of hardcoded versions is that they allow to easily and reliably determine if a user's browser is supported or not. But if we define sth like "last 2 versions" you would have no clear cutoff point (cause under last 2 versions doesn't mean you can't use Redash).

Comment thread redash/templates/unsupported.html
@arikfr
arikfr merged commit b5d97e2 into master Mar 27, 2019
@arikfr
arikfr deleted the browser branch March 27, 2019 15:47
@arikfr

arikfr commented Mar 27, 2019

Copy link
Copy Markdown
Member

👍

harveyrendell pushed a commit to pushpay/redash that referenced this pull request Nov 14, 2019
* Browser support config

* Removed some offending code

* Added unsupported html page and redirect for IE

* Typo in regex

* Made html page static

* Added redirect script to multi_org

* Moved static html page to client/app
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show message when trying to load Redash from an unsupported browser

3 participants