From c08a6bbeb8edb2411504a3313ad9c8841fca0c6d Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Thu, 28 Mar 2024 15:40:47 +0100 Subject: [PATCH] fix: improve DX & docs upon using vike-{react,vue,solid} configs without installing (fix #1578) --- docs/components/ImplementedBy.tsx | 35 +++++++++++++++ docs/components/index.ts | 1 + docs/pages/ClientOnly/+Page.mdx | 2 +- docs/pages/Layout/+Page.mdx | 4 +- docs/pages/Wrapper/+Page.mdx | 4 +- docs/pages/data-fetching/+Page.mdx | 2 +- docs/pages/extends/+Page.mdx | 45 +++++++++++++++++-- docs/pages/head/+Page.mdx | 2 +- docs/pages/onCreateApp/+Page.mdx | 5 ++- docs/pages/ssr/+Page.mdx | 6 +-- docs/pages/stream/+Page.mdx | 6 +-- docs/pages/useData/+Page.mdx | 2 +- docs/pages/usePageContext/+Page.mdx | 2 +- .../importUserCode/v1-design/getVikeConfig.ts | 35 ++++++++++++--- 14 files changed, 125 insertions(+), 26 deletions(-) create mode 100644 docs/components/ImplementedBy.tsx diff --git a/docs/components/ImplementedBy.tsx b/docs/components/ImplementedBy.tsx new file mode 100644 index 0000000000..d164186849 --- /dev/null +++ b/docs/components/ImplementedBy.tsx @@ -0,0 +1,35 @@ +export { ImplementedBy } + +import { Link } from '@brillout/docpress' +import { UiFrameworkVikeExtension, UiFrameworkVikeExtensionNames } from '../components' +import React from 'react' + +function ImplementedBy({ + children, + by, + noCustomGuide +}: { children: React.ReactNode; by?: React.ReactNode; noCustomGuide?: true }) { + return ( + <> +
+ Implemented by: {by ?? }. +
+

+ You need to use{' '} + {by ?? ( + <> + a + + )}{' '} + in order to use the {children}. + {!noCustomGuide && ( + <> + {' '}If you don't use {by ?? } then see{' '} + . + + )} +

+
+ + ) +} diff --git a/docs/components/index.ts b/docs/components/index.ts index 721b94fc33..955f97f770 100644 --- a/docs/components/index.ts +++ b/docs/components/index.ts @@ -9,3 +9,4 @@ export { RecommendationRouterLibraries } from './RecommendationRouterLibraries' export { HookTypeScriptHints } from './HookTypeScriptHints' export { ViteLazyTranspilingContradiction } from './ViteLazyTranspilingContradiction' export { Example, Github } from './Example' +export { ImplementedBy } from './ImplementedBy' diff --git a/docs/pages/ClientOnly/+Page.mdx b/docs/pages/ClientOnly/+Page.mdx index 903951474f..f2acea8755 100644 --- a/docs/pages/ClientOnly/+Page.mdx +++ b/docs/pages/ClientOnly/+Page.mdx @@ -2,7 +2,7 @@ import { Link } from '@brillout/docpress' import { ClientOnlyCommon } from './ClientOnlyCommon.tsx' import { UiFrameworkVikeExtension } from '../../components' -Provided by: (or yourself). +Implemented by: (or yourself). The `` wrapper enables you to render and load a component only on the client-side. diff --git a/docs/pages/Layout/+Page.mdx b/docs/pages/Layout/+Page.mdx index d4e809bf00..e3b9959242 100644 --- a/docs/pages/Layout/+Page.mdx +++ b/docs/pages/Layout/+Page.mdx @@ -1,7 +1,7 @@ import { Link, RepoLink } from '@brillout/docpress' -import { UiFrameworkVikeExtension } from '../../components' +import { UiFrameworkVikeExtension, ImplementedBy } from '../../components' -Provided by: (or yourself). +`Layout` setting > **What are layouts?** > Pages can have different layouts: diff --git a/docs/pages/Wrapper/+Page.mdx b/docs/pages/Wrapper/+Page.mdx index 4035bcb643..eb3343984d 100644 --- a/docs/pages/Wrapper/+Page.mdx +++ b/docs/pages/Wrapper/+Page.mdx @@ -1,7 +1,7 @@ import { Link } from '@brillout/docpress' -import { UiFrameworkVikeExtension } from '../../components' +import { UiFrameworkVikeExtension, ImplementedBy } from '../../components' -Provided by: (or yourself). +`Wrapper` setting The `Wrapper` setting wraps your Page component with another component. diff --git a/docs/pages/data-fetching/+Page.mdx b/docs/pages/data-fetching/+Page.mdx index fab67826a8..3613db19a3 100644 --- a/docs/pages/data-fetching/+Page.mdx +++ b/docs/pages/data-fetching/+Page.mdx @@ -54,7 +54,7 @@ import { useData } from 'vike-solid/useData' const { name, price } = data ``` -> `useData()` is provided by the . If you don't use then see . +> `useData()` is implemented by the . If you don't use then see . The `data()` hook is only meant for fetching the initial data of a page (in technical words: the SSR data). For other use cases see the sections below API routes and RPC. diff --git a/docs/pages/extends/+Page.mdx b/docs/pages/extends/+Page.mdx index ab299071a2..07f2130c53 100644 --- a/docs/pages/extends/+Page.mdx +++ b/docs/pages/extends/+Page.mdx @@ -1,14 +1,53 @@ import { Link, Warning } from '@brillout/docpress' -You use `extends` to install . +To install Vike extensions you use `extends`: ```js // /pages/+config.js -import vikeReact from 'vike-react' +import vikeReact from 'vike-react/config' export default { - // Inherit the configuration set by vike-react + // Install vike-react. + // In technical terms: inherit the configuration set by `vike-react/config`. extends: vikeReact } ``` + +## Inheritance + +Note that config inheritance also applies to `extends`. + +For example, you can use two completely different rendering strategy: some pages can use Vue without SSR while other pages can use React with SSR. + +```js +// /pages/admin/+config.js + +import vikeVue from 'vike-vue/config' + +// Applies only to Admin Panel pages: +// /pages/admin/income/+Page.js +// /pages/admin/kpi/+Page.js +// ... + +// Make all Admin Panel pages use Vue without SSR: +export default { + ssr: false, + extends: [vikeVue] +} +``` + +```js +// /pages/product/@id/+config.js + +import vikeReact from 'vike-react/config' + +// Applies only to the product page: +// /pages/product/@id/+Page.js + +// Make the product page use React with SSR: +export default { + ssr: true, + extends: [vikeReact] +} +``` diff --git a/docs/pages/head/+Page.mdx b/docs/pages/head/+Page.mdx index f89091d5a5..8770eaccf4 100644 --- a/docs/pages/head/+Page.mdx +++ b/docs/pages/head/+Page.mdx @@ -7,7 +7,7 @@ To add `` tags, such as `` and `<meta name="description">`, you can - The page settings <Link href="#title-favicon">`title` & `favicon`</Link>. - :construction: The <Link href="#usehead">`useHead()`</Link> component hook. -> These options are provided by the <UiFrameworkVikeExtension />. See <Link href="#without-vike-extension" /> if you don't use such extension. +> These options are implemented by the <UiFrameworkVikeExtension />. See <Link href="#without-vike-extension" /> if you don't use such extension. ## `Head` diff --git a/docs/pages/onCreateApp/+Page.mdx b/docs/pages/onCreateApp/+Page.mdx index 443053a07e..74e49d11f2 100644 --- a/docs/pages/onCreateApp/+Page.mdx +++ b/docs/pages/onCreateApp/+Page.mdx @@ -1,7 +1,8 @@ import { Link } from '@brillout/docpress' +import { ImplementedBy } from '../../components' -Environment: server, client. -Provided by: <Link href="/extensions"><code>vike-vue</code> extension</Link> +Environment: server, client. +<ImplementedBy by={<code>vike-vue</code>} noCustomGuide={true}>`onCreateApp()` hook</ImplementedBy> The `onCreateApp()` hook is called right after the [Vue app](https://vuejs.org/guide/essentials/application.html) is created, giving you the opportunity to extend it, diff --git a/docs/pages/ssr/+Page.mdx b/docs/pages/ssr/+Page.mdx index fb1c131933..2c0815e4c4 100644 --- a/docs/pages/ssr/+Page.mdx +++ b/docs/pages/ssr/+Page.mdx @@ -1,8 +1,8 @@ import { Link } from '@brillout/docpress' -import { UiFrameworkVikeExtension } from '../../components' +import { UiFrameworkVikeExtension, ImplementedBy } from '../../components' -Default value: `true`. -Provided by: <UiFrameworkVikeExtension /> (or <Link href="#without-vike-extension">yourself</Link>). +Default value: `true`. +<ImplementedBy>`ssr` setting</ImplementedBy> Setting to enable/disable Server-Side Rendering (SSR). You can disable SSR for all your pages or only for some pages. diff --git a/docs/pages/stream/+Page.mdx b/docs/pages/stream/+Page.mdx index 425c0a9105..38db4db9df 100644 --- a/docs/pages/stream/+Page.mdx +++ b/docs/pages/stream/+Page.mdx @@ -1,10 +1,10 @@ import { Link } from '@brillout/docpress' -import { UiFrameworkVikeExtension } from '../../components' +import { UiFrameworkVikeExtension, ImplementedBy } from '../../components' Default value: `false`. (Or `true` if using a <Link href="/extensions">Vike extension</Link> that requires streaming.) -Requires: <Link href="/ssr">`ssr: true`</Link>. -Provided by: <UiFrameworkVikeExtension /> (or <Link href="#without-vike-extension">yourself</Link>). +Requires: <Link href="/ssr">`ssr: true`</Link>. +<ImplementedBy>`stream` setting</ImplementedBy> Setting to disable/enable <Link href="/streaming">HTML Streaming</Link>. diff --git a/docs/pages/useData/+Page.mdx b/docs/pages/useData/+Page.mdx index 71a3b90684..81529fc15c 100644 --- a/docs/pages/useData/+Page.mdx +++ b/docs/pages/useData/+Page.mdx @@ -2,7 +2,7 @@ import { Link } from '@brillout/docpress' import { UiFrameworkVikeExtension } from '../../components' Environment: server, client. -Provided by: <UiFrameworkVikeExtension /> (or <Link href="#without-vike-extension">yourself</Link>). +Implemented by: <UiFrameworkVikeExtension /> (or <Link href="#without-vike-extension">yourself</Link>). The `useData()` component hook allows you to access the data that is returned by a <Link href="/data">`data()` hook</Link>. diff --git a/docs/pages/usePageContext/+Page.mdx b/docs/pages/usePageContext/+Page.mdx index f223ddac17..7bdd45faf5 100644 --- a/docs/pages/usePageContext/+Page.mdx +++ b/docs/pages/usePageContext/+Page.mdx @@ -3,7 +3,7 @@ import { Link, RepoLink } from '@brillout/docpress' import { UiFrameworkVikeExtension } from '../../components' Environment: server, client. -Provided by: <UiFrameworkVikeExtension /> (or <Link href="#without-vike-extension">yourself</Link>). +Implemented by: <UiFrameworkVikeExtension /> (or <Link href="#without-vike-extension">yourself</Link>). The `usePageContext()` hook enables any UI component to access the <Link href="/pageContext">`pageContext`</Link> object. diff --git a/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts b/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts index 985a223704..5a2b66f983 100644 --- a/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts +++ b/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts @@ -1046,7 +1046,34 @@ function assertNoUnexpectedPlusSign(filePath: string, fileName: string) { */ function handleUnknownConfig(configName: string, configNames: string[], filePathToShowToUser: string) { - let errMsg = `${filePathToShowToUser} defines an unknown config ${pc.cyan(configName)}` + { + const ui = ['vike-react', 'vike-vue', 'vike-solid'] as const + const knownVikeExntensionConfigs = { + description: ui, + favicon: ui, + Head: ui, + Layout: ui, + onCreateApp: ['vike-vue'], + title: ui, + ssr: ui, + stream: ui, + Wrapper: ui + } as const + if (configName in knownVikeExntensionConfigs) { + const requiredVikeExtension = knownVikeExntensionConfigs[configName as keyof typeof knownVikeExntensionConfigs] + assertUsage( + false, + [ + `${filePathToShowToUser} uses the config ${pc.cyan(configName)} (https://vike.dev/${configName})`, + `which requires the Vike extension ${requiredVikeExtension.map((e) => pc.bold(e)).join('/')}.`, + `Make sure to install the Vike extension,`, + `and make sure it applies to ${filePathToShowToUser} as explained at https://vike.dev/extends#inheritance.` + ].join(' ') + ) + } + } + + let errMsg = `${filePathToShowToUser} sets an unknown config ${pc.cyan(configName)}` let configNameSimilar: string | null = null if (configName === 'page') { configNameSimilar = 'Page' @@ -1055,16 +1082,12 @@ function handleUnknownConfig(configName: string, configNames: string[], filePath } if (configNameSimilar) { assert(configNameSimilar !== configName) - errMsg += `, did you mean to define ${pc.cyan(configNameSimilar)} instead?` + errMsg += `, did you mean to set ${pc.cyan(configNameSimilar)} instead?` if (configName === 'page') { errMsg += ` (The name of the config ${pc.cyan('Page')} starts with a capital letter ${pc.cyan( 'P' )} because it usually defines a UI component: a ubiquitous JavaScript convention is to start the name of UI components with a capital letter.)` } - } else { - errMsg += `, you need to define the config ${pc.cyan(configName)} by using ${pc.cyan( - 'config.meta' - )} https://vike.dev/meta` } assertUsage(false, errMsg) }