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

Perceived performance improvement with Mapbox Static Images API #331

Open
wants to merge 28 commits into
base: release/v1.1.0
Choose a base branch
from

Conversation

yen-tt
Copy link
Contributor

@yen-tt yen-tt commented Nov 9, 2022

This PR update mapbox component to use the Mapbox Static Images API to improve the perceived performance for users -- i.e immediately show a static image while Mapbox GL JS works in the background. From lighthouse analysis, this is generally similar to the performance before this change, occasionally a couple points increase. (overall ~86)

Note: the API only support width and height up to 1280 pixels, and will response with 422 error code otherwise. We could attempt to stretch the image to cover the space (e.g. such as using background-cover css style) but it wouldn't match with the display of the actual map on load (without initial search) so this PR currently will not use static image API unless the dimension of the map is within the restriction.

J=SLAP-2434
TEST=manual&auto

load location page and see that a static image is fetched over network and display until the canvas for the interactive map is loaded, then that become visible to the user instead.
added a story for map static image

alextaing and others added 7 commits October 5, 2022 09:33
This PR introduces the Mapbox Component. This lays the basic foundation for the component, with the interfaces constructed through discussion with Product.

Here are two relevant slack threads:
https://yext.slack.com/archives/C032CKFARGS/p1658322867803349 (inception)
https://yext.slack.com/archives/C032CKFARGS/p1659449732357219 (more recent)

J=SLAP-2221
TEST=manual

Tested through LocationsPage

Later items will add jest tests and storybook for further testing

NOTE: as of now, local test-site requires an `env` variable REACT_APP_MAPBOX_API_KEY for map to work properly
For github workflow to work (in future test items), some changes may be needed in the workflow: facebook/create-react-app#9064 (comment)
added jest tests for Mapbox component, specifically for the two prop fields: `getCoordinate` and `onDrag`. The remaining props are best tested through storybook.

