diff --git a/.changeset/modern-emus-share.md b/.changeset/modern-emus-share.md new file mode 100644 index 00000000000..6f688456d58 --- /dev/null +++ b/.changeset/modern-emus-share.md @@ -0,0 +1,5 @@ +--- +'@qwik.dev/core': minor +--- + +FEAT: `getClientManifest()` is now the way to get the client build manifest. Importing from `@qwik-client-manifest` is deprecated. diff --git a/packages/docs/src/routes/api/qwik/api.json b/packages/docs/src/routes/api/qwik/api.json index f2b7f880af8..c44fae71cb1 100644 --- a/packages/docs/src/routes/api/qwik/api.json +++ b/packages/docs/src/routes/api/qwik/api.json @@ -731,6 +731,20 @@ "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/jsx/types/jsx-node.ts", "mdFile": "core.functioncomponent.md" }, + { + "name": "getClientManifest", + "id": "getclientmanifest", + "hierarchy": [ + { + "name": "getClientManifest", + "id": "getclientmanifest" + } + ], + "kind": "Function", + "content": "Returns the client build manifest, which includes the mappings from symbols to bundles, the bundlegraph etc.\n\n\n```typescript\ngetClientManifest: () => ServerQwikManifest\n```\n**Returns:**\n\nServerQwikManifest", + "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/get-client-manifest.ts", + "mdFile": "core.getclientmanifest.md" + }, { "name": "getDomContainer", "id": "getdomcontainer", diff --git a/packages/docs/src/routes/api/qwik/index.mdx b/packages/docs/src/routes/api/qwik/index.mdx index fb0fc8db94a..cc2206a599d 100644 --- a/packages/docs/src/routes/api/qwik/index.mdx +++ b/packages/docs/src/routes/api/qwik/index.mdx @@ -1684,6 +1684,20 @@ export type FunctionComponent
= { [Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/jsx/types/jsx-node.ts) +
= {
renderFn(props: P, key: string | null, flags: number, dev?: DevJSX): JSXOutput;
}['renderFn'];
+// @public
+export const getClientManifest: () => ServerQwikManifest;
+
// Warning: (ae-forgotten-export) The symbol "PropsProxy" needs to be exported by the entry point index.d.ts
//
// @internal
diff --git a/packages/qwik/src/core/shared/get-client-manifest.ts b/packages/qwik/src/core/shared/get-client-manifest.ts
new file mode 100644
index 00000000000..16d6f0c4448
--- /dev/null
+++ b/packages/qwik/src/core/shared/get-client-manifest.ts
@@ -0,0 +1,17 @@
+import type { ServerQwikManifest } from '@qwik.dev/core/optimizer';
+
+/**
+ * Returns the client build manifest, which includes the mappings from symbols to bundles, the
+ * bundlegraph etc.
+ *
+ * @public
+ */
+export const getClientManifest = (): ServerQwikManifest => {
+ const manifest = (globalThis as any).__QWIK_MANIFEST__ as ServerQwikManifest;
+ if (!(globalThis as any).__QWIK_MANIFEST__) {
+ throw new Error(
+ `Client manifest is not available. It should have been automatically injected during the build process. Make sure that @qwik.dev/core is internal to the build.`
+ );
+ }
+ return manifest;
+};
diff --git a/packages/qwik/src/optimizer/src/plugins/plugin.ts b/packages/qwik/src/optimizer/src/plugins/plugin.ts
index 3add4e61d96..66dbaa76ba3 100644
--- a/packages/qwik/src/optimizer/src/plugins/plugin.ts
+++ b/packages/qwik/src/optimizer/src/plugins/plugin.ts
@@ -22,6 +22,7 @@ import type {
import { convertManifestToBundleGraph } from './bundle-graph';
import { createLinter, type QwikLinter } from './eslint-plugin';
import { isVirtualId, isWin, parseId } from './vite-utils';
+import MagicString from 'magic-string';
const REG_CTX_NAME = ['server'];
@@ -539,6 +540,9 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
};
}
} else if (pathId.endsWith(QWIK_CLIENT_MANIFEST_ID)) {
+ console.error(
+ `${importerId}: importing ${QWIK_CLIENT_MANIFEST_ID} is deprecated. Use \`getClientManifest()\` instead.`
+ );
debug(`resolveId(${count})`, 'Resolved', QWIK_CLIENT_MANIFEST_ID);
result = {
id: QWIK_CLIENT_MANIFEST_ID,
@@ -662,7 +666,7 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
debug(`load(${count})`, QWIK_CLIENT_MANIFEST_ID, opts.buildMode);
return {
moduleSideEffects: false,
- code: await getQwikServerManifestModule(isServer),
+ code: `export const manifest = globalThis.${globalManifestKey}'};\n`,
};
}
/**
@@ -715,6 +719,7 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
return null;
};
+ let theManifest: string | null | undefined;
let transformCount = 0;
const transform = async function (
ctx: Rollup.PluginContext,
@@ -725,7 +730,6 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
if (isVirtualId(id)) {
return;
}
- const count = transformCount++;
const isServer = getIsServer(transformOpts);
const currentOutputs = isServer ? serverTransformedOutputs : clientTransformedOutputs;
if (currentOutputs.has(id)) {
@@ -733,6 +737,10 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
return;
}
+ let shouldReturn = false;
+
+ const count = transformCount++;
+
const optimizer = getOptimizer();
const path = getPath();
@@ -741,6 +749,8 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
const dir = parsedPathId.dir;
const base = parsedPathId.base;
const ext = parsedPathId.ext.toLowerCase();
+ let map;
+ let meta;
if (ext in TRANSFORM_EXTS || TRANSFORM_REGEX.test(pathId)) {
/** Strip client|server code from qwik server|client, but not in lib/test */
const strip = opts.target === 'client' || opts.target === 'ssr';
@@ -846,19 +856,35 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
ctx.addWatchFile(id);
- return {
- code: module.code,
- map: module.map,
- meta: {
- segment: module.segment,
- qwikdeps: Array.from(deps),
- },
+ code = module.code;
+ map = module.map;
+ meta = {
+ segment: module.segment,
+ qwikdeps: Array.from(deps),
};
+ shouldReturn = true;
}
- debug(`transform(${count})`, 'Not transforming', id);
+ if (code.includes(`globalThis.${globalManifestKey}`)) {
+ if (theManifest === undefined) {
+ theManifest = await getQwikServerManifest(getIsServer(transformOpts));
+ }
+ const s = new MagicString(code);
+ // Always replace the check
+ s.replace(`!globalThis.${globalManifestKey}`, 'false');
+ if (theManifest) {
+ s.replace(`globalThis.${globalManifestKey}`, theManifest);
+ }
+ code = s.toString();
+ map ||= s.generateMap({ source: id, includeContent: false });
+ shouldReturn = true;
+ debug(`transform(${count})`, `Replaced globalThis.${globalManifestKey} with manifest input`);
+ }
- return null;
+ if (shouldReturn) {
+ return { code, map, meta };
+ }
+ debug(`transform(${count})`, 'Not transforming', id);
};
type OutputAnalyzer = {
@@ -957,7 +983,7 @@ export const isDev = ${JSON.stringify(isDev)};
`;
}
- async function getQwikServerManifestModule(isServer: boolean) {
+ async function getQwikServerManifest(isServer: boolean) {
if (
!opts.manifestInput &&
opts.target === 'ssr' &&
@@ -1001,8 +1027,7 @@ export const isDev = ${JSON.stringify(isDev)};
bundleGraph: manifest.bundleGraph,
};
}
- return `// @qwik-client-manifest
-export const manifest = ${serverManifest ? JSON.stringify(serverManifest) : 'globalThis.__QWIK_MANIFEST__'};\n`;
+ return serverManifest && JSON.stringify(serverManifest);
}
function setSourceMapSupport(sourcemap: boolean) {
@@ -1207,10 +1232,11 @@ export const QWIK_JSX_DEV_RUNTIME_ID = '@qwik.dev/core/jsx-dev-runtime';
export const QWIK_CORE_SERVER = '@qwik.dev/core/server';
+/** Internal use only - use `getClientManifest()` instead */
export const QWIK_CLIENT_MANIFEST_ID = '@qwik-client-manifest';
export const QWIK_PRELOADER_ID = '@qwik.dev/core/preloader';
-
+/** @internal virtual import to ensure the _run etc handlers are exported as-is */
export const QWIK_HANDLERS_ID = '@qwik-handlers';
export const SRC_DIR_DEFAULT = 'src';
@@ -1289,3 +1315,5 @@ export type QwikBuildTarget = 'client' | 'ssr' | 'lib' | 'test';
/** @public */
export type QwikBuildMode = 'production' | 'development';
+
+const globalManifestKey = '__QWIK_MANIFEST__';
diff --git a/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts b/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts
index 1f54cf23d11..2d372435c74 100644
--- a/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts
+++ b/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts
@@ -296,7 +296,7 @@ describe('resolveId', () => {
'id',
'@qwik.dev/core/build'
);
- expect(await plugin.resolveId(null!, '@qwik-client-manifest', '/foo/bar')).toHaveProperty(
+ expect(await plugin.resolveId(null!, '@qwik-client-manifest', '/foo/bar/core')).toHaveProperty(
'id',
'@qwik-client-manifest'
);
diff --git a/packages/qwik/src/server/server-modules.d.ts b/packages/qwik/src/server/server-modules.d.ts
index 081815adccc..4a8b961ccad 100644
--- a/packages/qwik/src/server/server-modules.d.ts
+++ b/packages/qwik/src/server/server-modules.d.ts
@@ -1,4 +1,5 @@
declare module '@qwik-client-manifest' {
+ /** @deprecated Use `getClientManifest()` instead */
const manifest: import('.').ServerQwikManifest;
export { manifest };
}
diff --git a/packages/qwik/src/server/ssr-render.ts b/packages/qwik/src/server/ssr-render.ts
index d00398b0e6e..ed7c47ded21 100644
--- a/packages/qwik/src/server/ssr-render.ts
+++ b/packages/qwik/src/server/ssr-render.ts
@@ -1,5 +1,8 @@
+import { getClientManifest } from '@qwik.dev/core';
import { getSymbolHash, setServerPlatform } from './platform';
-import type { JSXOutput, ResolvedManifest, SymbolMapper, StreamWriter } from './qwik-types';
+import type { JSXOutput, ResolvedManifest, StreamWriter, SymbolMapper } from './qwik-types';
+import { ssrCreateContainer } from './ssr-container';
+import { StreamHandler } from './ssr-stream-handler';
import type {
QwikManifest,
RenderToStreamOptions,
@@ -8,9 +11,6 @@ import type {
RenderToStringResult,
} from './types';
import { getBuildBase } from './utils';
-import { ssrCreateContainer } from './ssr-container';
-import { manifest as builtManifest } from '@qwik-client-manifest';
-import { StreamHandler } from './ssr-stream-handler';
/**
* Creates a server-side `document`, renders to root node to the document, then serializes the
@@ -102,6 +102,7 @@ export const renderToStream = async (
export function resolveManifest(
manifest?: Partial