Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions packages/docs/src/entry.ssr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import { Root } from './root';
export function render(opts: RenderToStringOptions) {
return renderToString(<Root />, {
manifest,
qwikLoader: {
include: 'body',
},
...opts,
});
}
2 changes: 1 addition & 1 deletion packages/qwik/src/server/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export interface RenderToStringOptions extends SerializeDocumentOptions {
prefetchStrategy?: PrefetchStrategy | null;
qwikLoader?: {
events?: string[];
include?: boolean | 'body' | 'head';
include?: boolean | 'top' | 'bottom';
};
snapshot?: boolean;
}
Expand Down
21 changes: 14 additions & 7 deletions packages/qwik/src/server/prefetch-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {

export function applyPrefetchImplementation(
doc: QwikDocument,
parentElm: Element,
opts: RenderToStringOptions,
prefetchResources: PrefetchResource[]
) {
Expand All @@ -19,21 +20,22 @@ export function applyPrefetchImplementation(
prefetchImpl === 'link-preload-html' ||
prefetchImpl === 'link-modulepreload-html'
) {
linkHtmlImplementation(doc, prefetchResources, prefetchImpl);
linkHtmlImplementation(doc, parentElm, prefetchResources, prefetchImpl);
} else if (
prefetchImpl === 'link-prefetch' ||
prefetchImpl === 'link-preload' ||
prefetchImpl === 'link-modulepreload'
) {
linkJsImplementation(doc, prefetchResources, prefetchImpl);
linkJsImplementation(doc, parentElm, prefetchResources, prefetchImpl);
} else if (prefetchImpl === 'worker-fetch') {
workerFetchImplementation(doc, prefetchResources);
workerFetchImplementation(doc, parentElm, prefetchResources);
}
}
}

function linkHtmlImplementation(
doc: QwikDocument,
parentElm: Element,
prefetchResources: PrefetchResource[],
prefetchImpl: PrefetchImplementation
) {
Expand All @@ -57,12 +59,13 @@ function linkHtmlImplementation(
}
}

doc.body.appendChild(linkElm);
parentElm.appendChild(linkElm);
}
}

