Skip to content

Commit

Permalink
Bundle web component rather than using a CDN (#274)
Browse files Browse the repository at this point in the history
# Motivation

We decided to stop loading web components via the Internet (e.g. a CDN
like unpkg.com) because:

1. It introduced a new point of failure. If the service goes down, our
site is degraded. See
#246
2. There is a delay in loading the web component because we first render
the HTML before finishing pulling the web component

Related, we also decided to switch from always using the latest version
of web components (by always pointing to the same URL) to instead
versioning the component. For example, the Sphinx Theme 1.14 might use a
different version of the same component than Theme 1.11. We believe it
is not very painful to update web components thanks to now having
release branches & automated releases. It is much more stable to pin the
version of the web component, whereas before, updating the URL impacted
every single Theme release without an opportunity to validate it makes
sense for each release.

# FYI: How we load the file

We use an "immediately invoked function expression" (IIFE). That makes
sure that the top nav bar is rendered at the same time as the general
site, unlike before. See
Qiskit/web-components#227 for the change to have
the web-components repo build the file this way.

## Rejected: ES6 module via a local file

We'd still use `type="module"` like we were using before, but change the
`href`/`src` to point to a local file path rather than URL.

This breaks opening up `index.html`. We get a CORS issue that the file
cannot be accessed. That happens because `<script type="module">` has
stricter CORS policies. So, you now need to use a server like running
`python -m http.server` inside the `_build/html` folder for the site to
render properly.

This also still has a delay in the top nav bar rendering. That is
because ES6 modules have deferred execution, meaning that the JavaScript
runs after the HTML page is set up.

## Rejected: inlining the JavaScript module

We can avoid the CORS issue from "ES6 module via a local file" by
inlining the JavaScript with a Jinja `include` directive.

But, that increases the file size of each HTML page by 184KB. It means
that we keep downloading the same duplicate JS code because the browser
cannot cache the dedicated web component file.

This approach also still results in a delay in loading the top nav bar
because ES6 modules have deferred execution.
  • Loading branch information
Eric-Arellano authored Apr 25, 2023
1 parent 91af507 commit a180609
Show file tree
Hide file tree
Showing 4 changed files with 677 additions and 9 deletions.
19 changes: 19 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ This subfolder contains some example `.rst` files that show how to implement spe
3. Run `pip install -e .`
4. Run `sphinx-build -b html example_docs/docs/ example_docs/docs/_build/html` to build the documentation. This will create the `example_docs/docs/_build` subfolder where you can see the html files generated based on the `.rst` files in the `docs` folder and the styles pulled from the `qiskit_sphinx_theme`.

------
## Updating bundled web components

We use web components from https://github.com/Qiskit/web-components to include common design elements from qiskit.org in our documentation.

To update the top nav bar web component:

1. In https://github.com/Qiskit/web-components, run `npm install` then `npm run build`.
2. There should be a file created at the root of the web components repository called `experimental-bundled-ui-shell.js`. Copy its contents into the file `js/web-components/top-nav-bar.js` in this theme repository.
3. Build the example docs with `tox -e py` to ensure everything works.

If you want to add a new web component:

1. Work with the web components repository's team to set up `npm run build` to generate a single JavaScript file.
2. Add the file contents to the `js/web-components/` folder in this theme repository.
3. Add to the HTML template (e.g. `layout.html`) a line like `<script src="{{ pathto('_static/js/web-components/my-component.js', 1) }}"></script>` in the `<head>`.
4. Build the example docs to ensure everything works.
5. Update this guide with specific instructions for the web component.

------
## Releases

Expand Down
9 changes: 1 addition & 8 deletions qiskit_sphinx_theme/pytorch_base/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,7 @@
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{%- endfor -%}

<link rel="modulepreload" href="https://cdn.jsdelivr.net/npm/@qiskit/web-components/experimental-bundled-ui-shell.js">
<script type="module" src="https://cdn.jsdelivr.net/npm/@qiskit/web-components/experimental-bundled-ui-shell.js"></script>
<style>
qiskit-ui-shell:not(:defined) {
display: block;
margin-bottom: 3.5rem;
}
</style>
<script src="{{ pathto('_static/js/web-components/top-nav-bar.js', 1) }}"></script>

<!-- SEGMENT ANALYTICS -->
{%- if analytics_enabled %}
Expand Down
1 change: 0 additions & 1 deletion qiskit_sphinx_theme/pytorch_base/static/css/theme.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a180609

Please sign in to comment.