Skip to content

Commit 537d95a

Browse files
committed
feat(insights): add route hints to bundlegraph, refactor
1 parent 1f5e4ea commit 537d95a

File tree

9 files changed

+89
-192
lines changed

9 files changed

+89
-192
lines changed

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

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -196,20 +196,6 @@
196196
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/types.ts",
197197
"mdFile": "qwik.inlineentrystrategy.md"
198198
},
199-
{
200-
"name": "InsightManifest",
201-
"id": "insightmanifest",
202-
"hierarchy": [
203-
{
204-
"name": "InsightManifest",
205-
"id": "insightmanifest"
206-
}
207-
],
208-
"kind": "Interface",
209-
"content": "```typescript\nexport interface InsightManifest \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\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\n[manual](#)\n\n\n</td><td>\n\n\n</td><td>\n\nRecord&lt;string, string&gt;\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[prefetch](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ route: string; symbols: string\\[\\]; }\\[\\]\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[type](#)\n\n\n</td><td>\n\n\n</td><td>\n\n'smart'\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>",
210-
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/types.ts",
211-
"mdFile": "qwik.insightmanifest.md"
212-
},
213199
{
214200
"name": "isAbsolute",
215201
"id": "path-isabsolute",
@@ -546,7 +532,7 @@
546532
}
547533
],
548534
"kind": "Interface",
549-
"content": "```typescript\nexport interface QwikVitePluginApi \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\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\n[getAssetsDir](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; string \\| undefined\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getClientOutDir](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; string \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getClientPublicOutDir](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; string \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getInsightsManifest](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(clientOutDir?: string \\| null) =&gt; Promise&lt;[InsightManifest](#insightmanifest) \\| null&gt;\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getManifest](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; [QwikManifest](#qwikmanifest) \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getOptimizer](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; [Optimizer](#optimizer) \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getOptions](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; NormalizedQwikPluginOptions\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getRootDir](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; string \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[registerBundleGraphAdder](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(adder: [BundleGraphAdder](#bundlegraphadder)<!-- -->) =&gt; void\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>",
535+
"content": "```typescript\nexport interface QwikVitePluginApi \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\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\n[getAssetsDir](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; string \\| undefined\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getClientOutDir](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; string \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getClientPublicOutDir](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; string \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getManifest](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; [QwikManifest](#qwikmanifest) \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getOptimizer](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; [Optimizer](#optimizer) \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getOptions](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; NormalizedQwikPluginOptions\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[getRootDir](#)\n\n\n</td><td>\n\n\n</td><td>\n\n() =&gt; string \\| null\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[registerBundleGraphAdder](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(adder: [BundleGraphAdder](#bundlegraphadder)<!-- -->) =&gt; void\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>",
550536
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/plugins/vite.ts",
551537
"mdFile": "qwik.qwikvitepluginapi.md"
552538
},

packages/docs/src/routes/api/qwik-optimizer/index.md

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -594,72 +594,6 @@ Description
594594

595595
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/types.ts)
596596