function linkJsImplementation(
doc: QwikDocument,
parentElm: Element,
prefetchResources: PrefetchResource[],
prefetchImpl: PrefetchImplementation
) {
Expand Down Expand Up @@ -103,7 +106,7 @@ function linkJsImplementation(
const script = doc.createElement('script');
script.setAttribute('type', 'module');
script.innerHTML = s;
doc.body.appendChild(script);
parentElm.appendChild(script);
}

function workerFetchScript() {
Expand All @@ -122,14 +125,18 @@ function workerFetchScript() {
return s;
}

function workerFetchImplementation(doc: QwikDocument, prefetchResources: PrefetchResource[]) {
function workerFetchImplementation(
doc: QwikDocument,
parentElm: Element,
prefetchResources: PrefetchResource[]
) {
let s = `const u=${JSON.stringify(flattenPrefetchResources(prefetchResources))};`;
s += workerFetchScript();

const script = doc.createElement('script');
script.setAttribute('type', 'module');
script.innerHTML = s;
doc.body.appendChild(script);
parentElm.appendChild(script);
}

export function flattenPrefetchResources(prefetchResources: PrefetchResource[]) {
Expand Down
37 changes: 21 additions & 16 deletions packages/qwik/src/server/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getPrefetchResources } from './prefetch-strategy';
import { _createDocument } from './document';
import type { SymbolMapper } from '../optimizer/src/types';
import { getCanonicalSymbol } from '../core/import/qrl-class';
import { isDocument } from '../core/util/element';

/**
* Creates a server-side `document`, renders to root node to the document,
Expand All @@ -19,43 +20,45 @@ import { getCanonicalSymbol } from '../core/import/qrl-class';
*/
export async function renderToString(rootNode: any, opts: RenderToStringOptions = {}) {
const createDocTimer = createTimer();
const doc = _createDocument(opts);
const doc = _createDocument(opts) as Document;
const createDocTime = createDocTimer();

const renderDocTimer = createTimer();
let rootEl: Element | Document = doc;
let root: Element | Document = doc;
if (typeof opts.fragmentTagName === 'string') {
if (opts.qwikLoader) {
opts.qwikLoader.include = false;
if (opts.qwikLoader.include === undefined) {
opts.qwikLoader.include = false;
}
} else {
opts.qwikLoader = { include: false };
}

rootEl = doc.createElement(opts.fragmentTagName);
doc.body.appendChild(rootEl);
root = doc.createElement(opts.fragmentTagName);
doc.body.appendChild(root);
}
const isFullDocument = isDocument(root);
const mapper = computeSymbolMapper(opts.manifest);

await setServerPlatform(doc, opts, mapper);

await render(doc, rootNode);
await render(root, rootNode);
const renderDocTime = renderDocTimer();

const buildBase = getBuildBase(opts);
const containerEl = getElement(doc);
const containerEl = getElement(root);
containerEl.setAttribute('q:base', buildBase);

let snapshotResult: SnapshotResult | null = null;
if (opts.snapshot !== false) {
snapshotResult = pauseContainer(doc);
snapshotResult = pauseContainer(root);
}
const prefetchResources = getPrefetchResources(snapshotResult, opts, mapper);
const parentElm = isFullDocument ? doc.body : containerEl;
if (prefetchResources.length > 0) {
applyPrefetchImplementation(doc, opts, prefetchResources);
applyPrefetchImplementation(doc, parentElm, opts, prefetchResources);
}

const includeLoader =
!opts.qwikLoader || opts.qwikLoader.include === undefined ? 'head' : opts.qwikLoader.include;
!opts.qwikLoader || opts.qwikLoader.include === undefined ? 'bottom' : opts.qwikLoader.include;
if (includeLoader) {
const qwikLoaderScript = getQwikLoaderScript({
events: opts.qwikLoader?.events,
Expand All @@ -64,10 +67,12 @@ export async function renderToString(rootNode: any, opts: RenderToStringOptions
const scriptElm = doc.createElement('script') as HTMLScriptElement;
scriptElm.setAttribute('id', 'qwikloader');
scriptElm.textContent = qwikLoaderScript;
if (includeLoader === 'body') {
doc.body.appendChild(scriptElm);
} else {
if (includeLoader === 'bottom') {
parentElm.appendChild(scriptElm);
} else if (isFullDocument) {
doc.head.appendChild(scriptElm);
} else {
parentElm.insertBefore(scriptElm, parentElm.firstChild);
}
}

Expand All @@ -76,7 +81,7 @@ export async function renderToString(rootNode: any, opts: RenderToStringOptions
const result: RenderToStringResult = {
prefetchResources,
snapshotResult,
html: serializeDocument(rootEl, opts),
html: serializeDocument(root, opts),
timing: {
createDocument: createDocTime,
render: renderDocTime,
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export interface RenderToStringOptions extends SerializeDocumentOptions {
/**
* Specifies if the Qwik Loader script is added to the document or not. Defaults to `{ include: true }`.
*/
qwikLoader?: { events?: string[]; include?: boolean | 'body' | 'head' };
qwikLoader?: { events?: string[]; include?: boolean | 'top' | 'bottom' };

prefetchStrategy?: PrefetchStrategy | null;
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/testing/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export interface RenderToStringOptions extends SerializeDocumentOptions {
prefetchStrategy?: PrefetchStrategy | null;
qwikLoader?: {
events?: string[];
include?: boolean | 'body' | 'head';
include?: boolean | 'top' | 'bottom';
};
snapshot?: boolean;
}
Expand Down
9 changes: 4 additions & 5 deletions starters/apps/e2e/src/components/containers/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const Containers = component$(() => {
);
});

export const Container = component$((props: ContainerProps) => {
export const Container = component$(async (props: ContainerProps) => {
useScopedStyles$(`
.container {
margin: 20px;
Expand All @@ -36,10 +36,9 @@ export const Container = component$((props: ContainerProps) => {
}
`);
const url = `http://localhost:3300${props.url}?fragment&loader=false`;
// const { default: fetch } = await import('node-fetch');
// const res = await fetch(url);
// const html = await res.text();
const html = '';
const { default: fetch } = await import('node-fetch');
const res = await fetch(url);
const html = await res.text();
return (
<Host class="container">
<div class="url">{url}</div>
Expand Down
2 changes: 1 addition & 1 deletion starters/apps/e2e/src/entry.ssr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function render(opts: RenderToStringOptions) {
</>,
{
debug: true,
fragmentTagName: 'div',
fragmentTagName: 'container',
qwikLoader: {
include: url.searchParams.get('loader') !== 'false',
events: ['click'],
Expand Down