summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/web
diff options
context:
space:
mode:
authortamaina <tamaina@hotmail.co.jp>2024-03-06 09:49:01 +0000
committertamaina <tamaina@hotmail.co.jp>2024-03-06 09:49:01 +0000
commit62922352b3cddaee9f72261448d862002e55a67c (patch)
tree82a53b9cdb526f16dc4048c377b7d084cf0122d8 /packages/backend/src/server/web
parentperf: boot.jsの調整 (diff)
downloadsharkey-62922352b3cddaee9f72261448d862002e55a67c.tar.gz
sharkey-62922352b3cddaee9f72261448d862002e55a67c.tar.bz2
sharkey-62922352b3cddaee9f72261448d862002e55a67c.zip
Revert "perf: boot.jsの調整"
This reverts commit 00c1e4eb550c68f43ae44ba9f0c8da9887fc2180.
Diffstat (limited to 'packages/backend/src/server/web')
-rw-r--r--packages/backend/src/server/web/boot.js501
1 files changed, 213 insertions, 288 deletions
diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js
index bc7b800d22..396536948e 100644
--- a/packages/backend/src/server/web/boot.js
+++ b/packages/backend/src/server/web/boot.js
@@ -7,163 +7,158 @@
* BOOT LOADER
* サーバーからレスポンスされるHTMLに埋め込まれるスクリプトで、以下の役割を持ちます。
* - 翻訳ファイルをフェッチする。
- * - 事前に挿入されたCLIENT_ENTRYを読んで適切なメインスクリプトを読み込む。
+ * - バージョンに基づいて適切なメインスクリプトを読み込む。
* - キャッシュされたコンパイル済みテーマを適用する。
* - クライアントの設定値に基づいて対応するHTMLクラス等を設定する。
- * - もしメインスクリプトの読み込みなどでエラーが発生した場合は、renderErrorでエラーを描画する。
* テーマをこの段階で設定するのは、メインスクリプトが読み込まれる間もテーマを適用したいためです。
+ * 注: webpackは介さないため、このファイルではrequireやimportは使えません。
*/
'use strict';
-var misskey_loader = new Set();
-
// ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので
-function boot() {
- const defaultSolutions = [
- 'Clear the browser cache / ブラウザのキャッシュをクリアする',
- 'Update your os and browser / ブラウザおよびOSを最新バージョンに更新する',
- 'Disable an adblocker / アドブロッカーを無効にする',
- '&#40;Tor Browser&#41; Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する'
- ];
-
- const onErrorStyle = `
- * {
- font-family: BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif;
- }
-
- #misskey_app,
- #splash {
- display: none !important;
- }
-
- body,
- html {
- background-color: #222;
- color: #dfddcc;
- justify-content: center;
- margin: auto;
- padding: 10px;
- text-align: center;
- }
-
- button {
- border-radius: 999px;
- padding: 0px 12px 0px 12px;
- border: none;
- cursor: pointer;
- margin-bottom: 12px;
- }
+(async () => {
+ window.onerror = (e) => {
+ console.error(e);
+ renderError('SOMETHING_HAPPENED', e);
+ };
+ window.onunhandledrejection = (e) => {
+ console.error(e);
+ renderError('SOMETHING_HAPPENED_IN_PROMISE', e);
+ };
- .button-big {
- background: linear-gradient(90deg, rgb(134, 179, 0), rgb(74, 179, 0));
- line-height: 50px;
+ let forceError = localStorage.getItem('forceError');
+ if (forceError != null) {
+ renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.')
}
- .button-big:hover {
- background: rgb(153, 204, 0);
- }
+ //#region Detect language & fetch translations
+ if (!localStorage.hasOwnProperty('locale')) {
+ const supportedLangs = LANGS;
+ let lang = localStorage.getItem('lang');
+ if (lang == null || !supportedLangs.includes(lang)) {
+ if (supportedLangs.includes(navigator.language)) {
+ lang = navigator.language;
+ } else {
+ lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
- .button-small {
- background: #444;
- line-height: 40px;
- }
+ // Fallback
+ if (lang == null) lang = 'en-US';
+ }
+ }
- .button-small:hover {
- background: #555;
- }
+ const metaRes = await window.fetch('/api/meta', {
+ method: 'POST',
+ body: JSON.stringify({}),
+ credentials: 'omit',
+ cache: 'no-cache',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ if (metaRes.status !== 200) {
+ renderError('META_FETCH');
+ return;
+ }
+ const meta = await metaRes.json();
+ const v = meta.version;
+ if (v == null) {
+ renderError('META_FETCH_V');
+ return;
+ }
- .button-label-big {
- color: #222;
- font-weight: bold;
- font-size: 1.2em;
- padding: 12px;
- }
+ // for https://github.com/misskey-dev/misskey/issues/10202
+ if (lang == null || lang.toString == null || lang.toString() === 'null') {
+ console.error('invalid lang value detected!!!', typeof lang, lang);
+ lang = 'en-US';
+ }
- .button-label-small {
- color: rgb(153, 204, 0);
- font-size: 16px;
- padding: 12px;
+ const localRes = await window.fetch(`/assets/locales/${lang}.${v}.json`);
+ if (localRes.status === 200) {
+ localStorage.setItem('lang', lang);
+ localStorage.setItem('locale', await localRes.text());
+ localStorage.setItem('localeVersion', v);
+ } else {
+ renderError('LOCALE_FETCH');
+ return;
+ }
}
+ //#endregion
- a {
- color: rgb(134, 179, 0);
- text-decoration: none;
+ //#region Script
+ async function importAppScript() {
+ await import(`/vite/${CLIENT_ENTRY}`)
+ .catch(async e => {
+ console.error(e);
+ renderError('APP_IMPORT', e);
+ });
}
- p,
- li {
- font-size: 16px;
+ // タイミングによっては、この時点でDOMの構築が済んでいる場合とそうでない場合とがある
+ if (document.readyState !== 'loading') {
+ importAppScript();
+ } else {
+ window.addEventListener('DOMContentLoaded', () => {
+ importAppScript();
+ });
}
+ //#endregion
- .icon-warning {
- color: #dec340;
- height: 4rem;
- padding-top: 2rem;
- }
+ //#region Theme
+ const theme = localStorage.getItem('theme');
+ if (theme) {
+ for (const [k, v] of Object.entries(JSON.parse(theme))) {
+ document.documentElement.style.setProperty(`--${k}`, v.toString());
- h1 {
- font-size: 1.5em;
- margin: 1em;
+ // HTMLの theme-color 適用
+ if (k === 'htmlThemeColor') {
+ for (const tag of document.head.children) {
+ if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
+ tag.setAttribute('content', v);
+ break;
+ }
+ }
+ }
+ }
}
-
- summary {
- cursor: pointer;
+ const colorScheme = localStorage.getItem('colorScheme');
+ if (colorScheme) {
+ document.documentElement.style.setProperty('color-scheme', colorScheme);
}
+ //#endregion
- code {
- font-family: Fira, FiraCode, monospace;
+ const fontSize = localStorage.getItem('fontSize');
+ if (fontSize) {
+ document.documentElement.classList.add('f-' + fontSize);
}
- #errors {
- display: flex;
- flex-direction: column;
- align-items: center;
+ const useSystemFont = localStorage.getItem('useSystemFont');
+ if (useSystemFont) {
+ document.documentElement.classList.add('useSystemFont');
}
- .errorInfo {
- background: #333;
- width: 40rem;
- max-width: 100%;
- border-radius: 10px;
- justify-content: center;
- padding: 1rem;
- margin-bottom: 1rem;
- box-sizing: border-box;
+ const wallpaper = localStorage.getItem('wallpaper');
+ if (wallpaper) {
+ document.documentElement.style.backgroundImage = `url(${wallpaper})`;
}
- .errorInfo > pre {
- text-wrap: auto;
- text-wrap: balance;
+ const customCss = localStorage.getItem('customCss');
+ if (customCss && customCss.length > 0) {
+ const style = document.createElement('style');
+ style.innerHTML = customCss;
+ document.head.appendChild(style);
}
- `;
-
- const addStyle = (styleText) => {
- try {
- let css = document.createElement('style');
- css.appendChild(document.createTextNode(styleText));
- document.head.appendChild(css);
- } catch (e) {
- console.error(e);
- }
+ async function addStyle(styleText) {
+ let css = document.createElement('style');
+ css.appendChild(document.createTextNode(styleText));
+ document.head.appendChild(css);
}
- const renderError = (code, details, solutions = defaultSolutions) => {
- if (document.readyState === 'loading') {
- window.addEventListener('DOMContentLoaded', () => {
- renderError(code, details, solutions);
- });
- try {
- addStyle(onErrorStyle);
- } catch (e) { }
- return;
- }
-
+ function renderError(code, details) {
let errorsElement = document.getElementById('errors');
if (!errorsElement) {
- // エラー描画用のビューになっていない場合は、エラー描画用のビューに切り替える
document.body.innerHTML = `
<svg class="icon-warning" xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-alert-triangle" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
@@ -175,7 +170,10 @@ function boot() {
<span class="button-label-big">Reload / リロード</span>
</button>
<p><b>The following actions may solve the problem. / 以下を行うと解決する可能性があります。</b></p>
- ${solutions.map(x => `<p>${x}</p>`).join('')}
+ <p>Clear the browser cache / ブラウザのキャッシュをクリアする</p>
+ <p>Update your os and browser / ブラウザおよびOSを最新バージョンに更新する</p>
+ <p>Disable an adblocker / アドブロッカーを無効にする</p>
+ <p>&#40;Tor Browser&#41; Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する</p>
<details style="color: #86b300;">
<summary>Other options / その他のオプション</summary>
<a href="/flush">
@@ -201,194 +199,121 @@ function boot() {
`;
errorsElement = document.getElementById('errors');
}
+ const detailsElement = document.createElement('details');
+ detailsElement.id = 'errorInfo';
+ detailsElement.innerHTML = `
+ <br>
+ <summary>
+ <code>ERROR CODE: ${code}</code>
+ </summary>
+ <code>${JSON.stringify(details)}</code>`;
+ errorsElement.appendChild(detailsElement);
+ addStyle(`
+ * {
+ font-family: BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif;
+ }
- if (typeof details === 'string') {
- const errorEl = document.createElement('div');
- errorEl.classList.add('errorInfo');
-
- const titleCodeElement = document.createElement('code');
- titleCodeElement.textContent = `ERROR CODE: ${code}`;
- errorEl.appendChild(titleCodeElement);
-
- errorEl.appendChild(document.createElement('br'));
-
- const detailsCodeElement = document.createElement('code');
- detailsCodeElement.textContent = details;
- errorEl.appendChild(detailsCodeElement);
-
- errorsElement.appendChild(errorEl);
- } else if (details instanceof Error) {
- const errorEl = document.createElement('details');
- errorEl.classList.add('errorInfo');
-
- const summaryElement = document.createElement('summary');
- const titleCodeElement = document.createElement('code');
- titleCodeElement.textContent = `ERROR CODE: ${code}`;
- summaryElement.appendChild(titleCodeElement);
- errorEl.appendChild(summaryElement);
-
- const detailsPreElement = document.createElement('pre');
- const detailsMessageElement = document.createElement('code');
- detailsMessageElement.textContent = details.message;
- detailsPreElement.appendChild(detailsMessageElement);
- detailsPreElement.appendChild(document.createElement('br'));
- const detailsCodeElement = document.createElement('code');
- detailsCodeElement.textContent = details.stack;
- detailsPreElement.appendChild(detailsCodeElement);
- errorEl.appendChild(detailsPreElement);
-
- errorsElement.appendChild(errorEl);
- } else {
- const errorEl = document.createElement('details');
- errorEl.classList.add('errorInfo');
-
- const summaryElement = document.createElement('summary');
- const titleCodeElement = document.createElement('code');
- titleCodeElement.textContent = `ERROR CODE: ${code}`;
- summaryElement.appendChild(titleCodeElement);
- errorEl.appendChild(summaryElement);
-
- const detailsCodeElement = document.createElement('code');
- detailsCodeElement.textContent = JSON.stringify(details);
- errorEl.appendChild(detailsCodeElement);
-
- errorsElement.appendChild(errorEl);
+ #misskey_app,
+ #splash {
+ display: none !important;
}
- addStyle(onErrorStyle);
- }
+ body,
+ html {
+ background-color: #222;
+ color: #dfddcc;
+ justify-content: center;
+ margin: auto;
+ padding: 10px;
+ text-align: center;
+ }
- window.onerror = (e) => {
- console.error(e);
- renderError('SOMETHING_HAPPENED', e);
- };
- window.onunhandledrejection = (e) => {
- console.error(e);
- renderError('SOMETHING_HAPPENED_IN_PROMISE', e);
- };
+ button {
+ border-radius: 999px;
+ padding: 0px 12px 0px 12px;
+ border: none;
+ cursor: pointer;
+ margin-bottom: 12px;
+ }
- let forceError = localStorage.getItem('forceError');
- if (forceError != null) {
- renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.')
- renderError('FORCED_ERROR', Error('This error is forced by having forceError in local storage.'));
- return;
- }
+ .button-big {
+ background: linear-gradient(90deg, rgb(134, 179, 0), rgb(74, 179, 0));
+ line-height: 50px;
+ }
- //#region After DOM loaded
- async function oncontentload() {
- const providedMetaEl = document.getElementById('misskey_meta');
- const meta = providedMetaEl && providedMetaEl.textContent ? JSON.parse(providedMetaEl.textContent) : null;
- const providedAt = providedMetaEl && providedMetaEl.dataset.generatedAt ? parseInt(providedMetaEl.dataset.generatedAt) : 0;
- console.log('providedAt', providedAt, 'now', Date.now());
- if (providedAt < Date.now() - 1000 * 60 * 60 * 24) {
- // 古いデータがなぜか提供された場合は、エラーを描画する
- renderError(
- 'META_PROVIDED_AT_TOO_OLD',
- 'This view is too old. Please reload.',
- [
- 'Reload / リロードする',
- 'Clear the browser cache then reload / ブラウザのキャッシュをクリアしてリロードする',
- 'Disable an adblocker / アドブロッカーを無効にする',
- ]
- );
- return;
+ .button-big:hover {
+ background: rgb(153, 204, 0);
}
- //#region Detect language & fetch translations on first load
- if (!localStorage.hasOwnProperty('locale')) {
- const supportedLangs = LANGS;
- let lang = localStorage.getItem('lang');
- if (lang == null || !supportedLangs.includes(lang)) {
- if (supportedLangs.includes(navigator.language)) {
- lang = navigator.language;
- } else {
- lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
+ .button-small {
+ background: #444;
+ line-height: 40px;
+ }
- // Fallback
- if (lang == null) lang = 'en-US';
- }
- }
+ .button-small:hover {
+ background: #555;
+ }
- const v = meta?.version;
+ .button-label-big {
+ color: #222;
+ font-weight: bold;
+ font-size: 1.2em;
+ padding: 12px;
+ }
- // for https://github.com/misskey-dev/misskey/issues/10202
- if (lang == null || lang.toString == null || lang.toString() === 'null') {
- console.warn('invalid lang value detected!!!', typeof lang, lang);
- lang = 'en-US';
- }
+ .button-label-small {
+ color: rgb(153, 204, 0);
+ font-size: 16px;
+ padding: 12px;
+ }
- const localRes = await window.fetch(`/assets/locales/${lang}.${v}.json`);
- if (localRes.status === 200) {
- localStorage.setItem('lang', lang);
- localStorage.setItem('locale', await localRes.text());
- localStorage.setItem('localeVersion', v);
- } else {
- renderError('LOCALE_FETCH');
- return;
- }
+ a {
+ color: rgb(134, 179, 0);
+ text-decoration: none;
}
- //#endregion
- await import(`/vite/${CLIENT_ENTRY}`)
- .catch(async e => {
- console.error(e);
- renderError('APP_IMPORT', e);
- });
- }
+ p,
+ li {
+ font-size: 16px;
+ }
- if (document.readyState !== 'loading') {
- misskey_loader.add(oncontentload());
- } else {
- window.addEventListener('DOMContentLoaded', () => {
- misskey_loader.add(oncontentload());
- });
- }
- //#endregion
+ .icon-warning {
+ color: #dec340;
+ height: 4rem;
+ padding-top: 2rem;
+ }
- //#region Theme
- const theme = localStorage.getItem('theme');
- if (theme) {
- for (const [k, v] of Object.entries(JSON.parse(theme))) {
- document.documentElement.style.setProperty(`--${k}`, v.toString());
+ h1 {
+ font-size: 1.5em;
+ margin: 1em;
+ }
- // HTMLの theme-color 適用
- if (k === 'htmlThemeColor') {
- for (const tag of document.head.children) {
- if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
- tag.setAttribute('content', v);
- break;
- }
- }
- }
+ code {
+ font-family: Fira, FiraCode, monospace;
}
- }
- const colorScheme = localStorage.getItem('colorScheme');
- if (colorScheme) {
- document.documentElement.style.setProperty('color-scheme', colorScheme);
- }
- //#endregion
- const fontSize = localStorage.getItem('fontSize');
- if (fontSize) {
- document.documentElement.classList.add('f-' + fontSize);
- }
+ #errorInfo {
+ background: #333;
+ margin-bottom: 2rem;
+ padding: 0.5rem 1rem;
+ width: 40rem;
+ border-radius: 10px;
+ justify-content: center;
+ margin: auto;
+ }
- const useSystemFont = localStorage.getItem('useSystemFont');
- if (useSystemFont) {
- document.documentElement.classList.add('useSystemFont');
- }
+ #errorInfo summary {
+ cursor: pointer;
+ }
- const wallpaper = localStorage.getItem('wallpaper');
- if (wallpaper) {
- document.documentElement.style.backgroundImage = `url(${wallpaper})`;
- }
+ #errorInfo summary > * {
+ display: inline;
+ }
- const customCss = localStorage.getItem('customCss');
- if (customCss && customCss.length > 0) {
- const style = document.createElement('style');
- style.innerHTML = customCss;
- document.head.appendChild(style);
+ @media screen and (max-width: 500px) {
+ #errorInfo {
+ width: 50%;
+ }
+ `)
}
-}
-
-boot();
+})();