597-
## InsightManifest
598-
599-
```typescript
600-
export interface InsightManifest
601-
```
602-
603-
<table><thead><tr><th>
604-
605-
Property
606-
607-
</th><th>
608-
609-
Modifiers
610-
611-
</th><th>
612-
613-
Type
614-
615-
</th><th>
616-
617-
Description
618-
619-
</th></tr></thead>
620-
<tbody><tr><td>
621-
622-
[manual](#)
623-
624-
</td><td>
625-
626-
</td><td>
627-
628-
Record&lt;string, string&gt;
629-
630-
</td><td>
631-
632-
</td></tr>
633-
<tr><td>
634-
635-
[prefetch](#)
636-
637-
</td><td>
638-
639-
</td><td>
640-
641-
{ route: string; symbols: string[]; }[]
642-
643-
</td><td>
644-
645-
</td></tr>
646-
<tr><td>
647-
648-
[type](#)
649-
650-
</td><td>
651-
652-
</td><td>
653-
654-
'smart'
655-
656-
</td><td>
657-
658-
</td></tr>
659-
</tbody></table>
660-
661-
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/types.ts)
662-
663597
## isAbsolute
664598

665599
```typescript
@@ -2188,19 +2122,6 @@ Description
21882122
</td></tr>
21892123
<tr><td>
21902124

2191-
[getInsightsManifest](#)
2192-
2193-
</td><td>
2194-
2195-
</td><td>
2196-
2197-
(clientOutDir?: string \| null) =&gt; Promise&lt;[InsightManifest](#insightmanifest) \| null&gt;
2198-
2199-
</td><td>
2200-
2201-
</td></tr>
2202-
<tr><td>
2203-
22042125
[getManifest](#)
22052126

22062127
</td><td>

packages/qwik-city/src/buildtime/vite/plugin.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ function qwikCityPlugin(userOpts?: QwikCityVitePluginOptions): any {
9595
if (!qwikPlugin) {
9696
throw new Error('Missing vite-plugin-qwik');
9797
}
98+
qwikPlugin.api.registerBundleGraphAdder?.((manifest) => {
99+
return getRouteImports(ctx!.routes, manifest);
100+
});
98101

99102
// @ts-ignore `format` removed in Vite 5
100103
if (config.ssr?.format === 'cjs') {
@@ -236,10 +239,6 @@ function qwikCityPlugin(userOpts?: QwikCityVitePluginOptions): any {
236239
generateBundle(_, bundles) {
237240
// client bundles
238241
if (ctx?.target === 'client') {
239-
qwikPlugin!.api.registerBundleGraphAdder((manifest) => {
240-
return getRouteImports(ctx!.routes, manifest);
241-
});
242-
243242
const entries = [...ctx.entries, ...ctx.serviceWorkers].map((entry) => {
244243
return {
245244
chunkFileName: entry.chunkFileName,

packages/qwik-labs/src-vite/insights/index.ts

Lines changed: 85 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { type QwikVitePluginOptions } from '@builder.io/qwik/optimizer';
2-
import { existsSync, mkdirSync } from 'fs';
3-
import { readFile, writeFile } from 'fs/promises';
4-
import { join } from 'node:path';
5-
import { resolve } from 'path';
1+
import { type QwikVitePlugin } from '@builder.io/qwik/optimizer';
2+
import { existsSync, mkdirSync } from 'node:fs';
3+
import { readFile, writeFile } from 'node:fs/promises';
4+
import { join, resolve } from 'node:path';
65
import { type PluginOption } from 'vite';
76

87
const logWarn = (message?: any, ...rest) => {
@@ -15,35 +14,102 @@ const log = (message?: any) => {
1514
console.log('\x1b[35m%s\x1b[0m', `qwikInsight(): ${message}`);
1615
};
1716

17+
/** @public */
18+
export interface InsightManifest {
19+
manual: Record<string, string>;
20+
prefetch: { route: string; symbols: string[] }[];
21+
}
22+
1823
export async function qwikInsights(qwikInsightsOpts: {
1924
publicApiKey: string;
2025
baseUrl?: string;
2126
outDir?: string;
2227
}): Promise<PluginOption> {
2328
const { publicApiKey, baseUrl = 'https://insights.qwik.dev', outDir = '' } = qwikInsightsOpts;
2429
let isProd = false;
30+
let jsonDir: string;
31+
let jsonFile: string;
32+
let data: InsightManifest | null = null;
33+
let qwikVitePlugin: QwikVitePlugin | null = null;
34+
35+
async function loadQwikInsights(): Promise<InsightManifest | null> {
36+
if (data) {
37+
return data;
38+
}
39+
if (existsSync(jsonFile)) {
40+
log('Reading Qwik Insight data from: ' + jsonFile);
41+
return (data = JSON.parse(await readFile(jsonFile, 'utf-8')) as InsightManifest);
42+
}
43+
return null;
44+
}
45+
2546
const vitePlugin: PluginOption = {
2647
name: 'vite-plugin-qwik-insights',
2748
enforce: 'pre',
2849
apply: 'build',
2950
async config(viteConfig) {
51+
jsonDir = resolve(viteConfig.root || '.', outDir);
52+
jsonFile = join(jsonDir, 'q-insights.json');
3053
isProd = viteConfig.mode !== 'ssr';
31-
if (isProd) {
32-
const qManifest: QwikVitePluginOptions['entryStrategy'] = { type: 'smart' };
33-
try {
34-
const response = await fetch(`${baseUrl}/api/v1/${publicApiKey}/bundles/strategy/`);
35-
const strategy = await response.json();
36-
Object.assign(qManifest, strategy);
37-
const path = resolve(viteConfig.root || '.', outDir);
38-
const pathJson = join(path, 'q-insights.json');
39-
mkdirSync(path, { recursive: true });
40-
log('Fetched latest Qwik Insight data into: ' + pathJson);
41-
await writeFile(pathJson, JSON.stringify(qManifest));
42-
} catch (e) {
43-
logWarn('Failed to fetch manifest from Insights DB', e);
54+
},
55+
configResolved: {
56+
// we want to register the bundle graph adder last so we overwrite existing routes
57+
order: 'post',
58+
async handler(config) {
59+
qwikVitePlugin = config.plugins.find(
60+
(p) => p.name === 'vite-plugin-qwik'
61+
) as QwikVitePlugin;
62+
if (!qwikVitePlugin) {
63+
throw new Error('Missing vite-plugin-qwik');
4464
}
45-
}
65+
const opts = qwikVitePlugin.api.getOptions();
66+
if (opts.entryStrategy.type !== 'smart') {
67+
return;
68+
}
69+
if (isProd) {
70+
try {
71+
const qManifest: InsightManifest = { manual: {}, prefetch: [] };
72+
const response = await fetch(`${baseUrl}/api/v1/${publicApiKey}/bundles/strategy/`);
73+
const strategy = await response.json();
74+
Object.assign(qManifest, strategy);
75+
data = qManifest;
76+
mkdirSync(jsonDir, { recursive: true });
77+
log('Fetched latest Qwik Insight data into: ' + jsonFile);
78+
await writeFile(jsonFile, JSON.stringify(qManifest));
79+
} catch (e) {
80+
logWarn('Failed to fetch manifest from Insights DB', e);
81+
await loadQwikInsights();
82+
}
83+
} else {
84+
await loadQwikInsights();
85+
}
86+
87+
if (data) {
88+
opts.entryStrategy.manual = { ...data.manual, ...opts.entryStrategy.manual };
89+
90+
qwikVitePlugin.api.registerBundleGraphAdder(() => {
91+
const result: Record<
92+
string,
93+
{ imports?: string[] | undefined; dynamicImports?: string[] | undefined }
94+
> = {};
95+
for (const item of data?.prefetch || []) {
96+
if (item.symbols) {
97+
let route = item.route;
98+
if (route.startsWith('/')) {
99+
route = route.slice(1);
100+
}
101+
if (!route.endsWith('/')) {
102+
route += '/';
103+
}
104+
result[route] = { imports: item.symbols };
105+
}
106+
}
107+
return result;
108+
});
109+
}
110+
},
46111
},
112+
47113
closeBundle: async () => {
48114
const path = resolve(outDir, 'q-manifest.json');
49115
if (isProd && existsSync(path)) {

packages/qwik/src/optimizer/src/api.md

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -75,19 +75,6 @@ export interface InlineEntryStrategy {
7575
type: 'inline';
7676
}
7777

78-
// @public (undocumented)
79-
export interface InsightManifest {
80-
// (undocumented)
81-
manual: Record<string, string>;
82-
// (undocumented)
83-
prefetch: {
84-
route: string;
85-
symbols: string[];
86-
}[];
87-
// (undocumented)
88-
type: 'smart';
89-
}
90-
9178
// @public (undocumented)
9279
export type MinifyMode = 'simplify' | 'none';
9380

@@ -299,8 +286,6 @@ export interface QwikVitePluginApi {
299286
// (undocumented)
300287
getClientPublicOutDir: () => string | null;
301288
// (undocumented)
302-
getInsightsManifest: (clientOutDir?: string | null) => Promise<InsightManifest | null>;
303-
// (undocumented)
304289
getManifest: () => QwikManifest | null;
305290
// (undocumented)
306291
getOptimizer: () => Optimizer | null;

packages/qwik/src/optimizer/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export type {
1010
SegmentAnalysis as HookAnalysis,
1111
SegmentEntryStrategy as HookEntryStrategy,
1212
InlineEntryStrategy,
13-
InsightManifest,
1413
MinifyMode,
1514
Optimizer,
1615
OptimizerOptions,

packages/qwik/src/optimizer/src/plugins/plugin.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import type {
88
EntryStrategy,
99
GlobalInjections,
1010
SegmentAnalysis,
11-
InsightManifest,
1211
Optimizer,
1312
OptimizerOptions,
1413
OptimizerSystem,
@@ -111,7 +110,6 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
111110
srcInputs: null as any,
112111
sourcemap: !!optimizerOptions.sourcemap,
113112
manifestInput: null,
114-
insightsManifest: null,
115113
manifestOutput: null,
116114
transformedModuleOutput: null,
117115
scope: null,
@@ -1011,7 +1009,6 @@ export interface QwikPluginOptions {
10111009
vendorRoots?: string[];
10121010
manifestOutput?: ((manifest: QwikManifest) => Promise<void> | void) | null;
10131011
manifestInput?: QwikManifest | null;
1014-
insightsManifest?: InsightManifest | null;
10151012
input?: string[] | string | { [entry: string]: string };
10161013
outDir?: string;
10171014
assetsDir?: string;

0 commit comments

Comments
 (0)