fix(v2): BaseUrl issue banner insertion should be prevented if JS can load (#4155)

* restore useBannerRemover

* fix BaseUrlIssueBanner issues
This commit is contained in:
Sébastien Lorber 2021-02-02 16:43:25 +01:00 committed by GitHub
parent d22039c200
commit 3b64aa6107
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 20 deletions

View file

@ -5,21 +5,24 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import React from 'react'; import React, {useLayoutEffect} from 'react';
import {useLocation} from 'react-router-dom'; import {useLocation} from '@docusaurus/router';
import Head from '@docusaurus/Head';
import Head from '../exports/Head'; import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
// The critical CSS will hide the banner if it loads successfully! // Double-security: critical CSS will hide the banner if CSS can load!
import './styles.module.css'; import './styles.module.css';
const BannerContainerId = 'docusaurus-base-url-issue-banner-container'; const BannerContainerId = 'docusaurus-base-url-issue-banner-container';
const BannerId = 'docusaurus-base-url-issue-banner';
const SuggestionContainerId = const SuggestionContainerId =
'docusaurus-base-url-issue-banner-suggestion-container'; 'docusaurus-base-url-issue-banner-suggestion-container';
const InsertBannerWindowAttribute = '__DOCUSAURUS_INSERT_BASEURL_BANNER';
// It is important to not use React to render this banner // It is important to not use React to render this banner
// otherwise Google would index it, even if it's hidden with some critical CSS! // otherwise Google would index it, even if it's hidden with some critical CSS!
// See https://github.com/facebook/docusaurus/issues/4028 // See https://github.com/facebook/docusaurus/issues/4028
@ -27,7 +30,7 @@ const SuggestionContainerId =
// - We can't CSR (as it means the baseurl is correct) // - We can't CSR (as it means the baseurl is correct)
function createInlineHtmlBanner(baseUrl: string) { function createInlineHtmlBanner(baseUrl: string) {
return ` return `
<div style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;"> <div id="${BannerId}" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;">
<p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p> <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p>
<p>A very common reason is a wrong site <a href="https://v2.docusaurus.io/docs/docusaurus.config.js/#baseurl" style="font-weight: bold;">baseUrl configuration</a>.</p> <p>A very common reason is a wrong site <a href="https://v2.docusaurus.io/docs/docusaurus.config.js/#baseurl" style="font-weight: bold;">baseUrl configuration</a>.</p>
<p>Current configured baseUrl = <span style="font-weight: bold; color: red;">${baseUrl}</span> ${ <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">${baseUrl}</span> ${
@ -41,16 +44,24 @@ function createInlineHtmlBanner(baseUrl: string) {
// fn needs to work for older browsers! // fn needs to work for older browsers!
function createInlineScript(baseUrl: string) { function createInlineScript(baseUrl: string) {
return ` return `
function renderBanner() { window['${InsertBannerWindowAttribute}'] = true;
var banner = document.getElementById('${BannerContainerId}');
if (!banner) { document.addEventListener('DOMContentLoaded', maybeInsertBanner);
function maybeInsertBanner() {
var shouldInsert = window['${InsertBannerWindowAttribute}'];
shouldInsert && insertBanner();
}
function insertBanner() {
var bannerContainer = document.getElementById('${BannerContainerId}');
if (!bannerContainer) {
return; return;
} }
var bannerHtml = ${JSON.stringify(createInlineHtmlBanner(baseUrl)) var bannerHtml = ${JSON.stringify(createInlineHtmlBanner(baseUrl))
// See https://redux.js.org/recipes/server-rendering/#security-considerations // See https://redux.js.org/recipes/server-rendering/#security-considerations
.replace(/</g, '\\\u003c')}; .replace(/</g, '\\\u003c')};
banner.innerHTML = bannerHtml; bannerContainer.innerHTML = bannerHtml;
var suggestionContainer = document.getElementById('${SuggestionContainerId}'); var suggestionContainer = document.getElementById('${SuggestionContainerId}');
var actualHomePagePath = window.location.pathname; var actualHomePagePath = window.location.pathname;
var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/' var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/'
@ -58,8 +69,6 @@ function renderBanner() {
: actualHomePagePath + '/'; : actualHomePagePath + '/';
suggestionContainer.innerHTML = suggestedBaseUrl; suggestionContainer.innerHTML = suggestedBaseUrl;
} }
document.addEventListener('DOMContentLoaded', renderBanner);
`; `;
} }
@ -67,18 +76,27 @@ function BaseUrlIssueBannerEnabled() {
const { const {
siteConfig: {baseUrl}, siteConfig: {baseUrl},
} = useDocusaurusContext(); } = useDocusaurusContext();
// useLayoutEffect fires before DOMContentLoaded.
// It gives the opportunity to avoid inserting the banner in the first place
useLayoutEffect(() => {
window[InsertBannerWindowAttribute] = false;
}, []);
return ( return (
<> <>
{!ExecutionEnvironment.canUseDOM && (
<Head> <Head>
<script>{createInlineScript(baseUrl)}</script> <script>{createInlineScript(baseUrl)}</script>
</Head> </Head>
)}
<div id={BannerContainerId} /> <div id={BannerContainerId} />
</> </>
); );
} }
// We want to help the users with a bad baseUrl configuration (very common error) // We want to help the users with a bad baseUrl configuration (very common error)
// Help message is inlined, and hides if the external CSS is able to load successfully // Help message is inlined, and hidden if JS or CSS is able to load
// Note: it might create false positives (ie network failures): not a big deal // Note: it might create false positives (ie network failures): not a big deal
// Note: we only inline this for the homepage to avoid polluting all the site's pages // Note: we only inline this for the homepage to avoid polluting all the site's pages
// See https://github.com/facebook/docusaurus/pull/3621 // See https://github.com/facebook/docusaurus/pull/3621

View file

@ -8,9 +8,9 @@
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
export function onRouteUpdate({location}: {location: Location}) { export function onRouteUpdate({location}: {location: Location}) {
console.log('onRouteUpdate', {location}); // console.log('onRouteUpdate', {location});
} }
if (ExecutionEnvironment.canUseDOM) { if (ExecutionEnvironment.canUseDOM) {
console.log('client module example log'); // console.log('client module example log');
} }