Code-split homepages

## Ticket
97

## Issue
8% of the ui.js chunk consists of the 5 custom homepages
This commit is contained in:
infinite-persistence 2021-10-26 11:23:11 +08:00
parent 9569b6c7a5
commit 310fc81bd9
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
7 changed files with 55 additions and 15 deletions

View file

@ -1,3 +1,6 @@
// Data is lazy-loaded in `doSetHomepage()`
window.odysee_homepages = window.odysee_homepages || {};
module.exports = { module.exports = {
en: {}, en: null,
}; };

View file

@ -14,6 +14,7 @@ import {
selectLanguage, selectLanguage,
selectLoadedLanguages, selectLoadedLanguages,
selectThemePath, selectThemePath,
selectHomepageCode,
} from 'redux/selectors/settings'; } from 'redux/selectors/settings';
import { import {
selectIsUpgradeAvailable, selectIsUpgradeAvailable,
@ -21,7 +22,7 @@ import {
selectModal, selectModal,
selectActiveChannelClaim, selectActiveChannelClaim,
} from 'redux/selectors/app'; } from 'redux/selectors/app';
import { doGetWalletSyncPreference, doSetLanguage } from 'redux/actions/settings'; import { doGetWalletSyncPreference, doSetLanguage, doSetHomepage } from 'redux/actions/settings';
import { doSyncLoop } from 'redux/actions/sync'; import { doSyncLoop } from 'redux/actions/sync';
import { import {
doDownloadUpgradeRequested, doDownloadUpgradeRequested,
@ -38,6 +39,7 @@ const select = (state) => ({
accessToken: selectAccessToken(state), accessToken: selectAccessToken(state),
theme: selectThemePath(state), theme: selectThemePath(state),
language: selectLanguage(state), language: selectLanguage(state),
homepageCode: selectHomepageCode(state),
syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state), syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
languages: selectLoadedLanguages(state), languages: selectLoadedLanguages(state),
autoUpdateDownloaded: selectAutoUpdateDownloaded(state), autoUpdateDownloaded: selectAutoUpdateDownloaded(state),
@ -58,6 +60,7 @@ const perform = (dispatch) => ({
fetchChannelListMine: () => dispatch(doFetchChannelListMine()), fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
fetchCollectionListMine: () => dispatch(doFetchCollectionListMine()), fetchCollectionListMine: () => dispatch(doFetchCollectionListMine()),
setLanguage: (language) => dispatch(doSetLanguage(language)), setLanguage: (language) => dispatch(doSetLanguage(language)),
doSetHomepage: (value) => dispatch(doSetHomepage(value)),
signIn: () => dispatch(doSignIn()), signIn: () => dispatch(doSignIn()),
requestDownloadUpgrade: () => dispatch(doDownloadUpgradeRequested()), requestDownloadUpgrade: () => dispatch(doDownloadUpgradeRequested()),
updatePreferences: () => dispatch(doGetAndPopulatePreferences()), updatePreferences: () => dispatch(doGetAndPopulatePreferences()),

View file

@ -72,6 +72,7 @@ const imaLibraryPath = 'https://imasdk.googleapis.com/js/sdkloader/ima3.js';
type Props = { type Props = {
language: string, language: string,
languages: Array<string>, languages: Array<string>,
homepageCode: string,
theme: string, theme: string,
user: ?{ id: string, has_verified_email: boolean, is_reward_approved: boolean }, user: ?{ id: string, has_verified_email: boolean, is_reward_approved: boolean },
location: { pathname: string, hash: string, search: string }, location: { pathname: string, hash: string, search: string },
@ -89,6 +90,7 @@ type Props = {
requestDownloadUpgrade: () => void, requestDownloadUpgrade: () => void,
onSignedIn: () => void, onSignedIn: () => void,
setLanguage: (string) => void, setLanguage: (string) => void,
doSetHomepage: (string) => void,
isUpgradeAvailable: boolean, isUpgradeAvailable: boolean,
autoUpdateDownloaded: boolean, autoUpdateDownloaded: boolean,
updatePreferences: () => Promise<any>, updatePreferences: () => Promise<any>,
@ -130,7 +132,9 @@ function App(props: Props) {
syncError, syncError,
language, language,
languages, languages,
homepageCode,
setLanguage, setLanguage,
doSetHomepage,
updatePreferences, updatePreferences,
getWalletSyncPref, getWalletSyncPref,
rewards, rewards,
@ -307,6 +311,11 @@ function App(props: Props) {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [language, languages]); }, [language, languages]);
// Fetch homepage for the first time
useEffect(() => {
doSetHomepage(homepageCode);
}, []); // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => { useEffect(() => {
if (shouldMigrateLanguage) { if (shouldMigrateLanguage) {
setLanguage(shouldMigrateLanguage); setLanguage(shouldMigrateLanguage);

View file

@ -14,6 +14,7 @@ import { doAlertWaitingForSync, doGetAndPopulatePreferences } from 'redux/action
import { selectPrefsReady } from 'redux/selectors/sync'; import { selectPrefsReady } from 'redux/selectors/sync';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import { getDefaultLanguage } from 'util/default-languages'; import { getDefaultLanguage } from 'util/default-languages';
import homepages from 'homepages';
const { DEFAULT_LANGUAGE } = require('config'); const { DEFAULT_LANGUAGE } = require('config');
const { SDK_SYNC_KEYS } = SHARED_PREFERENCES; const { SDK_SYNC_KEYS } = SHARED_PREFERENCES;
@ -298,13 +299,22 @@ export function doFetchLanguage(language) {
} }
export function doSetHomepage(code) { export function doSetHomepage(code) {
return (dispatch, getState) => { return async (dispatch, getState) => {
let languageCode; let languageCode;
if (code === getDefaultLanguage()) { if (code === getDefaultLanguage()) {
languageCode = null; languageCode = null;
} else { } else {
languageCode = code; languageCode = code;
} }
const homepage = homepages[code || 'en'];
if (homepage && homepage.lazyLoad) {
const homepageData = await homepage.lazyLoad();
if (homepageData) {
window.odysee_homepages[code || 'en'] = homepageData.default;
}
}
dispatch(doSetClientSetting(SETTINGS.HOMEPAGE, languageCode)); dispatch(doSetClientSetting(SETTINGS.HOMEPAGE, languageCode));
}; };
} }

View file

@ -53,21 +53,16 @@ export const selectThemePath = createSelector(
); );
export const selectHomepageCode = createSelector(makeSelectClientSetting(SETTINGS.HOMEPAGE), (setting) => { export const selectHomepageCode = createSelector(makeSelectClientSetting(SETTINGS.HOMEPAGE), (setting) => {
return homepages[setting] ? setting : getDefaultHomepageKey(); return Object.keys(homepages).includes(setting) ? setting : getDefaultHomepageKey();
}); });
export const selectLanguage = createSelector(makeSelectClientSetting(SETTINGS.LANGUAGE), (setting) => { export const selectLanguage = createSelector(makeSelectClientSetting(SETTINGS.LANGUAGE), (setting) => {
return setting || getDefaultLanguage(); return setting || getDefaultLanguage();
}); });
export const selectHomepageData = createSelector( export const selectHomepageData = (state) => {
// using homepage setting, const homepageCode = selectHomepageCode(state);
selectHomepageCode, return window.odysee_homepages[homepageCode] || {};
(homepageCode) => { };
// homepages = { 'en': homepageFile, ... }
// mixin Homepages here
return homepages[homepageCode] || homepages['en'] || {};
}
);
export const selectosNotificationsEnabled = makeSelectClientSetting(SETTINGS.OS_NOTIFICATIONS_ENABLED); export const selectosNotificationsEnabled = makeSelectClientSetting(SETTINGS.OS_NOTIFICATIONS_ENABLED);

View file

@ -77,9 +77,11 @@ export const getHomepageRowForCat = (cat: HomepageCat) => {
} }
let urlParams = new URLSearchParams(); let urlParams = new URLSearchParams();
if (cat.claimType) { if (cat.claimType) {
urlParams.set(CS.CLAIM_TYPE, cat.claimType); urlParams.set(CS.CLAIM_TYPE, cat.claimType);
} }
if (cat.channelIds) { if (cat.channelIds) {
urlParams.set(CS.CHANNEL_IDS_KEY, cat.channelIds.join(',')); urlParams.set(CS.CHANNEL_IDS_KEY, cat.channelIds.join(','));
} }
@ -88,11 +90,13 @@ export const getHomepageRowForCat = (cat: HomepageCat) => {
// can intend no limit, numerica auto limit, specific limit. // can intend no limit, numerica auto limit, specific limit.
let limitClaims; let limitClaims;
if (typeof cat.channelLimit === 'string' && cat.channelIds && cat.channelIds.length) { if (typeof cat.channelLimit === 'string' && cat.channelIds && cat.channelIds.length) {
if (cat.channelLimit === 'auto') { if (cat.channelLimit === 'auto') {
limitClaims = getLimitPerChannel(cat.channelIds.length, isChannelType); limitClaims = getLimitPerChannel(cat.channelIds.length, isChannelType);
} else if (cat.channelLimit) { } else if (cat.channelLimit) {
const limitNumber = Number(cat.channelLimit); const limitNumber = Number(cat.channelLimit);
// eslint-disable-next-line // eslint-disable-next-line
if (limitNumber === limitNumber && limitNumber !== 0) { if (limitNumber === limitNumber && limitNumber !== 0) {
// because javascript and NaN !== NaN // because javascript and NaN !== NaN
@ -293,9 +297,11 @@ export function GetLinksData(
}), }),
}, },
}; };
// $FlowFixMe flow thinks this might not be Array<string> // $FlowFixMe flow thinks this might not be Array<string>
rowData.push(RECENT_FROM_FOLLOWING); rowData.push(RECENT_FROM_FOLLOWING);
} }
if (isHomepage && !CUSTOM_HOMEPAGE) { if (isHomepage && !CUSTOM_HOMEPAGE) {
if (followedTags) { if (followedTags) {
const TRENDING_FOR_TAGS = { const TRENDING_FOR_TAGS = {
@ -310,6 +316,7 @@ export function GetLinksData(
limitClaimsPerChannel: 2, limitClaimsPerChannel: 2,
}, },
}; };
followedTags.forEach((tag: Tag) => { followedTags.forEach((tag: Tag) => {
const tagName = `#${toCapitalCase(tag.name)}`; const tagName = `#${toCapitalCase(tag.name)}`;
individualTagDataItems.push({ individualTagDataItems.push({
@ -322,7 +329,11 @@ export function GetLinksData(
}, },
}); });
}); });
if (showPersonalizedTags && !showIndividualTags) rowData.push(TRENDING_FOR_TAGS);
if (showPersonalizedTags && !showIndividualTags) {
rowData.push(TRENDING_FOR_TAGS);
}
if (showPersonalizedTags && showIndividualTags) { if (showPersonalizedTags && showIndividualTags) {
individualTagDataItems.forEach((item: RowDataItem) => { individualTagDataItems.forEach((item: RowDataItem) => {
rowData.push(item); rowData.push(item);
@ -330,6 +341,7 @@ export function GetLinksData(
} }
} }
} }
if (!CUSTOM_HOMEPAGE) { if (!CUSTOM_HOMEPAGE) {
if (!authenticated) { if (!authenticated) {
rowData.push(YOUTUBE_CREATOR_ROW); rowData.push(YOUTUBE_CREATOR_ROW);
@ -338,6 +350,7 @@ export function GetLinksData(
rowData.push(LATEST_FROM_LBRY); rowData.push(LATEST_FROM_LBRY);
if (!showPersonalizedChannels) rowData.push(TOP_CHANNELS); if (!showPersonalizedChannels) rowData.push(TOP_CHANNELS);
} }
// TODO: provide better method for exempting from homepage // TODO: provide better method for exempting from homepage
(Object.values(all): any) (Object.values(all): any)
.filter((row) => !(isHomepage && row.name === 'news')) .filter((row) => !(isHomepage && row.name === 'news'))

View file

@ -10,7 +10,14 @@ export const getDefaultLanguage = () => {
// If homepages has a key "zh-Hant" return that, otherwise return "zh", otherwise "en" // If homepages has a key "zh-Hant" return that, otherwise return "zh", otherwise "en"
export const getDefaultHomepageKey = () => { export const getDefaultHomepageKey = () => {
const language = getDefaultLanguage(); const language = getDefaultLanguage();
return (homepages[language] && language) || (homepages[language.slice(0, 2)] && language.slice(0, 2)) || DEFAULT_LANG; const keys = Object.keys(homepages);
if (keys.includes(language)) {
return language;
} else if (keys.include(language.slice(0, 2))) {
return language.slice(0, 2);
} else {
return DEFAULT_LANG;
}
}; };
/** /**