note that `mapbox-gl` is mocked as it seems to use some web browser functionality on initialization that is not supported in jest test environment (jsdom). Without mocking, jest would present an error `Error: Failed to initialize WebGL.`.
- tried third party libraries `jest-webgl-canvas-mock` and `jest-canvas-mock` still result in more window properties access related errors (`[TypeError: e.window.Worker is not a constructor]`, which could be resolve by [manually mocking Worker](jestjs/jest#3449), `[TypeError: this.target.addEventListener is not a function]`...).
- Looked into how pageJS test mapbox provider in their map component: the map wrapper component invoke a [load function](https://github.com/yext/pages/blob/main/packages/pages/src/components/map/map.tsx#L112) to construct [a script tag](https://github.com/yext/components-tsx-maps/blob/main/src/Providers/Mapbox.js#L137) from `yext/components-tsx-maps` and the assertions in the unit tests seem to check for the rendering of the wrapper component only and not waiting for the script to load. No content/interaction of the map was tested from my understanding.
- Looked into how mapbox-gl-js does their own testing: they had a couple util files to set up the environment for their tests (mock requests, [mock HtmlCanvas/WebLG in window](https://github.com/mapbox/mapbox-gl-js/blob/main/src/util/window.js) object, etc.).

I decided this complexity is probably unnecessary to add to the repo but we can discuss if other may think differently. We can have jest strictly test new isolated functionalities added from the component and leave all the UI rendering and mapbox interaction to storybook tests.

SLAP-2222
TEST=auto

new jest tests passed
Add react-dom as a peer dependency as it's now use in Mapbox component.

Note that, ReactDOM.render is deprecated in React 18, which now have a new client render function `createRoot`. For now, a warning will display in console informing user that the app will behave as if it’s running React 17 until the code switch to the new API. A new item will be created to address this issue.

TEST=manual

`npm pack` the component lib. Created a new React app using react 17/18, see that react-dom is installed as peer dep (automatically install with npm >=7) and mapbox component is display as expected (there's a warning in React 18).
single marker story
multiple marker story
custom marker story - follow docs.mapbox.com guide to add a simple popup pin

J=SLAP-2223
TEST=manual
 
serve and view stories
This PR uses a dynamic imports with a .catch fallback for when react-dom/client does not exist.

MapboxMap code had to be tweaked due to differences between ReactDOM.render and ReactDOM.createRoot().render(). Namely, createRoot() does not modify the container element unless it already exists on the physical page. This means that we can't call document.creatElement('div'), use createRoot, and THEN attach it to the mapbox map. Instead, we have to attach the div to the map first.

This also seems it make it more difficult to unit test, my guess would be because createRoot does not do anything on the server. For now I use some jest.mocks to ensure the right methods are being called in the right environments.

TEST=manual,auto

storybook can start up (react 17)
test site can display custom pin in both react 17 and 18
@yen-tt yen-tt requested a review from a team as a code owner November 9, 2022 19:25
@coveralls
Copy link

coveralls commented Nov 9, 2022

Coverage Status

Coverage increased (+1.5%) to 85.852% when pulling ffe64e5 on dev/mapbox-static-image into a46128b on release/v1.1.0.

Copy link
Collaborator

@tmeyer2115 tmeyer2115 left a comment

Choose a reason for hiding this comment

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

Would it be possible to add a Storybook story as well to test the loading state?

src/components/MapboxMap.tsx Outdated Show resolved Hide resolved
src/components/MapboxMap.tsx Outdated Show resolved Hide resolved
src/components/MapboxMap.tsx Outdated Show resolved Hide resolved
src/components/MapboxMap.tsx Outdated Show resolved Hide resolved
src/components/MapboxMap.tsx Outdated Show resolved Hide resolved
const centerAndZoom = `${center[0]},${center[1]},${zoom}`;
const dimension = `${width}x${height}`;
return `https://api.mapbox.com/styles/v1/${stylesheet}/static/${centerAndZoom}/${dimension}?access_token=${mapboxAccessToken}`;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I hate asking for more legal stuff but do we need to poke product about the static image api pricing? https://docs.mapbox.com/api/maps/static-images/#static-images-api-pricing
the first 50k are free which is nice at least https://www.mapbox.com/pricing/#static-images-api

Copy link
Contributor Author

Choose a reason for hiding this comment

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

per discussion during all hands, tom will run this by product and legal before the feature is merge into develop

@github-actions
Copy link
Contributor

github-actions bot commented Nov 10, 2022

Current unit coverage is 89.02181562280084%
Current visual coverage is 77.98434442270059%
Current combined coverage is 89.72554539057002%

@yen-tt yen-tt requested review from oshi97 and tmeyer2115 November 10, 2022 20:49
layout: 'fullscreen',
percy: {
enableJavascript: true,
waitForSelector: '.mapboxgl-map[style=\'visibility: visible;\']'
Copy link
Contributor

Choose a reason for hiding this comment

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

nice!

Copy link
Contributor Author

@yen-tt yen-tt Nov 14, 2022

Choose a reason for hiding this comment

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

actually, doesn't look like it works with javascript enabled :( . using the storybook play function to force await for the dynamic map doesn't work either

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yen-tt yen-tt requested review from nmanu1 and oshi97 November 14, 2022 16:37
@yen-tt yen-tt changed the base branch from feature/mapbox-component to develop November 15, 2022 17:16
@yen-tt yen-tt added the wip label Nov 15, 2022
@yen-tt yen-tt removed the wip label Nov 15, 2022
Copy link
Contributor

@nmanu1 nmanu1 left a comment

Choose a reason for hiding this comment

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

looks like the wcag tests complete but some of the stories are failing. the error is different from the one we were seeing in #332

@yen-tt
Copy link
Contributor Author

yen-tt commented Nov 16, 2022

looks like the wcag tests complete but some of the stories are failing. the error is different from the one we were seeing in #332

oh I think WCAG test wasn't updated in previous PR along with the percy snapshot test, to also accept MAPBOX_API_KEY environment variable since wcag gh action wasn't running at all -- we should consider triggering WCAG for merging to feature branch too...
I will put up a pr in the workflow repo to update WCAG gh action, and here as well!

yen-tt added a commit to yext/slapshot-reusable-workflows that referenced this pull request Nov 16, 2022
When testing wcag in search-react-ui repo, the mapbox API key is required to use Mapbox GL in storybook. Updated the workflow to optionally accept a mapbox API key as an env variable for the build step.

J=none
TEST=manual

tested in this PR: yext/search-ui-react#331, where wcag error `An API access token is required to use Mapbox GL.` is no longer present after using the workflow from this branch.
Copy link
Contributor

@nmanu1 nmanu1 left a comment

Choose a reason for hiding this comment

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

looks like there's a wcag violation in one of the map stories that's causing the check to fail

@yen-tt
Copy link
Contributor Author

yen-tt commented Nov 16, 2022

looks like there's a wcag violation in one of the map stories that's causing the check to fail

that is fixed in this PR: #337 for wcag related issues coming from the existing mapbox stories. will merge the change to this branch after.

yen-tt and others added 3 commits November 18, 2022 11:02
paired with the changes in this [PR](yext/slapshot-reusable-workflows#22) in WCAG workflow, this PR updates the WCAG github action in the repo to pass in the mapbox key. Also updated the wcag test to exclude checking elements coming from mapbox canvas container as any potential violations coming from there is outside of our repo's control.

WCAG github action also run on pull request to feature branch now.

J=SLAP-2458
TEST=auto

see that WCAG github action now passes
In addition to the changes in the [workflow PR](yext/slapshot-reusable-workflows#24), this up updates run-tests github action and coverage github action to pass mapbox api key so visual coverage test works as expected.

J=SLAP-2467
TEST=auto

see that run-tests github action and coverage github action passed -- looked into the logs, no false positive / errors related to visual coverage.
@yen-tt yen-tt changed the base branch from develop to release/v1.1.0 November 18, 2022 16:07
@yen-tt yen-tt requested a review from nmanu1 November 18, 2022 17:46
@oshi97
Copy link
Contributor

oshi97 commented Apr 21, 2023

putting wip tag to exclude this from our PR dashboard (even though the PR is done)

@oshi97 oshi97 added the wip label Apr 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants