Skip to content

Commit 74f2757

Browse files
committed
feat: useQwikRouter
this makes it possible to put the routerhead in root as well
1 parent 299a865 commit 74f2757

File tree

21 files changed

+359
-254
lines changed

21 files changed

+359
-254
lines changed

.changeset/every-badgers-bake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/router': minor
3+
---
4+
5+
FEAT: useQwikRouter() hook replaces QwikRouterProvider. This gives access to the context immediately and is slightly more efficient.

e2e/adapters-e2e/src/components/router-head/router-head.tsx

Lines changed: 0 additions & 24 deletions
This file was deleted.

e2e/adapters-e2e/src/root.tsx

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
import { component$ } from '@qwik.dev/core';
2-
import { QwikRouterProvider, RouterOutlet } from '@qwik.dev/router';
3-
import { RouterHead } from './components/router-head/router-head';
2+
import { RouterOutlet, useDocumentHead, useLocation, useQwikRouter } from '@qwik.dev/router';
43

54
export default component$(() => {
6-
/**
7-
* The root of a QwikCity site always start with the <QwikCityProvider> component, immediately
8-
* followed by the document's <head> and <body>.
9-
*
10-
* Don't remove the `<head>` and `<body>` elements.
11-
*/
5+
useQwikRouter();
6+
7+
const head = useDocumentHead();
8+
const loc = useLocation();
129

1310
return (
14-
<QwikRouterProvider>
11+
<>
1512
<head>
1613
<meta charset="utf-8" />
17-
<RouterHead />
14+
<title>{head.title}</title>
15+
16+
<link rel="canonical" href={loc.url.href} />
17+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
18+
19+
{head.meta.map((m) => (
20+
<meta key={m.key} {...m} />
21+
))}
22+
23+
{head.links.map((l) => (
24+
<link key={l.key} {...l} />
25+
))}
26+
{/* we don't use styles or scripts here */}
1827
</head>
19-
<body lang="en">
28+
<body>
2029
<RouterOutlet />
2130
</body>
22-
</QwikRouterProvider>
31+
</>
2332
);
2433
});

packages/docs/src/root.tsx

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import { component$, useContextProvider, useStore } from '@qwik.dev/core';
22
import { Insights } from '@qwik.dev/core/insights';
3-
import { QwikRouterProvider, RouterOutlet, ServiceWorkerRegister } from '@qwik.dev/router';
3+
import {
4+
RouterOutlet,
5+
ServiceWorkerRegister,
6+
useDocumentHead,
7+
useLocation,
8+
useQwikRouter,
9+
} from '@qwik.dev/router';
410
import RealMetricsOptimization from './components/real-metrics-optimization/real-metrics-optimization';
5-
import { RouterHead } from './components/router-head/router-head';
611
import { BUILDER_PUBLIC_API_KEY } from './constants';
712
import { GlobalStore, type SiteStore } from './context';
813
import './global.css';
14+
import { ThemeScript } from './components/router-head/theme-script';
15+
import { Social } from './components/router-head/social';
16+
import { Vendor } from './components/router-head/vendor';
917

1018
export const uwu = /*javascript*/ `
1119
;(function () {
@@ -41,6 +49,10 @@ export const uwu = /*javascript*/ `
4149
`;
4250

4351
export default component$(() => {
52+
useQwikRouter();
53+
const head = useDocumentHead();
54+
const { url } = useLocation();
55+
4456
const store = useStore<SiteStore>({
4557
headerMenuOpen: false,
4658
sideMenuOpen: false,
@@ -49,12 +61,94 @@ export default component$(() => {
4961

5062
useContextProvider(GlobalStore, store);
5163

64+
const title = head.title
65+
? `${head.title} 📚 Qwik Documentation`
66+
: `Qwik - Framework reimagined for the edge`;
67+
const description =
68+
head.meta.find((m) => m.name === 'description')?.content ||
69+
`No hydration, auto lazy-loading, edge-optimized, and fun 🎉!`;
70+
71+
const OGImage = {
72+
imageURL: '',
73+
ogImgTitle: '',
74+
ogImgSubTitle: '' as string | undefined,
75+
76+
get URL() {
77+
//turn the title into array with [0] -> Title [1] -> subTitle
78+
const arrayedTitle = title.split(' | ');
79+
const ogImageUrl = new URL('https://opengraphqwik.vercel.app/api/og?level=1');
80+
81+
// biggerTitle
82+
this.ogImgTitle = arrayedTitle[0];
83+
//smallerTitle
84+
this.ogImgSubTitle = arrayedTitle[1]
85+
? arrayedTitle[1].replace(' 📚 Qwik Documentation', '')
86+
: undefined;
87+
88+
//decide whether or not to show dynamic OGimage or use docs default social card
89+
if (this.ogImgSubTitle == undefined || this.ogImgTitle == undefined) {
90+
this.imageURL = new URL(`/logos/social-card.jpg`, url).href;
91+
92+
return this.imageURL;
93+
} else {
94+
ogImageUrl.searchParams.set('title', this.ogImgTitle);
95+
ogImageUrl.searchParams.set('subtitle', this.ogImgSubTitle);
96+
// ogImageUrl.searchParams.set('level', this.routeLevel.toString());
97+
98+
this.imageURL = ogImageUrl.toString();
99+
100+
return this.imageURL;
101+
}
102+
},
103+
};
104+
52105
return (
53-
<QwikRouterProvider>
106+
<>
54107
<head>
55108
<meta charset="utf-8" />
109+
110+
<title>{title}</title>
111+
<meta name="description" content={description} />
112+
<link rel="canonical" href={head.frontmatter?.canonical || url.href} />
113+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
114+
<meta name="apple-mobile-web-app-title" content="Qwik" />
115+
<meta name="application-name" content="Qwik" />
116+
<meta name="apple-mobile-web-app-title" content="Qwik" />
117+
<meta name="theme-color" content="#006ce9" />
118+
<meta name="color-scheme" content="dark light" />
119+
120+
<link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png" />
121+
<link rel="icon" href="/favicons/favicon.svg" type="image/svg+xml" />
122+
123+
{import.meta.env.PROD && (
124+
<>
125+
<Social title={title} description={description} href={url.href} ogImage={OGImage.URL} />
126+
<Vendor />
127+
</>
128+
)}
129+
130+
{/* The below are tags that were collected from all the `head` exports in the current route. */}
131+
{head.meta
132+
// Skip description because that was already added at the top
133+
.filter((s) => s.name !== 'description')
134+
.map((m, key) => (
135+
<meta key={key} {...m} />
136+
))}
137+
138+
{head.links.map((l, key) => (
139+
<link key={key} {...l} />
140+
))}
141+
142+
{head.styles.map((s, key) => (
143+
<style key={key} {...s.props} dangerouslySetInnerHTML={s.style} />
144+
))}
145+
146+
{head.scripts.map((s, key) => (
147+
<script key={key} {...s.props} dangerouslySetInnerHTML={s.script} />
148+
))}
149+
150+
<ThemeScript />
56151
<script dangerouslySetInnerHTML={uwu} />
57-
<RouterHead />
58152

59153
<ServiceWorkerRegister />
60154

@@ -67,10 +161,11 @@ export default component$(() => {
67161
'menu-open': store.sideMenuOpen,
68162
}}
69163
>
164+
{/* This renders the current route, including all Layout components. */}
70165
<RouterOutlet />
71166
<RealMetricsOptimization builderApiKey={BUILDER_PUBLIC_API_KEY} />
72167
</body>
73-
</QwikRouterProvider>
168+
</>
74169
);
75170
});
76171

packages/docs/src/routes/api/qwik-router/api.json

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@
558558
}
559559
],
560560
"kind": "Variable",
561-
"content": "> Warning: This API is now obsolete.\n> \n> Use `QwikRouterMockProvider` instead. Will be removed in V3\n> \n\n\n```typescript\nQwikCityMockProvider: import(\"@qwik.dev/core\").Component<QwikRouterMockProps>\n```",
561+
"content": "> Warning: This API is now obsolete.\n> \n> Use `useQwikMockRouter()` instead. Will be removed in V3\n> \n\n\n```typescript\nQwikCityMockProvider: import(\"@qwik.dev/core\").Component<QwikRouterMockProps>\n```",
562562
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/qwik-router-component.tsx",
563563
"mdFile": "router.qwikcitymockprovider.md"
564564
},
@@ -586,7 +586,7 @@
586586
}
587587
],
588588
"kind": "TypeAlias",
589-
"content": "> Warning: This API is now obsolete.\n> \n> Use `QwikRouterProps` instead. will be removed in V3\n> \n\n\n```typescript\nexport type QwikCityProps = QwikRouterProps;\n```\n**References:** [QwikRouterProps](#qwikrouterprops)",
589+
"content": "> Warning: This API is now obsolete.\n> \n> Use `QwikRouterProps` instead. Will be removed in v3.\n> \n\n\n```typescript\nexport type QwikCityProps = QwikRouterProps;\n```\n**References:** [QwikRouterProps](#qwikrouterprops)",
590590
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/qwik-router-component.tsx",
591591
"mdFile": "router.qwikcityprops.md"
592592
},
@@ -600,7 +600,7 @@
600600
}
601601
],
602602
"kind": "Variable",
603-
"content": "> Warning: This API is now obsolete.\n> \n> Use `QwikRouterProvider` instead. will be removed in V3\n> \n\n\n```typescript\nQwikCityProvider: import(\"@qwik.dev/core\").Component<QwikRouterProps>\n```",
603+
"content": "> Warning: This API is now obsolete.\n> \n> Use `useQwikRouter()` instead. Will be removed in v3.\n> \n\n\n```typescript\nQwikCityProvider: import(\"@qwik.dev/core\").Component<QwikRouterProps>\n```",
604604
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/qwik-router-component.tsx",
605605
"mdFile": "router.qwikcityprovider.md"
606606
},
@@ -670,7 +670,7 @@
670670
}
671671
],
672672
"kind": "Variable",
673-
"content": "```typescript\nQwikRouterProvider: import(\"@qwik.dev/core\").Component<QwikRouterProps>\n```",
673+
"content": "This is a wrapper around the `useQwikRouter()` hook. We recommend using the hook instead of this component.\n\n\n```typescript\nQwikRouterProvider: import(\"@qwik.dev/core\").Component<QwikRouterProps>\n```",
674674
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/qwik-router-component.tsx",
675675
"mdFile": "router.qwikrouterprovider.md"
676676
},
@@ -968,6 +968,20 @@
968968
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/use-functions.ts",
969969
"mdFile": "router.usepreventnavigate_.md"
970970
},
971+
{
972+
"name": "useQwikRouter",
973+
"id": "useqwikrouter",
974+
"hierarchy": [
975+
{
976+
"name": "useQwikRouter",
977+
"id": "useqwikrouter"
978+
}
979+
],
980+
"kind": "Function",
981+
"content": "This hook initializes Qwik Router, providing the necessary context for it to work.\n\nThis hook should be used once, at the root of your application.\n\n\n```typescript\nuseQwikRouter: (props?: QwikRouterProps) => void\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nprops\n\n\n</td><td>\n\n[QwikRouterProps](#qwikrouterprops)\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n</tbody></table>\n**Returns:**\n\nvoid",
982+
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/qwik-router-component.tsx",
983+
"mdFile": "router.useqwikrouter.md"
984+
},
971985
{
972986
"name": "valibot$",
973987
"id": "valibot_",

packages/docs/src/routes/api/qwik-router/index.mdx

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,7 +1815,7 @@ export type QwikCityMockProps = QwikRouterMockProps;
18151815
18161816
> Warning: This API is now obsolete.
18171817
>
1818-
> Use `QwikRouterMockProvider` instead. Will be removed in V3
1818+
> Use `useQwikMockRouter()` instead. Will be removed in V3
18191819
18201820
```typescript
18211821
QwikCityMockProvider: import("@qwik.dev/core").Component<QwikRouterMockProps>;
@@ -1841,7 +1841,7 @@ export type QwikCityPlan = QwikRouterConfig;
18411841
18421842
> Warning: This API is now obsolete.
18431843
>
1844-
> Use `QwikRouterProps` instead. will be removed in V3
1844+
> Use `QwikRouterProps` instead. Will be removed in v3.
18451845
18461846
```typescript
18471847
export type QwikCityProps = QwikRouterProps;
@@ -1855,7 +1855,7 @@ export type QwikCityProps = QwikRouterProps;
18551855
18561856
> Warning: This API is now obsolete.
18571857
>
1858-
> Use `QwikRouterProvider` instead. will be removed in V3
1858+
> Use `useQwikRouter()` instead. Will be removed in v3.
18591859
18601860
```typescript
18611861
QwikCityProvider: import("@qwik.dev/core").Component<QwikRouterProps>;
@@ -2116,6 +2116,8 @@ Default: `true`
21162116
21172117
## QwikRouterProvider
21182118
2119+
This is a wrapper around the `useQwikRouter()` hook. We recommend using the hook instead of this component.
2120+
21192121
```typescript
21202122
QwikRouterProvider: import("@qwik.dev/core").Component<QwikRouterProps>;
21212123
```
@@ -2651,6 +2653,49 @@ void
26512653
26522654
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/use-functions.ts)
26532655
2656+
## useQwikRouter
2657+
2658+
This hook initializes Qwik Router, providing the necessary context for it to work.
2659+
2660+
This hook should be used once, at the root of your application.
2661+
2662+
```typescript
2663+
useQwikRouter: (props?: QwikRouterProps) => void
2664+
```
2665+
2666+
<table><thead><tr><th>
2667+
2668+
Parameter
2669+
2670+
</th><th>
2671+
2672+
Type
2673+
2674+
</th><th>
2675+
2676+
Description
2677+
2678+
</th></tr></thead>
2679+
<tbody><tr><td>
2680+
2681+
props
2682+
2683+
</td><td>
2684+
2685+
[QwikRouterProps](#qwikrouterprops)
2686+
2687+
</td><td>
2688+
2689+
_(Optional)_
2690+
2691+
</td></tr>
2692+
</tbody></table>
2693+
**Returns:**
2694+
2695+
void
2696+
2697+
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/qwik-router-component.tsx)
2698+
26542699
## valibot$
26552700
26562701
> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.

0 commit comments

Comments
 (0)