@@ -3090,32 +3090,28 @@ export type SourceMapsOption = "external" | "inline" | undefined | null;
## symbolMapper
-> 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.
+> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
-For a given symbol (QRL such as `onKeydown$`) the server needs to know which bundle the symbol is in.
-
-Normally this is provided by Qwik's `q-manifest` . But `q-manifest` only exists after a full client build.
-
-This would be a problem in dev mode. So in dev mode the symbol is mapped to the expected URL using the symbolMapper function below. For Vite the given path is fixed for a given symbol.
+> Warning: This API is now obsolete.
+>
+> No longer needed, it is automatic now
```typescript
-symbolMapper: ReturnType;
+symbolMapper: undefined;
```
-[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/plugins/vite-dev-server.ts)
+[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/index.ts)
## SymbolMapper
-> 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.
-
-For a given symbol (QRL such as `onKeydown$`) the server needs to know which bundle the symbol is in.
-
-Normally this is provided by Qwik's `q-manifest` . But `q-manifest` only exists after a full client build.
+> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
-This would be a problem in dev mode. So in dev mode the symbol is mapped to the expected URL using the symbolMapper function below. For Vite the given path is fixed for a given symbol.
+> Warning: This API is now obsolete.
+>
+> No longer needed, it is automatic now
```typescript
-symbolMapper: ReturnType;
+symbolMapper: undefined;
```
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/types.ts)
diff --git a/packages/docs/src/routes/api/qwik-router-ssg/api.json b/packages/docs/src/routes/api/qwik-router-ssg/api.json
new file mode 100644
index 00000000000..9baf9834d6a
--- /dev/null
+++ b/packages/docs/src/routes/api/qwik-router-ssg/api.json
@@ -0,0 +1,62 @@
+{
+ "id": "qwik-router-ssg",
+ "package": "@qwik.dev/qwik-router/ssg",
+ "members": [
+ {
+ "name": "generate",
+ "id": "generate",
+ "hierarchy": [
+ {
+ "name": "generate",
+ "id": "generate"
+ }
+ ],
+ "kind": "Function",
+ "content": "Use this function when SSG should be generated from another module, such as a Vite plugin. This function's should be passed the paths of the entry module and Qwik Router Plan.\n\n\n```typescript\nexport declare function generate(opts: SsgOptions): Promise;\n```\n\n\n\n\nParameter\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\nopts\n\n\n | \n\n[SsgOptions](#staticgenerateoptions)\n\n\n | \n\n\n | \n \n**Returns:**\n\nPromise<[SsgResult](#staticgenerateresult)>",
+ "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/ssg/index.ts",
+ "mdFile": "router.generate.md"
+ },
+ {
+ "name": "SsgRenderOptions",
+ "id": "ssgrenderoptions",
+ "hierarchy": [
+ {
+ "name": "SsgRenderOptions",
+ "id": "ssgrenderoptions"
+ }
+ ],
+ "kind": "Interface",
+ "content": "```typescript\nexport interface SsgRenderOptions extends RenderOptions \n```\n**Extends:** RenderOptions\n\n\n\n\nProperty\n\n\n | \n\nModifiers\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\n[emit404Pages?](./router.ssgrenderoptions.emit404pages.md)\n\n\n | \n\n\n | \n\nboolean\n\n\n | \n\n_(Optional)_ Set to `false` if the static build should not write custom or default `404.html` pages. Defaults to `true`.\n\n\n | \n\n\n[emitData?](./router.ssgrenderoptions.emitdata.md)\n\n\n | \n\n\n | \n\nboolean\n\n\n | \n\n_(Optional)_ Set to `false` if the generated `q-data.json` data files should not be written to disk. Defaults to `true`.\n\n\n | \n\n\n[emitHtml?](./router.ssgrenderoptions.emithtml.md)\n\n\n | \n\n\n | \n\nboolean\n\n\n | \n\n_(Optional)_ Set to `false` if the generated static HTML files should not be written to disk. Setting to `false` is useful if the SSG should only write the `q-data.json` files to disk. Defaults to `true`.\n\n\n | \n\n\n[exclude?](./router.ssgrenderoptions.exclude.md)\n\n\n | \n\n\n | \n\nstring\\[\\]\n\n\n | \n\n_(Optional)_ Defines file system routes relative to the source `routes` directory that should not be static generated. Accepts wildcard behavior. This should not include the \"base\" pathname. `exclude` always takes priority over `include`.\n\n\n | \n\n\n[include?](./router.ssgrenderoptions.include.md)\n\n\n | \n\n\n | \n\nstring\\[\\]\n\n\n | \n\n_(Optional)_ Defines file system routes relative to the source `routes` directory that should be static generated. Accepts wildcard behavior. This should not include the \"base\" pathname. If not provided, all routes will be static generated. `exclude` always takes priority over `include`.\n\n\n | \n\n\n[log?](./router.ssgrenderoptions.log.md)\n\n\n | \n\n\n | \n\n'debug'\n\n\n | \n\n_(Optional)_ Log level.\n\n\n | \n\n\n[maxTasksPerWorker?](./router.ssgrenderoptions.maxtasksperworker.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n_(Optional)_ Maximum number of tasks to be running at one time per worker. Defaults to `20`.\n\n\n | \n\n\n[maxWorkers?](./router.ssgrenderoptions.maxworkers.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n_(Optional)_ Maximum number of workers to use while generating the static pages. Defaults to the number of CPUs available.\n\n\n | \n\n\n[origin](./router.ssgrenderoptions.origin.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\nThe URL `origin`, which is a combination of the scheme (protocol) and hostname (domain). For example, `https://qwik.dev` has the protocol `https://` and domain `qwik.dev`. However, the `origin` does not include a `pathname`.\n\nThe `origin` is used to provide a full URL during Static Site Generation (SSG), and to simulate a complete URL rather than just the `pathname`. For example, in order to render a correct canonical tag URL or URLs within the `sitemap.xml`, the `origin` must be provided too.\n\nIf the site also starts with a pathname other than `/`, please use the `basePathname` option in the Qwik Router config options.\n\n\n | \n\n\n[outDir](./router.ssgrenderoptions.outdir.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\nFile system directory where the static files should be written.\n\n\n | \n\n\n[sitemapOutFile?](./router.ssgrenderoptions.sitemapoutfile.md)\n\n\n | \n\n\n | \n\nstring \\| null\n\n\n | \n\n_(Optional)_ File system path to write the `sitemap.xml` to. Defaults to `sitemap.xml` and written to the root of the `outDir`. Setting to `null` will prevent the sitemap from being created.\n\n\n | \n ",
+ "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/ssg/types.ts",
+ "mdFile": "router.ssgrenderoptions.md"
+ },
+ {
+ "name": "StaticGenerateOptions",
+ "id": "staticgenerateoptions",
+ "hierarchy": [
+ {
+ "name": "StaticGenerateOptions",
+ "id": "staticgenerateoptions"
+ }
+ ],
+ "kind": "Interface",
+ "content": "```typescript\nexport interface SsgOptions extends SsgRenderOptions \n```\n**Extends:** [SsgRenderOptions](#ssgrenderoptions)\n\n\n\n\nProperty\n\n\n | \n\nModifiers\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\n[basePathname?](./router.staticgenerateoptions.basepathname.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\n_(Optional)_ Defaults to `/`\n\n\n | \n\n\n[qwikCityPlanModulePath?](./router.staticgenerateoptions.qwikcityplanmodulepath.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\n_(Optional)_\n\n\n | \n\n\n[qwikRouterConfigModulePath](./router.staticgenerateoptions.qwikrouterconfigmodulepath.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\nPath to the Qwik Router Config module exporting the default `@qwik-router-config`.\n\n\n | \n\n\n[renderModulePath](./router.staticgenerateoptions.rendermodulepath.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\nPath to the SSR module exporting the default render function. In most cases it'll be `./src/entry.ssr.tsx`.\n\n\n | \n\n\n[rootDir?](./router.staticgenerateoptions.rootdir.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\n_(Optional)_\n\n\n | \n ",
+ "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/ssg/types.ts",
+ "mdFile": "router.staticgenerateoptions.md"
+ },
+ {
+ "name": "StaticGenerateResult",
+ "id": "staticgenerateresult",
+ "hierarchy": [
+ {
+ "name": "StaticGenerateResult",
+ "id": "staticgenerateresult"
+ }
+ ],
+ "kind": "Interface",
+ "content": "```typescript\nexport interface SsgResult \n```\n\n\n\n\nProperty\n\n\n | \n\nModifiers\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\n[duration](./router.staticgenerateresult.duration.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n\n | \n\n\n[errors](./router.staticgenerateresult.errors.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n\n | \n\n\n[rendered](./router.staticgenerateresult.rendered.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n\n | \n\n\n[staticPaths](./router.staticgenerateresult.staticpaths.md)\n\n\n | \n\n\n | \n\nstring\\[\\]\n\n\n | \n\n\n | \n ",
+ "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/ssg/types.ts",
+ "mdFile": "router.staticgenerateresult.md"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/docs/src/routes/api/qwik-router-static/index.mdx b/packages/docs/src/routes/api/qwik-router-ssg/index.mdx
similarity index 78%
rename from packages/docs/src/routes/api/qwik-router-static/index.mdx
rename to packages/docs/src/routes/api/qwik-router-ssg/index.mdx
index a6b743667ea..646e005aa65 100644
--- a/packages/docs/src/routes/api/qwik-router-static/index.mdx
+++ b/packages/docs/src/routes/api/qwik-router-ssg/index.mdx
@@ -1,17 +1,15 @@
---
-title: \@qwik.dev/qwik-router/static API Reference
+title: \@qwik.dev/qwik-router/ssg API Reference
---
-# [API](/api) › @qwik.dev/qwik-router/static
+# [API](/api) › @qwik.dev/qwik-router/ssg
## generate
Use this function when SSG should be generated from another module, such as a Vite plugin. This function's should be passed the paths of the entry module and Qwik Router Plan.
```typescript
-export declare function generate(
- opts: StaticGenerateOptions,
-): Promise;
+export declare function generate(opts: SsgOptions): Promise;
```
@@ -33,7 +31,7 @@ opts
|
-[StaticGenerateOptions](#staticgenerateoptions)
+[SsgOptions](#staticgenerateoptions)
|
@@ -41,17 +39,17 @@ opts
|
---|
**Returns:**
-Promise<[StaticGenerateResult](#staticgenerateresult)>
+Promise<[SsgResult](#staticgenerateresult)>
-[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/static/index.ts)
+[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/ssg/index.ts)
-## StaticGenerateOptions
+## SsgRenderOptions
```typescript
-export interface StaticGenerateOptions extends StaticGenerateRenderOptions
+export interface SsgRenderOptions extends RenderOptions
```
-**Extends:** [StaticGenerateRenderOptions](#staticgeneraterenderoptions)
+**Extends:** RenderOptions
@@ -72,231 +70,235 @@ Description
|
-[basePathname?](./router.staticgenerateoptions.basepathname.md)
+[emit404Pages?](./router.ssgrenderoptions.emit404pages.md)
|
|
-string
+boolean
|
-_(Optional)_ Defaults to `/`
+_(Optional)_ Set to `false` if the static build should not write custom or default `404.html` pages. Defaults to `true`.
|
-[qwikCityPlanModulePath?](./router.staticgenerateoptions.qwikcityplanmodulepath.md)
+[emitData?](./router.ssgrenderoptions.emitdata.md)
|
|
-string
+boolean
|
-_(Optional)_
+_(Optional)_ Set to `false` if the generated `q-data.json` data files should not be written to disk. Defaults to `true`.
|
-[qwikRouterConfigModulePath](./router.staticgenerateoptions.qwikrouterconfigmodulepath.md)
+[emitHtml?](./router.ssgrenderoptions.emithtml.md)
|
|
-string
+boolean
|
-Path to the Qwik Router Config module exporting the default `@qwik-router-config`.
+_(Optional)_ Set to `false` if the generated static HTML files should not be written to disk. Setting to `false` is useful if the SSG should only write the `q-data.json` files to disk. Defaults to `true`.
|
-[renderModulePath](./router.staticgenerateoptions.rendermodulepath.md)
+[exclude?](./router.ssgrenderoptions.exclude.md)
|
|
-string
+string[]
|
-Path to the SSR module exporting the default render function. In most cases it'll be `./src/entry.ssr.tsx`.
+_(Optional)_ Defines file system routes relative to the source `routes` directory that should not be static generated. Accepts wildcard behavior. This should not include the "base" pathname. `exclude` always takes priority over `include`.
|
-[rootDir?](./router.staticgenerateoptions.rootdir.md)
+[include?](./router.ssgrenderoptions.include.md)
|
|
-string
+string[]
|
-_(Optional)_
+_(Optional)_ Defines file system routes relative to the source `routes` directory that should be static generated. Accepts wildcard behavior. This should not include the "base" pathname. If not provided, all routes will be static generated. `exclude` always takes priority over `include`.
|
-
-
-[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/static/types.ts)
-
-## StaticGenerateRenderOptions
-
-```typescript
-export interface StaticGenerateRenderOptions extends RenderOptions
-```
-
-**Extends:** RenderOptions
-
-
-
-Property
+ |
---|
- |
+[log?](./router.ssgrenderoptions.log.md)
-Modifiers
+ |
- |
+ |
-Type
+'debug'
- |
+ |
-Description
+_(Optional)_ Log level.
- |
-
+ |
+
-[emit404Pages?](./router.staticgeneraterenderoptions.emit404pages.md)
+[maxTasksPerWorker?](./router.ssgrenderoptions.maxtasksperworker.md)
|
|
-boolean
+number
|
-_(Optional)_ Set to `false` if the static build should not write custom or default `404.html` pages. Defaults to `true`.
+_(Optional)_ Maximum number of tasks to be running at one time per worker. Defaults to `20`.
|
-[emitData?](./router.staticgeneraterenderoptions.emitdata.md)
+[maxWorkers?](./router.ssgrenderoptions.maxworkers.md)
|
|
-boolean
+number
|
-_(Optional)_ Set to `false` if the generated `q-data.json` data files should not be written to disk. Defaults to `true`.
+_(Optional)_ Maximum number of workers to use while generating the static pages. Defaults to the number of CPUs available.
|
-[emitHtml?](./router.staticgeneraterenderoptions.emithtml.md)
+[origin](./router.ssgrenderoptions.origin.md)
|
|
-boolean
+string
|
-_(Optional)_ Set to `false` if the generated static HTML files should not be written to disk. Setting to `false` is useful if the SSG should only write the `q-data.json` files to disk. Defaults to `true`.
+The URL `origin`, which is a combination of the scheme (protocol) and hostname (domain). For example, `https://qwik.dev` has the protocol `https://` and domain `qwik.dev`. However, the `origin` does not include a `pathname`.
+
+The `origin` is used to provide a full URL during Static Site Generation (SSG), and to simulate a complete URL rather than just the `pathname`. For example, in order to render a correct canonical tag URL or URLs within the `sitemap.xml`, the `origin` must be provided too.
+
+If the site also starts with a pathname other than `/`, please use the `basePathname` option in the Qwik Router config options.
|
-[exclude?](./router.staticgeneraterenderoptions.exclude.md)
+[outDir](./router.ssgrenderoptions.outdir.md)
|
|
-string[]
+string
|
-_(Optional)_ Defines file system routes relative to the source `routes` directory that should not be static generated. Accepts wildcard behavior. This should not include the "base" pathname. `exclude` always takes priority over `include`.
+File system directory where the static files should be written.
|
-[include?](./router.staticgeneraterenderoptions.include.md)
+[sitemapOutFile?](./router.ssgrenderoptions.sitemapoutfile.md)
|
|
-string[]
+string \| null
|
-_(Optional)_ Defines file system routes relative to the source `routes` directory that should be static generated. Accepts wildcard behavior. This should not include the "base" pathname. If not provided, all routes will be static generated. `exclude` always takes priority over `include`.
+_(Optional)_ File system path to write the `sitemap.xml` to. Defaults to `sitemap.xml` and written to the root of the `outDir`. Setting to `null` will prevent the sitemap from being created.
|
-
+ |
-[log?](./router.staticgeneraterenderoptions.log.md)
+[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/ssg/types.ts)
- |
+## StaticGenerateOptions
- |
+```typescript
+export interface SsgOptions extends SsgRenderOptions
+```
-'debug'
+**Extends:** [SsgRenderOptions](#ssgrenderoptions)
- |
+
-_(Optional)_ Log level.
+Property
- |
-
+ |
+
+Modifiers
+
+ |
+
+Type
+
+ |
+
+Description
-[maxTasksPerWorker?](./router.staticgeneraterenderoptions.maxtasksperworker.md)
+ |
+
+
+[basePathname?](./router.staticgenerateoptions.basepathname.md)
|
|
-number
+string
|
-_(Optional)_ Maximum number of tasks to be running at one time per worker. Defaults to `20`.
+_(Optional)_ Defaults to `/`
|
-[maxWorkers?](./router.staticgeneraterenderoptions.maxworkers.md)
+[qwikCityPlanModulePath?](./router.staticgenerateoptions.qwikcityplanmodulepath.md)
|
|
-number
+string
|
-_(Optional)_ Maximum number of workers to use while generating the static pages. Defaults to the number of CPUs available.
+_(Optional)_
|
-[origin](./router.staticgeneraterenderoptions.origin.md)
+[qwikRouterConfigModulePath](./router.staticgenerateoptions.qwikrouterconfigmodulepath.md)
|
@@ -306,16 +308,12 @@ string
|
-The URL `origin`, which is a combination of the scheme (protocol) and hostname (domain). For example, `https://qwik.dev` has the protocol `https://` and domain `qwik.dev`. However, the `origin` does not include a `pathname`.
-
-The `origin` is used to provide a full URL during Static Site Generation (SSG), and to simulate a complete URL rather than just the `pathname`. For example, in order to render a correct canonical tag URL or URLs within the `sitemap.xml`, the `origin` must be provided too.
-
-If the site also starts with a pathname other than `/`, please use the `basePathname` option in the Qwik Router config options.
+Path to the Qwik Router Config module exporting the default `@qwik-router-config`.
|
-[outDir](./router.staticgeneraterenderoptions.outdir.md)
+[renderModulePath](./router.staticgenerateoptions.rendermodulepath.md)
|
@@ -325,32 +323,32 @@ string
|
-File system directory where the static files should be written.
+Path to the SSR module exporting the default render function. In most cases it'll be `./src/entry.ssr.tsx`.
|
-[sitemapOutFile?](./router.staticgeneraterenderoptions.sitemapoutfile.md)
+[rootDir?](./router.staticgenerateoptions.rootdir.md)
|
|
-string \| null
+string
|
-_(Optional)_ File system path to write the `sitemap.xml` to. Defaults to `sitemap.xml` and written to the root of the `outDir`. Setting to `null` will prevent the sitemap from being created.
+_(Optional)_
|
-[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/static/types.ts)
+[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/ssg/types.ts)
## StaticGenerateResult
```typescript
-export interface StaticGenerateResult
+export interface SsgResult
```
@@ -424,4 +422,4 @@ string[]
|
-[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/static/types.ts)
+[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/ssg/types.ts)
diff --git a/packages/docs/src/routes/api/qwik-router-static/api.json b/packages/docs/src/routes/api/qwik-router-static/api.json
deleted file mode 100644
index d337e378ae1..00000000000
--- a/packages/docs/src/routes/api/qwik-router-static/api.json
+++ /dev/null
@@ -1,62 +0,0 @@
-{
- "id": "qwik-router-static",
- "package": "@qwik.dev/qwik-router/static",
- "members": [
- {
- "name": "generate",
- "id": "generate",
- "hierarchy": [
- {
- "name": "generate",
- "id": "generate"
- }
- ],
- "kind": "Function",
- "content": "Use this function when SSG should be generated from another module, such as a Vite plugin. This function's should be passed the paths of the entry module and Qwik Router Plan.\n\n\n```typescript\nexport declare function generate(opts: StaticGenerateOptions): Promise;\n```\n\n\n\n\nParameter\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\nopts\n\n\n | \n\n[StaticGenerateOptions](#staticgenerateoptions)\n\n\n | \n\n\n | \n \n**Returns:**\n\nPromise<[StaticGenerateResult](#staticgenerateresult)>",
- "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/static/index.ts",
- "mdFile": "router.generate.md"
- },
- {
- "name": "StaticGenerateOptions",
- "id": "staticgenerateoptions",
- "hierarchy": [
- {
- "name": "StaticGenerateOptions",
- "id": "staticgenerateoptions"
- }
- ],
- "kind": "Interface",
- "content": "```typescript\nexport interface StaticGenerateOptions extends StaticGenerateRenderOptions \n```\n**Extends:** [StaticGenerateRenderOptions](#staticgeneraterenderoptions)\n\n\n\n\nProperty\n\n\n | \n\nModifiers\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\n[basePathname?](./router.staticgenerateoptions.basepathname.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\n_(Optional)_ Defaults to `/`\n\n\n | \n\n\n[qwikCityPlanModulePath?](./router.staticgenerateoptions.qwikcityplanmodulepath.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\n_(Optional)_\n\n\n | \n\n\n[qwikRouterConfigModulePath](./router.staticgenerateoptions.qwikrouterconfigmodulepath.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\nPath to the Qwik Router Config module exporting the default `@qwik-router-config`.\n\n\n | \n\n\n[renderModulePath](./router.staticgenerateoptions.rendermodulepath.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\nPath to the SSR module exporting the default render function. In most cases it'll be `./src/entry.ssr.tsx`.\n\n\n | \n\n\n[rootDir?](./router.staticgenerateoptions.rootdir.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\n_(Optional)_\n\n\n | \n ",
- "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/static/types.ts",
- "mdFile": "router.staticgenerateoptions.md"
- },
- {
- "name": "StaticGenerateRenderOptions",
- "id": "staticgeneraterenderoptions",
- "hierarchy": [
- {
- "name": "StaticGenerateRenderOptions",
- "id": "staticgeneraterenderoptions"
- }
- ],
- "kind": "Interface",
- "content": "```typescript\nexport interface StaticGenerateRenderOptions extends RenderOptions \n```\n**Extends:** RenderOptions\n\n\n\n\nProperty\n\n\n | \n\nModifiers\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\n[emit404Pages?](./router.staticgeneraterenderoptions.emit404pages.md)\n\n\n | \n\n\n | \n\nboolean\n\n\n | \n\n_(Optional)_ Set to `false` if the static build should not write custom or default `404.html` pages. Defaults to `true`.\n\n\n | \n\n\n[emitData?](./router.staticgeneraterenderoptions.emitdata.md)\n\n\n | \n\n\n | \n\nboolean\n\n\n | \n\n_(Optional)_ Set to `false` if the generated `q-data.json` data files should not be written to disk. Defaults to `true`.\n\n\n | \n\n\n[emitHtml?](./router.staticgeneraterenderoptions.emithtml.md)\n\n\n | \n\n\n | \n\nboolean\n\n\n | \n\n_(Optional)_ Set to `false` if the generated static HTML files should not be written to disk. Setting to `false` is useful if the SSG should only write the `q-data.json` files to disk. Defaults to `true`.\n\n\n | \n\n\n[exclude?](./router.staticgeneraterenderoptions.exclude.md)\n\n\n | \n\n\n | \n\nstring\\[\\]\n\n\n | \n\n_(Optional)_ Defines file system routes relative to the source `routes` directory that should not be static generated. Accepts wildcard behavior. This should not include the \"base\" pathname. `exclude` always takes priority over `include`.\n\n\n | \n\n\n[include?](./router.staticgeneraterenderoptions.include.md)\n\n\n | \n\n\n | \n\nstring\\[\\]\n\n\n | \n\n_(Optional)_ Defines file system routes relative to the source `routes` directory that should be static generated. Accepts wildcard behavior. This should not include the \"base\" pathname. If not provided, all routes will be static generated. `exclude` always takes priority over `include`.\n\n\n | \n\n\n[log?](./router.staticgeneraterenderoptions.log.md)\n\n\n | \n\n\n | \n\n'debug'\n\n\n | \n\n_(Optional)_ Log level.\n\n\n | \n\n\n[maxTasksPerWorker?](./router.staticgeneraterenderoptions.maxtasksperworker.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n_(Optional)_ Maximum number of tasks to be running at one time per worker. Defaults to `20`.\n\n\n | \n\n\n[maxWorkers?](./router.staticgeneraterenderoptions.maxworkers.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n_(Optional)_ Maximum number of workers to use while generating the static pages. Defaults to the number of CPUs available.\n\n\n | \n\n\n[origin](./router.staticgeneraterenderoptions.origin.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\nThe URL `origin`, which is a combination of the scheme (protocol) and hostname (domain). For example, `https://qwik.dev` has the protocol `https://` and domain `qwik.dev`. However, the `origin` does not include a `pathname`.\n\nThe `origin` is used to provide a full URL during Static Site Generation (SSG), and to simulate a complete URL rather than just the `pathname`. For example, in order to render a correct canonical tag URL or URLs within the `sitemap.xml`, the `origin` must be provided too.\n\nIf the site also starts with a pathname other than `/`, please use the `basePathname` option in the Qwik Router config options.\n\n\n | \n\n\n[outDir](./router.staticgeneraterenderoptions.outdir.md)\n\n\n | \n\n\n | \n\nstring\n\n\n | \n\nFile system directory where the static files should be written.\n\n\n | \n\n\n[sitemapOutFile?](./router.staticgeneraterenderoptions.sitemapoutfile.md)\n\n\n | \n\n\n | \n\nstring \\| null\n\n\n | \n\n_(Optional)_ File system path to write the `sitemap.xml` to. Defaults to `sitemap.xml` and written to the root of the `outDir`. Setting to `null` will prevent the sitemap from being created.\n\n\n | \n ",
- "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/static/types.ts",
- "mdFile": "router.staticgeneraterenderoptions.md"
- },
- {
- "name": "StaticGenerateResult",
- "id": "staticgenerateresult",
- "hierarchy": [
- {
- "name": "StaticGenerateResult",
- "id": "staticgenerateresult"
- }
- ],
- "kind": "Interface",
- "content": "```typescript\nexport interface StaticGenerateResult \n```\n\n\n\n\nProperty\n\n\n | \n\nModifiers\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\n[duration](./router.staticgenerateresult.duration.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n\n | \n\n\n[errors](./router.staticgenerateresult.errors.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n\n | \n\n\n[rendered](./router.staticgenerateresult.rendered.md)\n\n\n | \n\n\n | \n\nnumber\n\n\n | \n\n\n | \n\n\n[staticPaths](./router.staticgenerateresult.staticpaths.md)\n\n\n | \n\n\n | \n\nstring\\[\\]\n\n\n | \n\n\n | \n ",
- "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/static/types.ts",
- "mdFile": "router.staticgenerateresult.md"
- }
- ]
-}
\ No newline at end of file
diff --git a/packages/docs/src/routes/api/qwik-router-vite-ssg/api.json b/packages/docs/src/routes/api/qwik-router-vite-ssg/api.json
new file mode 100644
index 00000000000..ef150e5a758
--- /dev/null
+++ b/packages/docs/src/routes/api/qwik-router-vite-ssg/api.json
@@ -0,0 +1,48 @@
+{
+ "id": "qwik-router-vite-ssg",
+ "package": "@qwik.dev/qwik-router/vite/ssg",
+ "members": [
+ {
+ "name": "ssgAdapter",
+ "id": "ssgadapter",
+ "hierarchy": [
+ {
+ "name": "ssgAdapter",
+ "id": "ssgadapter"
+ }
+ ],
+ "kind": "Function",
+ "content": "```typescript\nexport declare function ssgAdapter(opts: SsgAdapterOptions): any;\n```\n\n\n\n\nParameter\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\nopts\n\n\n | \n\n[SsgAdapterOptions](#ssgadapteroptions)\n\n\n | \n\n\n | \n \n**Returns:**\n\nany",
+ "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/ssg/vite/index.ts",
+ "mdFile": "router.ssgadapter.md"
+ },
+ {
+ "name": "SsgAdapterOptions",
+ "id": "ssgadapteroptions",
+ "hierarchy": [
+ {
+ "name": "SsgAdapterOptions",
+ "id": "ssgadapteroptions"
+ }
+ ],
+ "kind": "Interface",
+ "content": "```typescript\nexport interface SsgAdapterOptions extends Omit \n```\n**Extends:** Omit<SsgRenderOptions, 'outDir'>",
+ "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/ssg/vite/index.ts",
+ "mdFile": "router.ssgadapteroptions.md"
+ },
+ {
+ "name": "staticAdapter",
+ "id": "staticadapter",
+ "hierarchy": [
+ {
+ "name": "staticAdapter",
+ "id": "staticadapter"
+ }
+ ],
+ "kind": "Variable",
+ "content": "> Warning: This API is now obsolete.\n> \n> Use `ssgAdapter` instead.\n> \n\n\n```typescript\nstaticAdapter: typeof ssgAdapter\n```",
+ "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/ssg/vite/index.ts",
+ "mdFile": "router.staticadapter.md"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/docs/src/routes/api/qwik-router-vite-ssg/index.mdx b/packages/docs/src/routes/api/qwik-router-vite-ssg/index.mdx
new file mode 100644
index 00000000000..1a1ea5463a5
--- /dev/null
+++ b/packages/docs/src/routes/api/qwik-router-vite-ssg/index.mdx
@@ -0,0 +1,64 @@
+---
+title: \@qwik.dev/qwik-router/vite/ssg API Reference
+---
+
+# [API](/api) › @qwik.dev/qwik-router/vite/ssg
+
+## ssgAdapter
+
+```typescript
+export declare function ssgAdapter(opts: SsgAdapterOptions): any;
+```
+
+
+
+Parameter
+
+ |
+
+Type
+
+ |
+
+Description
+
+ |
+
+
+opts
+
+ |
+
+[SsgAdapterOptions](#ssgadapteroptions)
+
+ |
+
+ |
+
+**Returns:**
+
+any
+
+[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/ssg/vite/index.ts)
+
+## SsgAdapterOptions
+
+```typescript
+export interface SsgAdapterOptions extends Omit
+```
+
+**Extends:** Omit<SsgRenderOptions, 'outDir'>
+
+[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/ssg/vite/index.ts)
+
+## staticAdapter
+
+> Warning: This API is now obsolete.
+>
+> Use `ssgAdapter` instead.
+
+```typescript
+staticAdapter: typeof ssgAdapter;
+```
+
+[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/ssg/vite/index.ts)
diff --git a/packages/docs/src/routes/api/qwik-router-vite-static/api.json b/packages/docs/src/routes/api/qwik-router-vite-static/api.json
deleted file mode 100644
index 33204188132..00000000000
--- a/packages/docs/src/routes/api/qwik-router-vite-static/api.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "id": "qwik-router-vite-static",
- "package": "@qwik.dev/qwik-router/vite/static",
- "members": [
- {
- "name": "staticAdapter",
- "id": "staticadapter",
- "hierarchy": [
- {
- "name": "staticAdapter",
- "id": "staticadapter"
- }
- ],
- "kind": "Function",
- "content": "```typescript\nexport declare function staticAdapter(opts: StaticGenerateAdapterOptions): any;\n```\n\n\n\n\nParameter\n\n\n | \n\nType\n\n\n | \n\nDescription\n\n\n | \n\n\nopts\n\n\n | \n\n[StaticGenerateAdapterOptions](#staticgenerateadapteroptions)\n\n\n | \n\n\n | \n \n**Returns:**\n\nany",
- "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/static/vite/index.ts",
- "mdFile": "router.staticadapter.md"
- },
- {
- "name": "StaticGenerateAdapterOptions",
- "id": "staticgenerateadapteroptions",
- "hierarchy": [
- {
- "name": "StaticGenerateAdapterOptions",
- "id": "staticgenerateadapteroptions"
- }
- ],
- "kind": "Interface",
- "content": "```typescript\nexport interface StaticGenerateAdapterOptions extends Omit \n```\n**Extends:** Omit<StaticGenerateRenderOptions, 'outDir'>",
- "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/static/vite/index.ts",
- "mdFile": "router.staticgenerateadapteroptions.md"
- }
- ]
-}
\ No newline at end of file
diff --git a/packages/docs/src/routes/api/qwik-router-vite-static/index.mdx b/packages/docs/src/routes/api/qwik-router-vite-static/index.mdx
deleted file mode 100644
index 8b54b776f24..00000000000
--- a/packages/docs/src/routes/api/qwik-router-vite-static/index.mdx
+++ /dev/null
@@ -1,52 +0,0 @@
----
-title: \@qwik.dev/qwik-router/vite/static API Reference
----
-
-# [API](/api) › @qwik.dev/qwik-router/vite/static
-
-## staticAdapter
-
-```typescript
-export declare function staticAdapter(opts: StaticGenerateAdapterOptions): any;
-```
-
-
-
-Parameter
-
- |
-
-Type
-
- |
-
-Description
-
- |
-
-
-opts
-
- |
-
-[StaticGenerateAdapterOptions](#staticgenerateadapteroptions)
-
- |
-
- |
-
-**Returns:**
-
-any
-
-[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/static/vite/index.ts)
-
-## StaticGenerateAdapterOptions
-
-```typescript
-export interface StaticGenerateAdapterOptions extends Omit
-```
-
-**Extends:** Omit<StaticGenerateRenderOptions, 'outDir'>
-
-[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/adapters/static/vite/index.ts)
diff --git a/packages/docs/src/routes/docs/(qwikrouter)/guides/static-site-generation/index.mdx b/packages/docs/src/routes/docs/(qwikrouter)/guides/static-site-generation/index.mdx
index 7ff3e31a06f..ffa985ae199 100644
--- a/packages/docs/src/routes/docs/(qwikrouter)/guides/static-site-generation/index.mdx
+++ b/packages/docs/src/routes/docs/(qwikrouter)/guides/static-site-generation/index.mdx
@@ -72,7 +72,7 @@ Select `Adapter: Static site (.html files)`. Done!
Running the above command will make the following changes to your project:
- A `build.server` script will be automatically added to your `package.json` file.
-- A `adapters/static/vite.config.mts` file will be created.
+- A `adapters/ssg/vite.config.mts` file will be created.
Your build files will be generated into the `dist` folder.
@@ -103,7 +103,7 @@ bun run build.server
### SSG Config
-The `adapters/static/vite.config.mts` file also includes the SSG config, which would be custom for each implementation.
+The `adapters/ssg/vite.config.mts` file also includes the SSG config, which would be custom for each implementation.
#### `origin`
@@ -119,7 +119,7 @@ The `outDir` is a file system output directory where the static files should be
### Javascript Runtimes
-For a Javascript project, it's quite common for the build's runtime to be built on top of [Node.js](https://nodejs.org/en/docs/). However, the core of Qwik Router static site generation isn't tied to using only Node.js, which is why the `qwikRouterGenerate()` function is imported from `@qwik.dev/router/static/node`. By scoping the generate function to a specific runtime, such as Node.js, this gives Qwik Router the flexibility to also generate SSG from other runtimes in the future, such as [Deno](https://deno.land/) or [Bun](https://bun.sh/).
+For a Javascript project, it's quite common for the build's runtime to be built on top of [Node.js](https://nodejs.org/en/docs/). However, the core of Qwik Router static site generation isn't tied to using only Node.js, which is why the `qwikRouterGenerate()` function is imported from `@qwik.dev/router/ssg/node`. By scoping the generate function to a specific runtime, such as Node.js, this gives Qwik Router the flexibility to also generate SSG from other runtimes in the future, such as [Deno](https://deno.land/) or [Bun](https://bun.sh/).
## Dynamic SSG Routes
diff --git a/packages/docs/src/routes/docs/deployments/cloudflare-pages/index.mdx b/packages/docs/src/routes/docs/deployments/cloudflare-pages/index.mdx
index 9988165ac67..4f60e4e3ccc 100644
--- a/packages/docs/src/routes/docs/deployments/cloudflare-pages/index.mdx
+++ b/packages/docs/src/routes/docs/deployments/cloudflare-pages/index.mdx
@@ -152,7 +152,11 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ['src/entry.cloudflare-pages.tsx', '@qwik-router-config'],
+ input: [
+ 'src/entry.cloudflare-pages.tsx',
+ // This ensures that the SSG can read the routes from the config
+ '@qwik-router-config',
+ ],
}
},
plugins: [
@@ -204,10 +208,9 @@ import {
createQwikRouter,
type PlatformCloudflarePages,
} from '@qwik.dev/router/middleware/cloudflare-pages';
-import qwikRouterConfig from '@qwik-router-config';
import render from './entry.ssr';
-const fetch = createQwikRouter({ render, qwikRouterConfig });
+const fetch = createQwikRouter({ render });
export { fetch };
```
diff --git a/packages/docs/src/routes/docs/deployments/netlify-edge/index.mdx b/packages/docs/src/routes/docs/deployments/netlify-edge/index.mdx
index bc62d20c2ed..6a3c86a288c 100644
--- a/packages/docs/src/routes/docs/deployments/netlify-edge/index.mdx
+++ b/packages/docs/src/routes/docs/deployments/netlify-edge/index.mdx
@@ -130,10 +130,9 @@ When the `netlify-edge` adapter is added, a new entry file will be created at `s
```tsx title="src/entry.netlify-edge.tsx"
import { createQwikRouter } from '@qwik.dev/router/middleware/netlify-edge';
-import qwikRouterConfig from '@qwik-router-config';
import render from './entry.ssr';
-export default createQwikRouter({ render, qwikRouterConfig });
+export default createQwikRouter({ render });
```
The compiled middleware will be built in the `.netlify/edge-functions` directory.
diff --git a/packages/docs/src/routes/docs/deployments/node/index.mdx b/packages/docs/src/routes/docs/deployments/node/index.mdx
index 90d8fb42dad..af89b389e8d 100644
--- a/packages/docs/src/routes/docs/deployments/node/index.mdx
+++ b/packages/docs/src/routes/docs/deployments/node/index.mdx
@@ -164,8 +164,6 @@ If you want to disable CSRF protection, you can set `checkOrigin: false` in the
// ...
const { router, notFound, staticFile } = createQwikRouter({
render,
- qwikRouterConfig,
- manifest,
checkOrigin: false,
});
// ...
diff --git a/packages/docs/src/routes/docs/deployments/static/index.mdx b/packages/docs/src/routes/docs/deployments/static/index.mdx
index f62e6bc25d9..c268d0285c1 100644
--- a/packages/docs/src/routes/docs/deployments/static/index.mdx
+++ b/packages/docs/src/routes/docs/deployments/static/index.mdx
@@ -15,36 +15,36 @@ Qwik's Static Site adapter helps to generate static html files which can be easi
## Installation
-To integrate the `static-site` adapter, use the `add` command:
+To integrate the `ssg` adapter, use the `add` command:
```shell
-pnpm run qwik add static
+pnpm run qwik add ssg
```
```shell
-npm run qwik add static
+npm run qwik add ssg
```
```shell
-yarn run qwik add static
+yarn run qwik add ssg
```
```shell
-bun run qwik add static
+bun run qwik add ssg
```
-Above command will create a directory at project root named `adapters/static/vite.config.mts` with the below code.
+Above command will create a directory at project root named `adapters/ssg/vite.config.mts` with the below code.
-```ts title="adapters/static/vite.config.mts"
-import { staticAdapter } from "@qwik.dev/router/adapters/static/vite";
+```ts title="adapters/ssg/vite.config.mts"
+import { ssgAdapter } from "@qwik.dev/router/adapters/ssg/vite";
import { extendConfig } from '@qwik.dev/router';
import baseConfig from '../../vite.config.mts';
@@ -57,7 +57,7 @@ export default extendConfig(baseConfig, () => {
},
},
plugins: [
- staticAdapter({
+ ssgAdapter({
origin: 'https://yoursite.qwik.dev',
}),
],
diff --git a/packages/docs/src/routes/docs/deployments/vercel-edge/index.mdx b/packages/docs/src/routes/docs/deployments/vercel-edge/index.mdx
index cd83b6b23cd..aa4f253f660 100644
--- a/packages/docs/src/routes/docs/deployments/vercel-edge/index.mdx
+++ b/packages/docs/src/routes/docs/deployments/vercel-edge/index.mdx
@@ -136,10 +136,9 @@ When the `vercel-edge` adapter is added, a new entry file will be created at `sr
```tsx title="src/entry.vercel-edge.tsx"
import { createQwikRouter } from '@qwik.dev/router/middleware/vercel-edge';
-import qwikRouterConfig from '@qwik-router-config';
import render from './entry.ssr';
-export default createQwikRouter({ render, qwikRouterConfig });
+export default createQwikRouter({ render });
```
The compiled middleware will be built in the `.vercel/output` directory.
diff --git a/packages/docs/src/routes/docs/integrations/react/index.mdx b/packages/docs/src/routes/docs/integrations/react/index.mdx
index 771cdb95806..50f7e2bd993 100644
--- a/packages/docs/src/routes/docs/integrations/react/index.mdx
+++ b/packages/docs/src/routes/docs/integrations/react/index.mdx
@@ -909,6 +909,4 @@ The host element is not part of React, meaning that hydration is not necessary t
This will effectively allow you to respond to a click in a [MUI button](https://mui.com/material-ui/react-button/) without downloading a single byte of React code.
-🧑💻Happy hacking!import PackageManagerTabs from '~/components/package-manager-tabs/index.tsx';
-import CodeSandbox, { CodeFile } from '../../../../components/code-sandbox/index.tsx';
-
+🧑💻Happy hacking!
diff --git a/packages/insights/adapters/netlify-edge/vite.config.ts b/packages/insights/adapters/netlify-edge/vite.config.ts
index 8275b44631c..42f7ec4061a 100644
--- a/packages/insights/adapters/netlify-edge/vite.config.ts
+++ b/packages/insights/adapters/netlify-edge/vite.config.ts
@@ -7,7 +7,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ['src/entry.netlify-edge.tsx', '@qwik-router-config'],
+ input: ['src/entry.netlify-edge.tsx'],
},
outDir: '.netlify/edge-functions/entry.netlify-edge',
},
diff --git a/packages/insights/src/entry.netlify-edge.tsx b/packages/insights/src/entry.netlify-edge.tsx
index 5ae3c0bd069..f09fe49a1cc 100644
--- a/packages/insights/src/entry.netlify-edge.tsx
+++ b/packages/insights/src/entry.netlify-edge.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/netlify-edge/
*
*/
-import qwikRouterConfig from '@qwik-router-config';
import { createQwikRouter, type PlatformNetlify } from '@qwik.dev/router/middleware/netlify-edge';
import render from './entry.ssr';
@@ -17,7 +16,6 @@ declare global {
export default createQwikRouter({
render,
- qwikRouterConfig,
// disable CSRF protection because we get called from everywhere
checkOrigin: false,
});
diff --git a/packages/insights/src/entry.preview.tsx b/packages/insights/src/entry.preview.tsx
index 2965805f8de..b260af58fd0 100644
--- a/packages/insights/src/entry.preview.tsx
+++ b/packages/insights/src/entry.preview.tsx
@@ -10,9 +10,8 @@
* - https://vitejs.dev/config/preview-options.html#preview-options
*
*/
-import qwikRouterConfig from '@qwik-router-config';
import { createQwikRouter } from '@qwik.dev/router/middleware/node';
import render from './entry.ssr';
/** The default export is the QwikRouter adapter used by Vite preview. */
-export default createQwikRouter({ render, qwikRouterConfig });
+export default createQwikRouter({ render });
diff --git a/packages/qwik-router/adapters/static/vite.d.ts b/packages/qwik-router/adapters/static/vite.d.ts
index c62d0cab821..483e314fd23 100644
--- a/packages/qwik-router/adapters/static/vite.d.ts
+++ b/packages/qwik-router/adapters/static/vite.d.ts
@@ -1,2 +1,2 @@
// re-export for typescript in old resolution mode
-export * from '../../lib/adapters/static/vite';
+export * from '../../lib/adapters/ssg/vite';
diff --git a/packages/qwik-router/global.d.ts b/packages/qwik-router/global.d.ts
index 08bc95c6520..689e59a2843 100644
--- a/packages/qwik-router/global.d.ts
+++ b/packages/qwik-router/global.d.ts
@@ -21,3 +21,6 @@ declare var __EXPERIMENTAL__: {
};
declare var __DEFAULT_LOADERS_SERIALIZATION_STRATEGY__: SerializationStrategy;
+
+/** Should routes not have a trailing slash? */
+declare var __NO_TRAILING_SLASH__: boolean;
diff --git a/packages/qwik-router/package.json b/packages/qwik-router/package.json
index 98b06e94d34..d1611fb8925 100644
--- a/packages/qwik-router/package.json
+++ b/packages/qwik-router/package.json
@@ -92,9 +92,14 @@
"require": "./lib/adapters/shared/vite/index.cjs"
},
"./adapters/static/vite": {
- "types": "./lib/adapters/static/vite/index.d.ts",
- "import": "./lib/adapters/static/vite/index.mjs",
- "require": "./lib/adapters/static/vite/index.cjs"
+ "types": "./lib/adapters/ssg/vite/index.d.ts",
+ "import": "./lib/adapters/ssg/vite/index.mjs",
+ "require": "./lib/adapters/ssg/vite/index.cjs"
+ },
+ "./adapters/ssg/vite": {
+ "types": "./lib/adapters/ssg/vite/index.d.ts",
+ "import": "./lib/adapters/ssg/vite/index.mjs",
+ "require": "./lib/adapters/ssg/vite/index.cjs"
},
"./adapters/vercel-edge/vite": {
"types": "./lib/adapters/vercel-edge/vite/index.d.ts",
@@ -144,9 +149,14 @@
"import": "./lib/middleware/vercel-edge/index.mjs"
},
"./static": {
- "types": "./lib/static/index.d.ts",
- "import": "./lib/static/index.mjs",
- "require": "./lib/static/index.cjs"
+ "types": "./lib/ssg/index.d.ts",
+ "import": "./lib/ssg/index.mjs",
+ "require": "./lib/ssg/index.cjs"
+ },
+ "./ssg": {
+ "types": "./lib/ssg/index.d.ts",
+ "import": "./lib/ssg/index.mjs",
+ "require": "./lib/ssg/index.cjs"
},
"./vite": {
"types": "./lib/vite/index.d.ts",
@@ -169,6 +179,7 @@
"README.md",
"service-worker.d.ts",
"static.d.ts",
+ "ssg.d.ts",
"vite.d.ts"
],
"homepage": "https://qwik.dev/",
diff --git a/packages/qwik-router/src/adapters/azure-swa/adapter.azure-swa.api.md b/packages/qwik-router/src/adapters/azure-swa/adapter.azure-swa.api.md
index 540bb1296d3..b9e11b5eda2 100644
--- a/packages/qwik-router/src/adapters/azure-swa/adapter.azure-swa.api.md
+++ b/packages/qwik-router/src/adapters/azure-swa/adapter.azure-swa.api.md
@@ -5,7 +5,7 @@
```ts
import { ServerAdapterOptions } from '../../shared/vite';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
// @public (undocumented)
export function azureSwaAdapter(opts?: AzureSwaAdapterOptions): any;
@@ -14,7 +14,7 @@ export function azureSwaAdapter(opts?: AzureSwaAdapterOptions): any;
export interface AzureSwaAdapterOptions extends ServerAdapterOptions {
}
-export { StaticGenerateRenderOptions }
+export { SsgRenderOptions }
// (No @packageDocumentation comment for this package)
diff --git a/packages/qwik-router/src/adapters/azure-swa/vite/index.ts b/packages/qwik-router/src/adapters/azure-swa/vite/index.ts
index eee42333ab9..1b995d9de71 100644
--- a/packages/qwik-router/src/adapters/azure-swa/vite/index.ts
+++ b/packages/qwik-router/src/adapters/azure-swa/vite/index.ts
@@ -1,4 +1,4 @@
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import fs from 'node:fs';
import { join } from 'node:path';
import { type ServerAdapterOptions, viteAdapter } from '../../shared/vite';
@@ -68,4 +68,4 @@ export function azureSwaAdapter(opts: AzureSwaAdapterOptions = {}): any {
export interface AzureSwaAdapterOptions extends ServerAdapterOptions {}
/** @public */
-export type { StaticGenerateRenderOptions };
+export type { SsgRenderOptions };
diff --git a/packages/qwik-router/src/adapters/bun-server/adapter.bun-server.api.md b/packages/qwik-router/src/adapters/bun-server/adapter.bun-server.api.md
index 3dbadf68656..582e81feb48 100644
--- a/packages/qwik-router/src/adapters/bun-server/adapter.bun-server.api.md
+++ b/packages/qwik-router/src/adapters/bun-server/adapter.bun-server.api.md
@@ -5,7 +5,7 @@
```ts
import { ServerAdapterOptions } from '../../shared/vite';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
// @beta (undocumented)
export function bunServerAdapter(opts?: bunServerAdapterOptions): any;
@@ -16,7 +16,7 @@ export interface bunServerAdapterOptions extends ServerAdapterOptions {
name?: string;
}
-export { StaticGenerateRenderOptions }
+export { SsgRenderOptions }
// (No @packageDocumentation comment for this package)
diff --git a/packages/qwik-router/src/adapters/bun-server/vite/index.ts b/packages/qwik-router/src/adapters/bun-server/vite/index.ts
index 396c9ae2098..6bcb325bb05 100644
--- a/packages/qwik-router/src/adapters/bun-server/vite/index.ts
+++ b/packages/qwik-router/src/adapters/bun-server/vite/index.ts
@@ -1,4 +1,4 @@
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import { viteAdapter, type ServerAdapterOptions } from '../../shared/vite';
/** @beta */
@@ -30,4 +30,4 @@ export interface bunServerAdapterOptions extends ServerAdapterOptions {
}
/** @beta */
-export type { StaticGenerateRenderOptions };
+export type { SsgRenderOptions };
diff --git a/packages/qwik-router/src/adapters/cloud-run/adapter.cloud-run.api.md b/packages/qwik-router/src/adapters/cloud-run/adapter.cloud-run.api.md
index a8f6055e910..c101f7732ed 100644
--- a/packages/qwik-router/src/adapters/cloud-run/adapter.cloud-run.api.md
+++ b/packages/qwik-router/src/adapters/cloud-run/adapter.cloud-run.api.md
@@ -5,7 +5,7 @@
```ts
import { ServerAdapterOptions } from '../../shared/vite';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
// @public (undocumented)
export function cloudRunAdapter(opts?: CloudRunAdapterOptions): any;
@@ -14,7 +14,7 @@ export function cloudRunAdapter(opts?: CloudRunAdapterOptions): any;
export interface CloudRunAdapterOptions extends ServerAdapterOptions {
}
-export { StaticGenerateRenderOptions }
+export { SsgRenderOptions }
// (No @packageDocumentation comment for this package)
diff --git a/packages/qwik-router/src/adapters/cloud-run/vite/index.ts b/packages/qwik-router/src/adapters/cloud-run/vite/index.ts
index 785c04ea714..24c8126a0ff 100644
--- a/packages/qwik-router/src/adapters/cloud-run/vite/index.ts
+++ b/packages/qwik-router/src/adapters/cloud-run/vite/index.ts
@@ -1,4 +1,4 @@
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import { type ServerAdapterOptions, viteAdapter } from '../../shared/vite';
/** @public */
@@ -24,4 +24,4 @@ export function cloudRunAdapter(opts: CloudRunAdapterOptions = {}): any {
export interface CloudRunAdapterOptions extends ServerAdapterOptions {}
/** @public */
-export type { StaticGenerateRenderOptions };
+export type { SsgRenderOptions };
diff --git a/packages/qwik-router/src/adapters/cloudflare-pages/adapter.cloudflare-pages.api.md b/packages/qwik-router/src/adapters/cloudflare-pages/adapter.cloudflare-pages.api.md
index f0caf175cd5..6a97a6bcddf 100644
--- a/packages/qwik-router/src/adapters/cloudflare-pages/adapter.cloudflare-pages.api.md
+++ b/packages/qwik-router/src/adapters/cloudflare-pages/adapter.cloudflare-pages.api.md
@@ -5,7 +5,7 @@
```ts
import { ServerAdapterOptions } from '../../shared/vite';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
// @public (undocumented)
export function cloudflarePagesAdapter(opts?: CloudflarePagesAdapterOptions): any;
@@ -16,7 +16,7 @@ export interface CloudflarePagesAdapterOptions extends ServerAdapterOptions {
staticPaths?: string[];
}
-export { StaticGenerateRenderOptions }
+export { SsgRenderOptions }
// (No @packageDocumentation comment for this package)
diff --git a/packages/qwik-router/src/adapters/cloudflare-pages/vite/index.ts b/packages/qwik-router/src/adapters/cloudflare-pages/vite/index.ts
index 728e92452d1..ed0fed99c06 100644
--- a/packages/qwik-router/src/adapters/cloudflare-pages/vite/index.ts
+++ b/packages/qwik-router/src/adapters/cloudflare-pages/vite/index.ts
@@ -1,4 +1,4 @@
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import fs from 'node:fs';
import { join, relative } from 'node:path';
import { normalizePathSlash } from '../../../utils/fs';
@@ -85,4 +85,4 @@ export interface CloudflarePagesAdapterOptions extends ServerAdapterOptions {
}
/** @public */
-export type { StaticGenerateRenderOptions };
+export type { SsgRenderOptions };
diff --git a/packages/qwik-router/src/adapters/deno-server/adapter.deno-server.api.md b/packages/qwik-router/src/adapters/deno-server/adapter.deno-server.api.md
index efc7b7e1774..2f468113757 100644
--- a/packages/qwik-router/src/adapters/deno-server/adapter.deno-server.api.md
+++ b/packages/qwik-router/src/adapters/deno-server/adapter.deno-server.api.md
@@ -5,7 +5,7 @@
```ts
import { ServerAdapterOptions } from '../../shared/vite';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
// @beta (undocumented)
export function denoServerAdapter(opts?: DenoServerAdapterOptions): any;
@@ -16,7 +16,7 @@ export interface DenoServerAdapterOptions extends ServerAdapterOptions {
name?: string;
}
-export { StaticGenerateRenderOptions }
+export { SsgRenderOptions }
// (No @packageDocumentation comment for this package)
diff --git a/packages/qwik-router/src/adapters/deno-server/vite/index.ts b/packages/qwik-router/src/adapters/deno-server/vite/index.ts
index 5f99f9f52a4..aba61a974b5 100644
--- a/packages/qwik-router/src/adapters/deno-server/vite/index.ts
+++ b/packages/qwik-router/src/adapters/deno-server/vite/index.ts
@@ -1,4 +1,4 @@
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import { viteAdapter, type ServerAdapterOptions } from '../../shared/vite';
/** @beta */
@@ -42,4 +42,4 @@ export interface DenoServerAdapterOptions extends ServerAdapterOptions {
}
/** @beta */
-export type { StaticGenerateRenderOptions };
+export type { SsgRenderOptions };
diff --git a/packages/qwik-router/src/adapters/netlify-edge/adapter.netlify-edge.api.md b/packages/qwik-router/src/adapters/netlify-edge/adapter.netlify-edge.api.md
index 79c02998108..21e8cb95a5e 100644
--- a/packages/qwik-router/src/adapters/netlify-edge/adapter.netlify-edge.api.md
+++ b/packages/qwik-router/src/adapters/netlify-edge/adapter.netlify-edge.api.md
@@ -5,7 +5,7 @@
```ts
import { ServerAdapterOptions } from '../../shared/vite';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
// @public (undocumented)
export function netlifyEdgeAdapter(opts?: NetlifyEdgeAdapterOptions): any;
@@ -17,7 +17,7 @@ export interface NetlifyEdgeAdapterOptions extends ServerAdapterOptions {
staticPaths?: string[];
}
-export { StaticGenerateRenderOptions }
+export { SsgRenderOptions }
// (No @packageDocumentation comment for this package)
diff --git a/packages/qwik-router/src/adapters/netlify-edge/vite/index.ts b/packages/qwik-router/src/adapters/netlify-edge/vite/index.ts
index 0b569f11563..0261b4fa485 100644
--- a/packages/qwik-router/src/adapters/netlify-edge/vite/index.ts
+++ b/packages/qwik-router/src/adapters/netlify-edge/vite/index.ts
@@ -1,5 +1,5 @@
import { basePathname } from '@qwik-router-config';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import fs, { existsSync } from 'node:fs';
import { join } from 'node:path';
import { getParentDir, type ServerAdapterOptions, viteAdapter } from '../../shared/vite';
@@ -131,4 +131,4 @@ export interface NetlifyEdgeAdapterOptions extends ServerAdapterOptions {
}
/** @public */
-export type { StaticGenerateRenderOptions };
+export type { SsgRenderOptions };
diff --git a/packages/qwik-router/src/adapters/node-server/adapter.node-server.api.md b/packages/qwik-router/src/adapters/node-server/adapter.node-server.api.md
index 34785dc9d51..736c0f74d37 100644
--- a/packages/qwik-router/src/adapters/node-server/adapter.node-server.api.md
+++ b/packages/qwik-router/src/adapters/node-server/adapter.node-server.api.md
@@ -5,7 +5,7 @@
```ts
import { ServerAdapterOptions } from '../../shared/vite';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
// @beta (undocumented)
export function nodeServerAdapter(opts?: NodeServerAdapterOptions): any;
@@ -16,7 +16,7 @@ export interface NodeServerAdapterOptions extends ServerAdapterOptions {
name?: string;
}
-export { StaticGenerateRenderOptions }
+export { SsgRenderOptions }
// (No @packageDocumentation comment for this package)
diff --git a/packages/qwik-router/src/adapters/node-server/vite/index.ts b/packages/qwik-router/src/adapters/node-server/vite/index.ts
index 52e95b010e5..db733a4f024 100644
--- a/packages/qwik-router/src/adapters/node-server/vite/index.ts
+++ b/packages/qwik-router/src/adapters/node-server/vite/index.ts
@@ -1,4 +1,4 @@
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import { viteAdapter, type ServerAdapterOptions } from '../../shared/vite';
/** @beta */
@@ -30,4 +30,4 @@ export interface NodeServerAdapterOptions extends ServerAdapterOptions {
}
/** @beta */
-export type { StaticGenerateRenderOptions };
+export type { SsgRenderOptions };
diff --git a/packages/qwik-router/src/adapters/shared/adapter.shared.api.md b/packages/qwik-router/src/adapters/shared/adapter.shared.api.md
index 5737d80e817..49cb71e0d10 100644
--- a/packages/qwik-router/src/adapters/shared/adapter.shared.api.md
+++ b/packages/qwik-router/src/adapters/shared/adapter.shared.api.md
@@ -5,11 +5,11 @@
```ts
import type { Plugin as Plugin_2 } from 'vite';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import type { UserConfig } from 'vite';
// @public (undocumented)
-export interface AdapterSSGOptions extends Omit {
+export interface AdapterSSGOptions extends Omit {
exclude?: string[];
include: string[];
origin?: string;
diff --git a/packages/qwik-router/src/adapters/shared/vite/index.ts b/packages/qwik-router/src/adapters/shared/vite/index.ts
index bd95d56afc7..c83c54b8dfd 100644
--- a/packages/qwik-router/src/adapters/shared/vite/index.ts
+++ b/packages/qwik-router/src/adapters/shared/vite/index.ts
@@ -1,5 +1,5 @@
import type { QwikVitePlugin } from '@qwik.dev/core/optimizer';
-import type { StaticGenerateOptions, StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { StaticGenerateOptions, SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import type { QwikRouterPlugin } from '@qwik.dev/router/vite';
import fs from 'node:fs';
import { basename, dirname, join, resolve } from 'node:path';
@@ -70,7 +70,22 @@ export function viteAdapter(opts: ViteAdapterPluginOptions) {
}
}
},
-
+ buildStart() {
+ if (isSsrBuild && opts.ssg !== null) {
+ const { srcDir } = qwikVitePlugin!.api!.getOptions()!;
+ // TODO don't rely on entry points for SSG, somehow
+ this.emitFile({
+ id: '@qwik-router-config',
+ type: 'chunk',
+ fileName: '@qwik-router-config.js',
+ });
+ this.emitFile({
+ id: `${srcDir}/entry.ssr`,
+ type: 'chunk',
+ fileName: 'entry.ssr.js',
+ });
+ }
+ },
generateBundle(_, bundles) {
if (isSsrBuild) {
outputEntries.length = 0;
@@ -87,18 +102,6 @@ export function viteAdapter(opts: ViteAdapterPluginOptions) {
}
}
}
-
- if (!renderModulePath) {
- throw new Error(
- 'Unable to find "entry.ssr" entry point. Did you forget to add it to "build.rollupOptions.input"?'
- );
- }
-
- if (!qwikRouterConfigModulePath) {
- throw new Error(
- 'Unable to find "@qwik-router-config" entry point. Did you forget to add it to "build.rollupOptions.input"?'
- );
- }
}
},
@@ -139,14 +142,14 @@ export function viteAdapter(opts: ViteAdapterPluginOptions) {
}
try {
ssgOrigin = new URL(ssgOrigin).origin;
- } catch (e) {
+ } catch {
this.warn(
`Invalid "origin" option: "${ssgOrigin}". Using default origin: "https://yoursite.qwik.dev"`
);
ssgOrigin = `https://yoursite.qwik.dev`;
}
- const staticGenerate = await import('../../../static');
+ const staticGenerate = await import('../../../ssg');
const generateOpts: StaticGenerateOptions = {
maxWorkers: opts.maxWorkers,
basePathname,
@@ -262,7 +265,7 @@ export interface ServerAdapterOptions {
}
/** @public */
-export interface AdapterSSGOptions extends Omit {
+export interface AdapterSSGOptions extends Omit {
/** Defines routes that should be static generated. Accepts wildcard behavior. */
include: string[];
/**
diff --git a/packages/qwik-router/src/adapters/ssg/adapter.ssg.api.md b/packages/qwik-router/src/adapters/ssg/adapter.ssg.api.md
new file mode 100644
index 00000000000..0f8d9be1046
--- /dev/null
+++ b/packages/qwik-router/src/adapters/ssg/adapter.ssg.api.md
@@ -0,0 +1,21 @@
+## API Report File for "@qwik.dev/router"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+
+import type { SsgRenderOptions } from '../../../ssg';
+
+// @public (undocumented)
+export function ssgAdapter(opts: SsgAdapterOptions): any;
+
+// @public (undocumented)
+export interface SsgAdapterOptions extends Omit {
+}
+
+// @public @deprecated (undocumented)
+export const staticAdapter: typeof ssgAdapter;
+
+// (No @packageDocumentation comment for this package)
+
+```
diff --git a/packages/qwik-router/src/adapters/static/vite/api-extractor.json b/packages/qwik-router/src/adapters/ssg/vite/api-extractor.json
similarity index 61%
rename from packages/qwik-router/src/adapters/static/vite/api-extractor.json
rename to packages/qwik-router/src/adapters/ssg/vite/api-extractor.json
index c8679c637c1..82aaf6b93b8 100644
--- a/packages/qwik-router/src/adapters/static/vite/api-extractor.json
+++ b/packages/qwik-router/src/adapters/ssg/vite/api-extractor.json
@@ -1,20 +1,20 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"extends": "../../../api-extractor.json",
- "mainEntryPointFilePath": "/../../dist-dev/dts-out/packages/qwik-router/src/adapters/static/vite/index.d.ts",
+ "mainEntryPointFilePath": "/../../dist-dev/dts-out/packages/qwik-router/src/adapters/ssg/vite/index.d.ts",
"newlineKind": "lf",
"apiReport": {
"enabled": true,
- "reportFileName": "adapter.static",
- "reportFolder": "/src/adapters/static/",
- "reportTempFolder": "/../../dist-dev/api-extractor/qwik-router/adapters/static"
+ "reportFileName": "adapter.ssg",
+ "reportFolder": "/src/adapters/ssg/",
+ "reportTempFolder": "/../../dist-dev/api-extractor/qwik-router/adapters/ssg"
},
"dtsRollup": {
"enabled": true,
- "untrimmedFilePath": "/lib/adapters/static/vite/index.d.ts"
+ "untrimmedFilePath": "/lib/adapters/ssg/vite/index.d.ts"
},
"docModel": {
"enabled": true,
- "apiJsonFilePath": "/../../dist-dev/api/qwik-router/vite/static/docs.api.json"
+ "apiJsonFilePath": "/../../dist-dev/api/qwik-router/vite/ssg/docs.api.json"
}
}
diff --git a/packages/qwik-router/src/adapters/ssg/vite/index.ts b/packages/qwik-router/src/adapters/ssg/vite/index.ts
new file mode 100644
index 00000000000..9ef64224a75
--- /dev/null
+++ b/packages/qwik-router/src/adapters/ssg/vite/index.ts
@@ -0,0 +1,20 @@
+import type { SsgRenderOptions } from '../../../ssg';
+import { viteAdapter } from '../../shared/vite';
+
+/** @public */
+export function ssgAdapter(opts: SsgAdapterOptions): any {
+ return viteAdapter({
+ name: 'static-site-generation',
+ origin: opts.origin,
+ ssg: {
+ include: ['/*'],
+ ...opts,
+ },
+ });
+}
+
+/** @public @deprecated Use `ssgAdapter` instead. */
+export const staticAdapter = ssgAdapter;
+
+/** @public */
+export interface SsgAdapterOptions extends Omit {}
diff --git a/packages/qwik-router/src/adapters/static/adapter.static.api.md b/packages/qwik-router/src/adapters/static/adapter.static.api.md
deleted file mode 100644
index d724ba37fdc..00000000000
--- a/packages/qwik-router/src/adapters/static/adapter.static.api.md
+++ /dev/null
@@ -1,18 +0,0 @@
-## API Report File for "@qwik.dev/router"
-
-> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
-
-```ts
-
-import type { StaticGenerateRenderOptions } from '../../../static';
-
-// @public (undocumented)
-export function staticAdapter(opts: StaticGenerateAdapterOptions): any;
-
-// @public (undocumented)
-export interface StaticGenerateAdapterOptions extends Omit {
-}
-
-// (No @packageDocumentation comment for this package)
-
-```
diff --git a/packages/qwik-router/src/adapters/static/vite/index.ts b/packages/qwik-router/src/adapters/static/vite/index.ts
deleted file mode 100644
index aafff639780..00000000000
--- a/packages/qwik-router/src/adapters/static/vite/index.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { StaticGenerateRenderOptions } from '../../../static';
-import { viteAdapter } from '../../shared/vite';
-
-/** @public */
-export function staticAdapter(opts: StaticGenerateAdapterOptions): any {
- return viteAdapter({
- name: 'static-generate',
- origin: opts.origin,
- ssg: {
- include: ['/*'],
- ...opts,
- },
- });
-}
-
-/** @public */
-export interface StaticGenerateAdapterOptions extends Omit {}
diff --git a/packages/qwik-router/src/adapters/vercel-edge/adapter.vercel-edge.api.md b/packages/qwik-router/src/adapters/vercel-edge/adapter.vercel-edge.api.md
index 9873821540b..05ffc97ad50 100644
--- a/packages/qwik-router/src/adapters/vercel-edge/adapter.vercel-edge.api.md
+++ b/packages/qwik-router/src/adapters/vercel-edge/adapter.vercel-edge.api.md
@@ -5,9 +5,9 @@
```ts
import { ServerAdapterOptions } from '../../shared/vite';
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
-export { StaticGenerateRenderOptions }
+export { SsgRenderOptions }
// @public (undocumented)
export function vercelEdgeAdapter(opts?: VercelEdgeAdapterOptions): any;
diff --git a/packages/qwik-router/src/adapters/vercel-edge/vite/index.ts b/packages/qwik-router/src/adapters/vercel-edge/vite/index.ts
index 0d3b76b54f3..87d1df73646 100644
--- a/packages/qwik-router/src/adapters/vercel-edge/vite/index.ts
+++ b/packages/qwik-router/src/adapters/vercel-edge/vite/index.ts
@@ -1,4 +1,4 @@
-import type { StaticGenerateRenderOptions } from '@qwik.dev/router/static';
+import type { SsgRenderOptions } from 'packages/qwik-router/src/ssg';
import fs from 'node:fs';
import { dirname, join } from 'node:path';
import { getParentDir, type ServerAdapterOptions, viteAdapter } from '../../shared/vite';
@@ -140,4 +140,4 @@ export interface VercelEdgeAdapterOptions extends ServerAdapterOptions {
}
/** @public */
-export type { StaticGenerateRenderOptions };
+export type { SsgRenderOptions };
diff --git a/packages/qwik-router/src/buildtime/context.ts b/packages/qwik-router/src/buildtime/context.ts
index 75d6448240c..4f2b0dbff46 100644
--- a/packages/qwik-router/src/buildtime/context.ts
+++ b/packages/qwik-router/src/buildtime/context.ts
@@ -92,10 +92,6 @@ function normalizeOptions(
const url = new URL(opts.basePathname, 'https://qwik.dev/');
opts.basePathname = url.pathname;
- if (typeof opts.trailingSlash !== 'boolean') {
- opts.trailingSlash = true;
- }
-
opts.mdx = opts.mdx || {};
opts.platform = opts.platform || {};
diff --git a/packages/qwik-router/src/buildtime/markdown/markdown-url.ts b/packages/qwik-router/src/buildtime/markdown/markdown-url.ts
index d8cd091d7df..0b56ae83204 100644
--- a/packages/qwik-router/src/buildtime/markdown/markdown-url.ts
+++ b/packages/qwik-router/src/buildtime/markdown/markdown-url.ts
@@ -49,10 +49,10 @@ export function getMarkdownRelativeUrl(
}
} else if (extension === '') {
if (url.endsWith('/')) {
- if (!opts.trailingSlash) {
+ if (globalThis.__NO_TRAILING_SLASH__) {
url = url.slice(0, -1);
}
- } else if (opts.trailingSlash) {
+ } else if (!globalThis.__NO_TRAILING_SLASH__) {
url += '/';
}
}
diff --git a/packages/qwik-router/src/buildtime/markdown/markdown-url.unit.ts b/packages/qwik-router/src/buildtime/markdown/markdown-url.unit.ts
index 7a5757e3295..a2a951831f6 100644
--- a/packages/qwik-router/src/buildtime/markdown/markdown-url.unit.ts
+++ b/packages/qwik-router/src/buildtime/markdown/markdown-url.unit.ts
@@ -66,10 +66,9 @@ const menuFilePath = join(routesDir, 'docs', 'menu.md');
expect: './getting-started.txt',
},
].forEach((t) => {
- test(`getMarkdownRelativeUrl ${t.href}`, () => {
+ test(`getMarkdownRelativeUrl ${t.href} ${t.trailingSlash ? 'with' : 'without'} slash`, () => {
const opts: NormalizedPluginOptions = {
basePathname: '/',
- trailingSlash: !!t.trailingSlash,
routesDir,
serverPluginsDir,
mdxPlugins: {
@@ -82,6 +81,7 @@ const menuFilePath = join(routesDir, 'docs', 'menu.md');
rewriteRoutes: [],
defaultLoadersSerializationStrategy: 'never',
};
+ globalThis.__NO_TRAILING_SLASH__ = !t.trailingSlash;
assert.equal(getMarkdownRelativeUrl(opts, menuFilePath, t.href), t.expect);
});
});
diff --git a/packages/qwik-router/src/buildtime/routing/resolve-source-file.unit.ts b/packages/qwik-router/src/buildtime/routing/resolve-source-file.unit.ts
index f699938adf6..13d1c3fbb33 100644
--- a/packages/qwik-router/src/buildtime/routing/resolve-source-file.unit.ts
+++ b/packages/qwik-router/src/buildtime/routing/resolve-source-file.unit.ts
@@ -40,7 +40,6 @@ test('resolveLayout', () => {
routesDir: '',
serverPluginsDir: '',
basePathname: '/',
- trailingSlash: false,
mdxPlugins: {
remarkGfm: true,
rehypeSyntaxHighlight: true,
diff --git a/packages/qwik-router/src/buildtime/runtime-generation/generate-qwik-router-config.ts b/packages/qwik-router/src/buildtime/runtime-generation/generate-qwik-router-config.ts
index 5908eee1afe..efb8b41f908 100644
--- a/packages/qwik-router/src/buildtime/runtime-generation/generate-qwik-router-config.ts
+++ b/packages/qwik-router/src/buildtime/runtime-generation/generate-qwik-router-config.ts
@@ -24,7 +24,7 @@ export function generateQwikRouterConfig(
createEntries(ctx, c);
- c.push(`export const trailingSlash = ${JSON.stringify(!!ctx.opts.trailingSlash)};`);
+ c.push(`export const trailingSlash = ${JSON.stringify(!globalThis.__NO_TRAILING_SLASH__)};`);
c.push(`export const basePathname = ${JSON.stringify(ctx.opts.basePathname)};`);
diff --git a/packages/qwik-router/src/buildtime/types.ts b/packages/qwik-router/src/buildtime/types.ts
index 7f6473a11d8..ad505d19ca7 100644
--- a/packages/qwik-router/src/buildtime/types.ts
+++ b/packages/qwik-router/src/buildtime/types.ts
@@ -145,7 +145,7 @@ export interface MdxPlugins {
rehypeAutolinkHeadings: boolean;
}
-export interface NormalizedPluginOptions extends Required {
+export interface NormalizedPluginOptions extends Omit, 'trailingSlash'> {
assetsDir?: string;
}
diff --git a/packages/qwik-router/src/buildtime/vite/dev-server.ts b/packages/qwik-router/src/buildtime/vite/dev-server.ts
index a8d5abcc502..4b43545c0f9 100644
--- a/packages/qwik-router/src/buildtime/vite/dev-server.ts
+++ b/packages/qwik-router/src/buildtime/vite/dev-server.ts
@@ -44,7 +44,7 @@ export function ssrDevMiddleware(ctx: BuildContext, server: ViteDevServer) {
return { route, params };
}
- if (ctx.opts.trailingSlash && !pathname.endsWith('/')) {
+ if (!globalThis.__NO_TRAILING_SLASH__ && !pathname.endsWith('/')) {
params = matchRoute(route.pathname, pathname + '/');
if (params) {
return { route, params };
@@ -129,7 +129,7 @@ export function ssrDevMiddleware(ctx: BuildContext, server: ViteDevServer) {
return { serverPlugins, loadedRoute };
};
const resolveRoute = (routeModulePaths: WeakMap, string>, url: URL) => {
- const matchPathname = getRouteMatchPathname(url.pathname, ctx.opts.trailingSlash);
+ const matchPathname = getRouteMatchPathname(url.pathname);
routePs[matchPathname] ||= _resolveRoute(routeModulePaths, matchPathname).finally(() => {
delete routePs[matchPathname];
});
@@ -251,7 +251,6 @@ export function ssrDevMiddleware(ctx: BuildContext, server: ViteDevServer) {
loadedRoute,
requestHandlers,
rebuildRouteInfo,
- ctx.opts.trailingSlash,
ctx.opts.basePathname,
qwikSerializer
);
diff --git a/packages/qwik-router/src/buildtime/vite/plugin.ts b/packages/qwik-router/src/buildtime/vite/plugin.ts
index c28e83a8fca..4696082ef7c 100644
--- a/packages/qwik-router/src/buildtime/vite/plugin.ts
+++ b/packages/qwik-router/src/buildtime/vite/plugin.ts
@@ -71,6 +71,9 @@ function qwikRouterPlugin(userOpts?: QwikRouterVitePluginOptions): any {
type P = Plugin & { api: T };
+ let didEmitStaticPaths = false;
+ let didEmitNotFoundPaths = false;
+
const plugin: P = {
name: 'vite-plugin-qwik-router',
enforce: 'pre',
@@ -82,6 +85,7 @@ function qwikRouterPlugin(userOpts?: QwikRouterVitePluginOptions): any {
'globalThis.__DEFAULT_LOADERS_SERIALIZATION_STRATEGY__': JSON.stringify(
userOpts?.defaultLoadersSerializationStrategy || 'never'
),
+ 'globalThis.__NO_TRAILING_SLASH__': JSON.stringify(userOpts?.trailingSlash === false),
},
appType: 'custom',
resolve: {
@@ -147,6 +151,7 @@ function qwikRouterPlugin(userOpts?: QwikRouterVitePluginOptions): any {
},
configureServer(server) {
+ // this callback is run after the vite middlewares are registered
return () => {
if (!ctx) {
throw new Error('configureServer: Missing ctx from configResolved');
@@ -163,6 +168,8 @@ function qwikRouterPlugin(userOpts?: QwikRouterVitePluginOptions): any {
},
buildStart() {
+ didEmitStaticPaths = false;
+ didEmitNotFoundPaths = false;
resetBuildContext(ctx);
},
@@ -182,17 +189,29 @@ function qwikRouterPlugin(userOpts?: QwikRouterVitePluginOptions): any {
if (id === QWIK_ROUTER_SW_REGISTER) {
return join(rootDir!, id);
}
- if (id === STATIC_PATHS_ID) {
- return {
- id: './' + RESOLVED_STATIC_PATHS_ID,
- external: true,
- };
+ if (id.endsWith(STATIC_PATHS_ID)) {
+ const resolvedId = 'virtual:' + RESOLVED_STATIC_PATHS_ID;
+ if (!didEmitStaticPaths) {
+ this.emitFile({
+ type: 'chunk',
+ fileName: RESOLVED_STATIC_PATHS_ID,
+ id,
+ });
+ didEmitStaticPaths = true;
+ }
+ return { id: resolvedId };
}
- if (id === NOT_FOUND_PATHS_ID) {
- return {
- id: './' + RESOLVED_NOT_FOUND_PATHS_ID,
- external: true,
- };
+ if (id.endsWith(NOT_FOUND_PATHS_ID)) {
+ const resolvedId = 'virtual:' + RESOLVED_NOT_FOUND_PATHS_ID;
+ if (!didEmitNotFoundPaths) {
+ this.emitFile({
+ type: 'chunk',
+ fileName: RESOLVED_NOT_FOUND_PATHS_ID,
+ id,
+ });
+ didEmitNotFoundPaths = true;
+ }
+ return { id: resolvedId };
}
return null;
},
@@ -204,12 +223,11 @@ function qwikRouterPlugin(userOpts?: QwikRouterVitePluginOptions): any {
return generateQwikRouterEntries(ctx);
}
const isSerializer = id.endsWith(QWIK_SERIALIZER);
- const isRouterConfig = id.endsWith(QWIK_ROUTER_CONFIG_ID);
- const isSwRegister = id.endsWith(QWIK_ROUTER_SW_REGISTER);
-
if (isSerializer) {
return `export {_deserialize, _serialize, _verifySerializable} from '@qwik.dev/core'`;
}
+ const isRouterConfig = id.endsWith(QWIK_ROUTER_CONFIG_ID);
+ const isSwRegister = id.endsWith(QWIK_ROUTER_SW_REGISTER);
if (isRouterConfig || isSwRegister) {
if (!ctx.isDevServer && ctx.isDirty) {
await build(ctx);
@@ -231,6 +249,15 @@ function qwikRouterPlugin(userOpts?: QwikRouterVitePluginOptions): any {
}
}
}
+ // These files are overwritten in post-build.ts
+ const isStaticPaths = id.endsWith(RESOLVED_STATIC_PATHS_ID);
+ if (isStaticPaths) {
+ return `export const isStaticPath = () => false`;
+ }
+ const isNotFoundPathsId = id.endsWith(RESOLVED_NOT_FOUND_PATHS_ID);
+ if (isNotFoundPathsId) {
+ return `export const getNotFound = () => {}`;
+ }
return null;
},
diff --git a/packages/qwik-router/src/middleware/aws-lambda/index.ts b/packages/qwik-router/src/middleware/aws-lambda/index.ts
index 681a4218245..9d86e7cdac6 100644
--- a/packages/qwik-router/src/middleware/aws-lambda/index.ts
+++ b/packages/qwik-router/src/middleware/aws-lambda/index.ts
@@ -7,18 +7,17 @@ import type { ServerRenderOptions } from '@qwik.dev/router/middleware/request-ha
interface AwsOpt {
render: Render;
manifest?: QwikManifest;
- qwikRouterConfig: QwikRouterConfig;
- /** @deprecated Use `QwikRouterConfig` instead. Will be removed in V3 */
+ /** @deprecated Not used */
+ qwikRouterConfig?: QwikRouterConfig;
+ /** @deprecated Not used */
qwikCityPlan?: QwikCityPlan;
}
/** @public */
export function createQwikRouter(opts: AwsOpt) {
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
- console.warn('qwikCityPlan is deprecated. Use qwikRouterConfig instead.');
+ console.warn('qwikCityPlan is deprecated. Simply remove it.');
opts.qwikRouterConfig = opts.qwikCityPlan;
- } else if (!opts.qwikRouterConfig) {
- throw new Error('qwikRouterConfig is required.');
}
try {
const { router, staticFile, notFound } = createQwikRouterNode({
@@ -37,7 +36,7 @@ export function createQwikRouter(opts: AwsOpt) {
});
const fixPath = (pathT: string) => {
- if (opts.qwikRouterConfig.trailingSlash) {
+ if (!globalThis.__NO_TRAILING_SLASH__) {
const url = new URL(pathT, 'http://aws-qwik.local');
if (url.pathname.includes('.', url.pathname.lastIndexOf('/'))) {
return pathT;
diff --git a/packages/qwik-router/src/middleware/azure-swa/index.ts b/packages/qwik-router/src/middleware/azure-swa/index.ts
index acfdbcf07cb..43ef55198fa 100644
--- a/packages/qwik-router/src/middleware/azure-swa/index.ts
+++ b/packages/qwik-router/src/middleware/azure-swa/index.ts
@@ -51,10 +51,8 @@ interface AzureCookie {
/** @public */
export function createQwikRouter(opts: QwikRouterAzureOptions): AzureFunction {
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
- console.warn('qwikCityPlan is deprecated. Use qwikRouterConfig instead.');
+ console.warn('qwikCityPlan is deprecated. Simply remove it.');
opts.qwikRouterConfig = opts.qwikCityPlan;
- } else if (!opts.qwikRouterConfig) {
- throw new Error('qwikRouterConfig is required.');
}
const qwikSerializer: QwikSerializer = {
_deserialize,
diff --git a/packages/qwik-router/src/middleware/bun/index.ts b/packages/qwik-router/src/middleware/bun/index.ts
index cedb50e3833..f945d6a342a 100644
--- a/packages/qwik-router/src/middleware/bun/index.ts
+++ b/packages/qwik-router/src/middleware/bun/index.ts
@@ -19,10 +19,8 @@ import { MIME_TYPES } from '../request-handler/mime-types';
/** @public */
export function createQwikRouter(opts: QwikRouterBunOptions) {
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
- console.warn('qwikCityPlan is deprecated. Use qwikRouterConfig instead.');
+ console.warn('qwikCityPlan is deprecated. Simply remove it.');
opts.qwikRouterConfig = opts.qwikCityPlan;
- } else if (!opts.qwikRouterConfig) {
- throw new Error('qwikRouterConfig is required.');
}
// @qwik.dev/router/middleware/bun
// still missing from bun: last check was bun version 1.1.8
@@ -129,7 +127,7 @@ export function createQwikRouter(opts: QwikRouterBunOptions) {
let filePath: string;
if (fileName.includes('.')) {
filePath = join(staticFolder, pathname);
- } else if (opts.qwikRouterConfig!.trailingSlash) {
+ } else if (!globalThis.__NO_TRAILING_SLASH__) {
filePath = join(staticFolder, pathname + 'index.html');
} else {
filePath = join(staticFolder, pathname, 'index.html');
diff --git a/packages/qwik-router/src/middleware/cloudflare-pages/index.ts b/packages/qwik-router/src/middleware/cloudflare-pages/index.ts
index bcc5d92fa38..5b8bf8c2a89 100644
--- a/packages/qwik-router/src/middleware/cloudflare-pages/index.ts
+++ b/packages/qwik-router/src/middleware/cloudflare-pages/index.ts
@@ -17,17 +17,14 @@ import {
/** @public */
export function createQwikRouter(opts: QwikRouterCloudflarePagesOptions) {
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
- console.warn('qwikCityPlan is deprecated. Use qwikRouterConfig instead.');
+ console.warn('qwikCityPlan is deprecated. Simply remove it.');
opts.qwikRouterConfig = opts.qwikCityPlan;
- } else if (!opts.qwikRouterConfig) {
- throw new Error('qwikRouterConfig is required.');
}
try {
// https://developers.cloudflare.com/workers/configuration/compatibility-dates/#streams-constructors
// this will throw if CF compatibility_date < 2022-11-30
new globalThis.TextEncoderStream();
- } catch (e) {
- // @ts-ignore
+ } catch {
globalThis.TextEncoderStream = _TextEncoderStream_polyfill;
}
const qwikSerializer = { _deserialize, _serialize, _verifySerializable };
diff --git a/packages/qwik-router/src/middleware/deno/index.ts b/packages/qwik-router/src/middleware/deno/index.ts
index 147e15951e0..98851461ab3 100644
--- a/packages/qwik-router/src/middleware/deno/index.ts
+++ b/packages/qwik-router/src/middleware/deno/index.ts
@@ -30,10 +30,8 @@ export interface ServeHandlerInfo {
/** @public */
export function createQwikRouter(opts: QwikRouterDenoOptions) {
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
- console.warn('qwikCityPlan is deprecated. Use qwikRouterConfig instead.');
+ console.warn('qwikCityPlan is deprecated. Simply remove it.');
opts.qwikRouterConfig = opts.qwikCityPlan;
- } else if (!opts.qwikRouterConfig) {
- throw new Error('qwikRouterConfig is required.');
}
const qwikSerializer: QwikSerializer = {
_deserialize,
@@ -132,7 +130,7 @@ export function createQwikRouter(opts: QwikRouterDenoOptions) {
let filePath: string;
if (fileName.includes('.')) {
filePath = join(staticFolder, pathname);
- } else if (opts.qwikRouterConfig!.trailingSlash) {
+ } else if (!globalThis.__NO_TRAILING_SLASH__) {
filePath = join(staticFolder, pathname + 'index.html');
} else {
filePath = join(staticFolder, pathname, 'index.html');
diff --git a/packages/qwik-router/src/middleware/firebase/index.ts b/packages/qwik-router/src/middleware/firebase/index.ts
index 8580e5ccbf0..d51b0e514ce 100755
--- a/packages/qwik-router/src/middleware/firebase/index.ts
+++ b/packages/qwik-router/src/middleware/firebase/index.ts
@@ -5,10 +5,8 @@ import type { ServerRenderOptions } from '@qwik.dev/router/middleware/request-ha
/** @public */
export function createQwikRouter(opts: QwikRouterFirebaseOptions) {
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
- console.warn('qwikCityPlan is deprecated. Use qwikRouterConfig instead.');
+ console.warn('qwikCityPlan is deprecated. Simply remove it.');
opts.qwikRouterConfig = opts.qwikCityPlan;
- } else if (!opts.qwikRouterConfig) {
- throw new Error('qwikRouterConfig is required.');
}
const { staticFile, notFound, router } = createQwikRouterNode({
render: opts.render,
diff --git a/packages/qwik-router/src/middleware/netlify-edge/index.ts b/packages/qwik-router/src/middleware/netlify-edge/index.ts
index 758964073d2..00090db03a1 100644
--- a/packages/qwik-router/src/middleware/netlify-edge/index.ts
+++ b/packages/qwik-router/src/middleware/netlify-edge/index.ts
@@ -17,10 +17,8 @@ declare const Deno: any;
/** @public */
export function createQwikRouter(opts: QwikRouterNetlifyOptions) {
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
- console.warn('qwikCityPlan is deprecated. Use qwikRouterConfig instead.');
+ console.warn('qwikCityPlan is deprecated. Simply remove it.');
opts.qwikRouterConfig = opts.qwikCityPlan;
- } else if (!opts.qwikRouterConfig) {
- throw new Error('qwikRouterConfig is required.');
}
const qwikSerializer: QwikSerializer = {
_deserialize,
diff --git a/packages/qwik-router/src/middleware/node/index.ts b/packages/qwik-router/src/middleware/node/index.ts
index 87dca72cff6..377a2afac2d 100644
--- a/packages/qwik-router/src/middleware/node/index.ts
+++ b/packages/qwik-router/src/middleware/node/index.ts
@@ -18,10 +18,8 @@ import { computeOrigin, fromNodeHttp, getUrl } from './http';
/** @public */
export function createQwikRouter(opts: QwikRouterNodeRequestOptions | QwikCityNodeRequestOptions) {
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
- console.warn('qwikCityPlan is deprecated. Use qwikRouterConfig instead.');
+ console.warn('qwikCityPlan is deprecated. Simply remove it.');
opts.qwikRouterConfig = opts.qwikCityPlan;
- } else if (!opts.qwikRouterConfig) {
- throw new Error('qwikRouterConfig is required.');
}
const qwikSerializer: QwikSerializer = {
@@ -108,7 +106,7 @@ export function createQwikRouter(opts: QwikRouterNodeRequestOptions | QwikCityNo
let filePath: string;
if (basename(pathname).includes('.')) {
filePath = join(staticFolder, pathname);
- } else if (opts.qwikRouterConfig!.trailingSlash) {
+ } else if (!globalThis.__NO_TRAILING_SLASH__) {
filePath = join(staticFolder, pathname + 'index.html');
} else {
filePath = join(staticFolder, pathname, 'index.html');
diff --git a/packages/qwik-router/src/middleware/request-handler/middleware.request-handler.api.md b/packages/qwik-router/src/middleware/request-handler/middleware.request-handler.api.md
index 60f43ae05a9..45c2499bb7d 100644
--- a/packages/qwik-router/src/middleware/request-handler/middleware.request-handler.api.md
+++ b/packages/qwik-router/src/middleware/request-handler/middleware.request-handler.api.md
@@ -204,7 +204,7 @@ export interface ServerRenderOptions extends RenderOptions {
checkOrigin?: boolean;
// @deprecated (undocumented)
qwikCityPlan?: QwikCityPlan;
- // (undocumented)
+ // @deprecated (undocumented)
qwikRouterConfig?: QwikRouterConfig;
// (undocumented)
render: Render;
diff --git a/packages/qwik-router/src/middleware/request-handler/request-event.ts b/packages/qwik-router/src/middleware/request-handler/request-event.ts
index aea33e469d1..6744b25935c 100644
--- a/packages/qwik-router/src/middleware/request-handler/request-event.ts
+++ b/packages/qwik-router/src/middleware/request-handler/request-event.ts
@@ -37,7 +37,6 @@ export const RequestEvQwikSerializer = Symbol('RequestEvQwikSerializer');
export const RequestEvLoaderSerializationStrategyMap = Symbol(
'RequestEvLoaderSerializationStrategyMap'
);
-export const RequestEvTrailingSlash = Symbol('RequestEvTrailingSlash');
export const RequestRouteName = '@routeName';
export const RequestEvSharedActionId = '@actionId';
export const RequestEvSharedActionFormData = '@actionFormData';
@@ -51,7 +50,6 @@ export function createRequestEvent(
serverRequestEv: ServerRequestEvent,
loadedRoute: LoadedRoute | null,
requestHandlers: RequestHandler[],
- trailingSlash: boolean,
basePathname: string,
qwikSerializer: QwikSerializer,
resolved: (response: any) => void
@@ -64,7 +62,7 @@ export function createRequestEvent(
const url = new URL(request.url);
if (url.pathname.endsWith(QDATA_JSON)) {
url.pathname = url.pathname.slice(0, -QDATA_JSON_LEN);
- if (trailingSlash && !url.pathname.endsWith('/')) {
+ if (!globalThis.__NO_TRAILING_SLASH__ && !url.pathname.endsWith('/')) {
url.pathname += '/';
}
sharedMap.set(IsQData, true);
@@ -155,7 +153,6 @@ export function createRequestEvent(
[RequestEvLoaders]: loaders,
[RequestEvLoaderSerializationStrategyMap]: new Map(),
[RequestEvMode]: serverRequestEv.mode,
- [RequestEvTrailingSlash]: trailingSlash,
get [RequestEvRoute]() {
return loadedRoute;
},
@@ -339,7 +336,6 @@ export interface RequestEventInternal extends RequestEvent, RequestEventLoader {
[RequestEvLoaders]: Record | undefined>;
[RequestEvLoaderSerializationStrategyMap]: Map;
[RequestEvMode]: ServerRequestMode;
- [RequestEvTrailingSlash]: boolean;
[RequestEvRoute]: LoadedRoute | null;
[RequestEvQwikSerializer]: QwikSerializer;
@@ -372,10 +368,6 @@ export function getRequestLoaderSerializationStrategyMap(requestEv: RequestEvent
return (requestEv as RequestEventInternal)[RequestEvLoaderSerializationStrategyMap];
}
-export function getRequestTrailingSlash(requestEv: RequestEventCommon) {
- return (requestEv as RequestEventInternal)[RequestEvTrailingSlash];
-}
-
export function getRequestRoute(requestEv: RequestEventCommon) {
return (requestEv as RequestEventInternal)[RequestEvRoute];
}
diff --git a/packages/qwik-router/src/middleware/request-handler/request-handler.ts b/packages/qwik-router/src/middleware/request-handler/request-handler.ts
index d5d29c51daf..bd64cf6ff09 100644
--- a/packages/qwik-router/src/middleware/request-handler/request-handler.ts
+++ b/packages/qwik-router/src/middleware/request-handler/request-handler.ts
@@ -5,6 +5,11 @@ import { renderQwikMiddleware, resolveRequestHandlers } from './resolve-request-
import type { QwikSerializer, ServerRenderOptions, ServerRequestEvent } from './types';
import { getRouteMatchPathname, runQwikRouter, type QwikRouterRun } from './user-response';
+/**
+ * We need to delay importing the config until the first request, because vite also imports from
+ * this file and @qwik-router-config doesn't exist from the vite config before the build.
+ */
+let qwikRouterConfigActual: QwikRouterConfig;
/**
* The request handler for QwikRouter. Called by every integration.
*
@@ -15,13 +20,20 @@ export async function requestHandler(
opts: ServerRenderOptions,
qwikSerializer: QwikSerializer
): Promise | null> {
- const { render, qwikRouterConfig, checkOrigin } = opts;
+ const { render, checkOrigin } = opts;
+ let { qwikRouterConfig } = opts;
+ if (!qwikRouterConfig) {
+ if (!qwikRouterConfigActual) {
+ qwikRouterConfigActual = await import('@qwik-router-config');
+ }
+ qwikRouterConfig = qwikRouterConfigActual;
+ }
if (!qwikRouterConfig) {
throw new Error('qwikRouterConfig is required.');
}
const pathname = serverRequestEv.url.pathname;
- const matchPathname = getRouteMatchPathname(pathname, qwikRouterConfig.trailingSlash);
+ const matchPathname = getRouteMatchPathname(pathname);
const routeAndHandlers = await loadRequestHandlers(
qwikRouterConfig,
matchPathname,
@@ -34,7 +46,7 @@ export async function requestHandler(
const [route, requestHandlers] = routeAndHandlers;
const rebuildRouteInfo: RebuildRouteInfoInternal = async (url: URL) => {
- const matchPathname = getRouteMatchPathname(url.pathname, qwikRouterConfig.trailingSlash);
+ const matchPathname = getRouteMatchPathname(url.pathname);
const routeAndHandlers = await loadRequestHandlers(
qwikRouterConfig,
matchPathname,
@@ -56,7 +68,6 @@ export async function requestHandler(
route,
requestHandlers,
rebuildRouteInfo,
- qwikRouterConfig.trailingSlash,
qwikRouterConfig.basePathname,
qwikSerializer
);
diff --git a/packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.ts b/packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.ts
index f06d4cb0e4b..94396b91938 100644
--- a/packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.ts
+++ b/packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.ts
@@ -27,7 +27,6 @@ import {
getRequestLoaderSerializationStrategyMap,
getRequestLoaders,
getRequestMode,
- getRequestTrailingSlash,
type RequestEventInternal,
} from './request-event';
import { getQwikRouterServerData } from './response-page';
@@ -397,13 +396,12 @@ async function pureServerFunction(ev: RequestEvent) {
}
function fixTrailingSlash(ev: RequestEvent) {
- const trailingSlash = getRequestTrailingSlash(ev);
const { basePathname, originalUrl, sharedMap } = ev;
const { pathname, search } = originalUrl;
const isQData = sharedMap.has(IsQData);
if (!isQData && pathname !== basePathname && !pathname.endsWith('.html')) {
// only check for slash redirect on pages
- if (trailingSlash) {
+ if (!globalThis.__NO_TRAILING_SLASH__) {
// must have a trailing slash
if (!pathname.endsWith('/')) {
// add slash to existing pathname
@@ -442,12 +440,12 @@ export function isLastModulePageRoute(routeModules: RouteModule[]) {
return lastRouteModule && typeof (lastRouteModule as PageModule).default === 'function';
}
-export function getPathname(url: URL, trailingSlash: boolean | undefined) {
+export function getPathname(url: URL) {
url = new URL(url);
if (url.pathname.endsWith(QDATA_JSON)) {
url.pathname = url.pathname.slice(0, -QDATA_JSON.length);
}
- if (trailingSlash) {
+ if (!globalThis.__NO_TRAILING_SLASH__) {
if (!url.pathname.endsWith('/')) {
url.pathname += '/';
}
@@ -500,7 +498,6 @@ export function renderQwikMiddleware(render: Render) {
responseHeaders.set('Content-Type', 'text/html; charset=utf-8');
}
- const trailingSlash = getRequestTrailingSlash(requestEv);
const { readable, writable } = new TextEncoderStream();
const writableStream = requestEv.getWritableStream();
const pipe = readable.pipeTo(writableStream, { preventClose: true });
@@ -522,7 +519,7 @@ export function renderQwikMiddleware(render: Render) {
loaders: getRequestLoaders(requestEv),
action: requestEv.sharedMap.get(RequestEvSharedActionId),
status: status !== 200 ? status : 200,
- href: getPathname(requestEv.url, trailingSlash),
+ href: getPathname(requestEv.url),
};
if (typeof (result as any as RenderToStringResult).html === 'string') {
// render result used renderToString(), so none of it was streamed
@@ -587,7 +584,6 @@ export async function renderQData(requestEv: RequestEvent) {
const status = requestEv.status();
const redirectLocation = requestEv.headers.get('Location');
- const trailingSlash = getRequestTrailingSlash(requestEv);
const requestHeaders: Record = {};
requestEv.request.headers.forEach((value, key) => (requestHeaders[key] = value));
@@ -612,13 +608,13 @@ export async function renderQData(requestEv: RequestEvent) {
// send minimal data to the client
loaders,
status: status !== 200 ? status : 200,
- href: getPathname(requestEv.url, trailingSlash),
+ href: getPathname(requestEv.url),
}
: {
loaders,
action: requestEv.sharedMap.get(RequestEvSharedActionId),
status: status !== 200 ? status : 200,
- href: getPathname(requestEv.url, trailingSlash),
+ href: getPathname(requestEv.url),
redirect: redirectLocation ?? undefined,
isRewrite: requestEv.sharedMap.get(RequestEvIsRewrite),
};
diff --git a/packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.unit.ts b/packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.unit.ts
index ef3de3c1e0a..6fe6014964f 100644
--- a/packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.unit.ts
+++ b/packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.unit.ts
@@ -4,31 +4,31 @@ import { getPathname, isContentType } from './resolve-request-handlers';
describe('resolve-request-handler', () => {
describe('getPathname', () => {
it('should remove q-data.json', () => {
- expect(getPathname(new URL('http://server/path/q-data.json?foo=bar#hash'), true)).toBe(
+ globalThis.__NO_TRAILING_SLASH__ = false;
+ expect(getPathname(new URL('http://server/path/q-data.json?foo=bar#hash'))).toBe(
'/path/?foo=bar#hash'
);
- expect(getPathname(new URL('http://server/path/q-data.json?foo=bar#hash'), false)).toBe(
+ globalThis.__NO_TRAILING_SLASH__ = true;
+ expect(getPathname(new URL('http://server/path/q-data.json?foo=bar#hash'))).toBe(
'/path?foo=bar#hash'
);
});
it('should pass non q-data.json through', () => {
- expect(getPathname(new URL('http://server/path?foo=bar#hash'), true)).toBe(
- '/path/?foo=bar#hash'
- );
- expect(getPathname(new URL('http://server/path/?foo=bar#hash'), false)).toBe(
- '/path?foo=bar#hash'
- );
+ globalThis.__NO_TRAILING_SLASH__ = false;
+ expect(getPathname(new URL('http://server/path?foo=bar#hash'))).toBe('/path/?foo=bar#hash');
+ globalThis.__NO_TRAILING_SLASH__ = true;
+ expect(getPathname(new URL('http://server/path/?foo=bar#hash'))).toBe('/path?foo=bar#hash');
});
it('should remove internal search params', () => {
- expect(getPathname(new URL('http://server/path?qaction=123&qdata=data'), true)).toBe(
- '/path/'
- );
- expect(getPathname(new URL('http://server/path?foo=1&qfunc=f&bar=2'), false)).toBe(
+ globalThis.__NO_TRAILING_SLASH__ = false;
+ expect(getPathname(new URL('http://server/path?qaction=123&qdata=data'))).toBe('/path/');
+ globalThis.__NO_TRAILING_SLASH__ = true;
+ expect(getPathname(new URL('http://server/path?foo=1&qfunc=f&bar=2'))).toBe(
'/path?foo=1&bar=2'
);
- expect(getPathname(new URL('http://server/path?foo=1&qloaders=f&bar=2'), false)).toBe(
+ expect(getPathname(new URL('http://server/path?foo=1&qloaders=f&bar=2'))).toBe(
'/path?foo=1&bar=2'
);
});
diff --git a/packages/qwik-router/src/middleware/request-handler/types.ts b/packages/qwik-router/src/middleware/request-handler/types.ts
index 640249b16fa..97173a6a66f 100644
--- a/packages/qwik-router/src/middleware/request-handler/types.ts
+++ b/packages/qwik-router/src/middleware/request-handler/types.ts
@@ -48,9 +48,10 @@ export type ServerResponseHandler = (
export interface ServerRenderOptions extends RenderOptions {
render: Render;
- /** @deprecated Use `QwikRouterConfig` instead. Will be removed in V3 */
+ /** @deprecated Not used */
qwikCityPlan?: QwikCityPlan;
+ /** @deprecated Not used */
qwikRouterConfig?: QwikRouterConfig;
/**
* Protection against cross-site request forgery (CSRF) attacks.
diff --git a/packages/qwik-router/src/middleware/request-handler/user-response.ts b/packages/qwik-router/src/middleware/request-handler/user-response.ts
index e519c34de11..4656d146149 100644
--- a/packages/qwik-router/src/middleware/request-handler/user-response.ts
+++ b/packages/qwik-router/src/middleware/request-handler/user-response.ts
@@ -41,7 +41,6 @@ export function runQwikRouter(
loadedRoute: LoadedRoute | null,
requestHandlers: RequestHandler[],
rebuildRouteInfo: RebuildRouteInfoInternal,
- trailingSlash = true,
basePathname = '/',
qwikSerializer: QwikSerializer
): QwikRouterRun {
@@ -51,7 +50,6 @@ export function runQwikRouter(
serverRequestEv,
loadedRoute,
requestHandlers,
- trailingSlash,
basePathname,
qwikSerializer,
resolve!
@@ -144,9 +142,9 @@ async function runNext(
* The pathname used to match in the route regex array. A pathname ending with /q-data.json should
* be treated as a pathname without it.
*/
-export function getRouteMatchPathname(pathname: string, trailingSlash: boolean | undefined) {
+export function getRouteMatchPathname(pathname: string) {
if (pathname.endsWith(QDATA_JSON)) {
- const trimEnd = pathname.length - QDATA_JSON_LEN + (trailingSlash ? 1 : 0);
+ const trimEnd = pathname.length - QDATA_JSON_LEN + (globalThis.__NO_TRAILING_SLASH__ ? 0 : 1);
pathname = pathname.slice(0, trimEnd);
if (pathname === '') {
pathname = '/';
diff --git a/packages/qwik-router/src/middleware/vercel-edge/index.ts b/packages/qwik-router/src/middleware/vercel-edge/index.ts
index 3e492cbbbaa..186daa0fa9d 100644
--- a/packages/qwik-router/src/middleware/vercel-edge/index.ts
+++ b/packages/qwik-router/src/middleware/vercel-edge/index.ts
@@ -20,10 +20,8 @@ const BASE_URL = 'BASE_URL';
/** @public */
export function createQwikRouter(opts: QwikRouterVercelEdgeOptions) {
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
- console.warn('qwikCityPlan is deprecated. Use qwikRouterConfig instead.');
+ console.warn('qwikCityPlan is deprecated. Simply remove it.');
opts.qwikRouterConfig = opts.qwikCityPlan;
- } else if (!opts.qwikRouterConfig) {
- throw new Error('qwikRouterConfig is required.');
}
const qwikSerializer: QwikSerializer = {
_deserialize,
diff --git a/packages/qwik-router/src/runtime/src/qwik-router-component.tsx b/packages/qwik-router/src/runtime/src/qwik-router-component.tsx
index 3ec51f06bc3..198c2a7f9ef 100644
--- a/packages/qwik-router/src/runtime/src/qwik-router-component.tsx
+++ b/packages/qwik-router/src/runtime/src/qwik-router-component.tsx
@@ -419,10 +419,10 @@ export const QwikRouterProvider = component$((props) => {
// ensure correct trailing slash
if (trackUrl.pathname.endsWith('/')) {
- if (!qwikRouterConfig.trailingSlash) {
+ if (globalThis.__NO_TRAILING_SLASH__) {
trackUrl.pathname = trackUrl.pathname.slice(0, -1);
}
- } else if (qwikRouterConfig.trailingSlash) {
+ } else if (!globalThis.__NO_TRAILING_SLASH__) {
trackUrl.pathname += '/';
}
let loadRoutePromise = loadRoute(
diff --git a/packages/qwik-router/src/runtime/src/qwik-router-config.ts b/packages/qwik-router/src/runtime/src/qwik-router-config.ts
index be9509c4b75..ca5c0487cea 100644
--- a/packages/qwik-router/src/runtime/src/qwik-router-config.ts
+++ b/packages/qwik-router/src/runtime/src/qwik-router-config.ts
@@ -4,7 +4,7 @@ import type { MenuData, RouteData, RouteModule } from './types';
export const routes: RouteData[] = [];
export const menus: MenuData[] = [];
export const serverPlugins: RouteModule[] = [];
-export const trailingSlash = false;
+export const trailingSlash = !globalThis.__NO_TRAILING_SLASH__;
export const basePathname = '/';
export const cacheModules = false;
diff --git a/packages/qwik-router/src/static/api-extractor.json b/packages/qwik-router/src/ssg/api-extractor.json
similarity index 64%
rename from packages/qwik-router/src/static/api-extractor.json
rename to packages/qwik-router/src/ssg/api-extractor.json
index b33eb2ebb8e..54855628a27 100644
--- a/packages/qwik-router/src/static/api-extractor.json
+++ b/packages/qwik-router/src/ssg/api-extractor.json
@@ -1,20 +1,20 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"extends": "../api-extractor.json",
- "mainEntryPointFilePath": "/../../dist-dev/dts-out/packages/qwik-router/src/static/index.d.ts",
+ "mainEntryPointFilePath": "/../../dist-dev/dts-out/packages/qwik-router/src/ssg/index.d.ts",
"newlineKind": "lf",
"apiReport": {
"enabled": true,
- "reportFileName": "qwik-router.static",
- "reportFolder": "/src/static/",
- "reportTempFolder": "/../../dist-dev/api-extractor/qwik-router/static"
+ "reportFileName": "qwik-router.ssg",
+ "reportFolder": "/src/ssg/",
+ "reportTempFolder": "/../../dist-dev/api-extractor/qwik-router/ssg"
},
"dtsRollup": {
"enabled": true,
- "untrimmedFilePath": "/lib/static/index.d.ts"
+ "untrimmedFilePath": "/lib/ssg/index.d.ts"
},
"docModel": {
"enabled": true,
- "apiJsonFilePath": "/../../dist-dev/api/qwik-router/static/docs.api.json"
+ "apiJsonFilePath": "/../../dist-dev/api/qwik-router/ssg/docs.api.json"
}
}
diff --git a/packages/qwik-router/src/ssg/deno/index.ts b/packages/qwik-router/src/ssg/deno/index.ts
new file mode 100644
index 00000000000..caf758da9f6
--- /dev/null
+++ b/packages/qwik-router/src/ssg/deno/index.ts
@@ -0,0 +1,8 @@
+import type { SsgOptions } from '../types';
+
+export async function generate(_opts: SsgOptions) {
+ console.error(`Deno not implemented`);
+ Deno.exit(1);
+}
+
+declare const Deno: any;
diff --git a/packages/qwik-router/src/static/extract-params.ts b/packages/qwik-router/src/ssg/extract-params.ts
similarity index 100%
rename from packages/qwik-router/src/static/extract-params.ts
rename to packages/qwik-router/src/ssg/extract-params.ts
diff --git a/packages/qwik-router/src/static/extract-params.unit.ts b/packages/qwik-router/src/ssg/extract-params.unit.ts
similarity index 100%
rename from packages/qwik-router/src/static/extract-params.unit.ts
rename to packages/qwik-router/src/ssg/extract-params.unit.ts
diff --git a/packages/qwik-router/src/static/index.ts b/packages/qwik-router/src/ssg/index.ts
similarity index 74%
rename from packages/qwik-router/src/static/index.ts
rename to packages/qwik-router/src/ssg/index.ts
index 046d1069e10..4bdcc82a8ea 100644
--- a/packages/qwik-router/src/static/index.ts
+++ b/packages/qwik-router/src/ssg/index.ts
@@ -1,10 +1,6 @@
-import type {
- StaticGenerateOptions,
- StaticGenerateRenderOptions,
- StaticGenerateResult,
-} from './types';
+import type { SsgOptions, SsgRenderOptions, SsgResult } from './types';
-// @qwik.dev/router/static
+// @qwik.dev/router/ssg
/**
* Use this function when SSG should be generated from another module, such as a Vite plugin. This
@@ -12,13 +8,17 @@ import type {
*
* @public
*/
-export async function generate(opts: StaticGenerateOptions) {
+export async function generate(opts: SsgOptions) {
const ssgPlatform = await getEntryModule();
- const result: StaticGenerateResult = await ssgPlatform.generate(opts);
+ const result: SsgResult = await ssgPlatform.generate(opts);
return result;
}
-export type { StaticGenerateOptions, StaticGenerateRenderOptions, StaticGenerateResult };
+export type {
+ SsgOptions as StaticGenerateOptions,
+ SsgRenderOptions,
+ SsgResult as StaticGenerateResult,
+};
function getEntryModulePath() {
if (isDeno()) {
diff --git a/packages/qwik-router/src/static/main-thread.ts b/packages/qwik-router/src/ssg/main-thread.ts
similarity index 95%
rename from packages/qwik-router/src/static/main-thread.ts
rename to packages/qwik-router/src/ssg/main-thread.ts
index a6e31c18e5c..0b9f93d50ef 100644
--- a/packages/qwik-router/src/static/main-thread.ts
+++ b/packages/qwik-router/src/ssg/main-thread.ts
@@ -9,7 +9,7 @@ import { getPathnameForDynamicRoute } from '../utils/pathname';
import { extractParamNames } from './extract-params';
import { generateNotFoundPages } from './not-found';
import { createRouteTester } from './routes';
-import type { StaticGenerateOptions, StaticGenerateResult, StaticRoute, System } from './types';
+import type { SsgOptions, SsgResult, SsgRoute, System } from './types';
export async function mainThread(sys: System) {
const opts = sys.getOptions();
@@ -23,16 +23,16 @@ export async function mainThread(sys: System) {
await import(pathToFileURL(opts.qwikRouterConfigModulePath).href)
).default;
- const queue: StaticRoute[] = [];
+ const queue: SsgRoute[] = [];
const active = new Set();
const routes = qwikRouterConfig.routes || [];
const trailingSlash = !!qwikRouterConfig.trailingSlash;
const includeRoute = createRouteTester(opts.basePathname || '/', opts.include, opts.exclude);
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, reject) => {
try {
const timer = sys.createTimer();
- const generatorResult: StaticGenerateResult = {
+ const generatorResult: SsgResult = {
duration: 0,
rendered: 0,
errors: 0,
@@ -102,7 +102,7 @@ export async function mainThread(sys: System) {
}
};
- const render = async (staticRoute: StaticRoute) => {
+ const render = async (staticRoute: SsgRoute) => {
try {
active.add(staticRoute.pathname);
@@ -224,7 +224,7 @@ export async function mainThread(sys: System) {
});
}
-function validateOptions(opts: StaticGenerateOptions) {
+function validateOptions(opts: SsgOptions) {
if (!opts.qwikRouterConfigModulePath) {
if (!opts.qwikCityPlanModulePath) {
throw new Error(`Missing "qwikRouterConfigModulePath" option`);
diff --git a/packages/qwik-router/src/static/node/index.ts b/packages/qwik-router/src/ssg/node/index.ts
similarity index 83%
rename from packages/qwik-router/src/static/node/index.ts
rename to packages/qwik-router/src/ssg/node/index.ts
index 4f31e3ab603..eab5c8d798f 100644
--- a/packages/qwik-router/src/static/node/index.ts
+++ b/packages/qwik-router/src/ssg/node/index.ts
@@ -1,10 +1,10 @@
-import type { StaticGenerateOptions } from '../types';
+import type { SsgOptions } from '../types';
import { createSystem } from './node-system';
import { isMainThread, workerData } from 'node:worker_threads';
import { mainThread } from '../main-thread';
import { workerThread } from '../worker-thread';
-export async function generate(opts: StaticGenerateOptions) {
+export async function generate(opts: SsgOptions) {
if (isMainThread) {
const sys = await createSystem(opts);
const result = await mainThread(sys);
diff --git a/packages/qwik-router/src/static/node/node-main.ts b/packages/qwik-router/src/ssg/node/node-main.ts
similarity index 90%
rename from packages/qwik-router/src/static/node/node-main.ts
rename to packages/qwik-router/src/ssg/node/node-main.ts
index 4bf079ba0b6..88e4c89cd63 100644
--- a/packages/qwik-router/src/static/node/node-main.ts
+++ b/packages/qwik-router/src/ssg/node/node-main.ts
@@ -1,8 +1,8 @@
import type {
MainContext,
- StaticGenerateOptions,
- StaticRoute,
- StaticWorkerRenderResult,
+ SsgOptions,
+ SsgRoute,
+ SsgWorkerRenderResult,
WorkerOutputMessage,
WorkerInputMessage,
System,
@@ -15,8 +15,8 @@ import { ensureDir } from './node-system';
import { normalizePath } from '../../utils/fs';
import { createSingleThreadWorker } from '../worker-thread';
-export async function createNodeMainProcess(sys: System, opts: StaticGenerateOptions) {
- const ssgWorkers: StaticGeneratorWorker[] = [];
+export async function createNodeMainProcess(sys: System, opts: SsgOptions) {
+ const ssgWorkers: SsgWorker[] = [];
const sitemapBuffer: string[] = [];
let sitemapPromise: Promise | null = null;
@@ -56,7 +56,7 @@ export async function createNodeMainProcess(sys: System, opts: StaticGenerateOpt
const createWorker = (workerIndex: number) => {
if (workerIndex === 0) {
// same thread worker, don't start a new process
- const ssgSameThreadWorker: StaticGeneratorWorker = {
+ const ssgSameThreadWorker: SsgWorker = {
activeTasks: 0,
totalTasks: 0,
@@ -90,7 +90,7 @@ export async function createNodeMainProcess(sys: System, opts: StaticGenerateOpt
const nodeWorker = new Worker(workerFilePath, { workerData: opts });
- const ssgWorker: StaticGeneratorWorker = {
+ const ssgWorker: SsgWorker = {
activeTasks: 0,
totalTasks: 0,
@@ -161,10 +161,10 @@ export async function createNodeMainProcess(sys: System, opts: StaticGenerateOpt
return ssgWorker.activeTasks < maxTasksPerWorker;
};
- const render = async (staticRoute: StaticRoute) => {
+ const render = async (ssgRoute: SsgRoute) => {
const ssgWorker = getNextWorker();
- const result = await ssgWorker.render(staticRoute);
+ const result = await ssgWorker.render(ssgRoute);
if (sitemapOutFile && result.ok && result.resourceType === 'page') {
sitemapBuffer.push(`${result.url}`);
@@ -226,7 +226,7 @@ export async function createNodeMainProcess(sys: System, opts: StaticGenerateOpt
return mainCtx;
}
-function ssgWorkerCompare(a: StaticGeneratorWorker, b: StaticGeneratorWorker) {
+function ssgWorkerCompare(a: SsgWorker, b: SsgWorker) {
if (a.activeTasks < b.activeTasks) {
return -1;
}
@@ -236,11 +236,11 @@ function ssgWorkerCompare(a: StaticGeneratorWorker, b: StaticGeneratorWorker) {
return a.totalTasks < b.totalTasks ? -1 : 1;
}
-type WorkerMainTask = (result: StaticWorkerRenderResult) => void;
+type WorkerMainTask = (result: SsgWorkerRenderResult) => void;
-interface StaticGeneratorWorker {
+interface SsgWorker {
activeTasks: number;
totalTasks: number;
- render: (staticRoute: StaticRoute) => Promise;
+ render: (staticRoute: SsgRoute) => Promise;
terminate: () => Promise;
}
diff --git a/packages/qwik-router/src/static/node/node-system.ts b/packages/qwik-router/src/ssg/node/node-system.ts
similarity index 95%
rename from packages/qwik-router/src/static/node/node-system.ts
rename to packages/qwik-router/src/ssg/node/node-system.ts
index df138924232..79699dae295 100644
--- a/packages/qwik-router/src/static/node/node-system.ts
+++ b/packages/qwik-router/src/ssg/node/node-system.ts
@@ -1,5 +1,5 @@
/* eslint-disable no-console */
-import type { StaticGenerateOptions, System } from '../types';
+import type { SsgOptions, System } from '../types';
import fs from 'node:fs';
import { dirname, join } from 'node:path';
import { createNodeMainProcess } from './node-main';
@@ -7,7 +7,7 @@ import { createNodeWorkerProcess } from './node-worker';
import { normalizePath } from '../../utils/fs';
/** @public */
-export async function createSystem(opts: StaticGenerateOptions) {
+export async function createSystem(opts: SsgOptions) {
const createWriteStream = (filePath: string) => {
return fs.createWriteStream(filePath, {
flags: 'w',
diff --git a/packages/qwik-router/src/static/node/node-worker.ts b/packages/qwik-router/src/ssg/node/node-worker.ts
similarity index 100%
rename from packages/qwik-router/src/static/node/node-worker.ts
rename to packages/qwik-router/src/ssg/node/node-worker.ts
diff --git a/packages/qwik-router/src/static/not-found.ts b/packages/qwik-router/src/ssg/not-found.ts
similarity index 82%
rename from packages/qwik-router/src/static/not-found.ts
rename to packages/qwik-router/src/ssg/not-found.ts
index d29a7dc2ee1..7738ecede4c 100644
--- a/packages/qwik-router/src/static/not-found.ts
+++ b/packages/qwik-router/src/ssg/not-found.ts
@@ -1,13 +1,9 @@
import type { RouteData } from '@qwik.dev/router';
import { getErrorHtml } from '@qwik.dev/router/middleware/request-handler';
-import type { StaticGenerateOptions, System } from './types';
+import type { SsgOptions, System } from './types';
import { RouteDataProp } from '../runtime/src/types';
-export async function generateNotFoundPages(
- sys: System,
- opts: StaticGenerateOptions,
- routes: RouteData[]
-) {
+export async function generateNotFoundPages(sys: System, opts: SsgOptions, routes: RouteData[]) {
if (opts.emit404Pages !== false) {
const basePathname = opts.basePathname || '/';
const rootNotFoundPathname = basePathname + '404.html';
diff --git a/packages/qwik-router/src/static/qwik-router.static.api.md b/packages/qwik-router/src/ssg/qwik-router.ssg.api.md
similarity index 88%
rename from packages/qwik-router/src/static/qwik-router.static.api.md
rename to packages/qwik-router/src/ssg/qwik-router.ssg.api.md
index d2f73332020..4d021772202 100644
--- a/packages/qwik-router/src/static/qwik-router.static.api.md
+++ b/packages/qwik-router/src/ssg/qwik-router.ssg.api.md
@@ -10,18 +10,7 @@ import type { RenderOptions } from '@qwik.dev/core/server';
export function generate(opts: StaticGenerateOptions): Promise;
// @public (undocumented)
-export interface StaticGenerateOptions extends StaticGenerateRenderOptions {
- basePathname?: string;
- // @deprecated (undocumented)
- qwikCityPlanModulePath?: string;
- qwikRouterConfigModulePath: string;
- renderModulePath: string;
- // (undocumented)
- rootDir?: string;
-}
-
-// @public (undocumented)
-export interface StaticGenerateRenderOptions extends RenderOptions {
+export interface SsgRenderOptions extends RenderOptions {
emit404Pages?: boolean;
emitData?: boolean;
emitHtml?: boolean;
@@ -35,6 +24,17 @@ export interface StaticGenerateRenderOptions extends RenderOptions {
sitemapOutFile?: string | null;
}
+// @public (undocumented)
+export interface StaticGenerateOptions extends SsgRenderOptions {
+ basePathname?: string;
+ // @deprecated (undocumented)
+ qwikCityPlanModulePath?: string;
+ qwikRouterConfigModulePath: string;
+ renderModulePath: string;
+ // (undocumented)
+ rootDir?: string;
+}
+
// @public (undocumented)
export interface StaticGenerateResult {
// (undocumented)
diff --git a/packages/qwik-router/src/static/routes.ts b/packages/qwik-router/src/ssg/routes.ts
similarity index 100%
rename from packages/qwik-router/src/static/routes.ts
rename to packages/qwik-router/src/ssg/routes.ts
diff --git a/packages/qwik-router/src/static/types.ts b/packages/qwik-router/src/ssg/types.ts
similarity index 87%
rename from packages/qwik-router/src/static/types.ts
rename to packages/qwik-router/src/ssg/types.ts
index 65f6e21acc5..0b616b68f09 100644
--- a/packages/qwik-router/src/static/types.ts
+++ b/packages/qwik-router/src/ssg/types.ts
@@ -8,7 +8,7 @@ export interface System {
onMessage: (msg: WorkerInputMessage) => Promise
) => void;
createLogger: () => Promise;
- getOptions: () => StaticGenerateOptions;
+ getOptions: () => SsgOptions;
ensureDir: (filePath: string) => Promise;
access: (path: string) => Promise;
createWriteStream: (filePath: string) => StaticStreamWriter;
@@ -27,7 +27,7 @@ export interface StaticStreamWriter extends StreamWriter {
export interface MainContext {
hasAvailableWorker: () => boolean;
- render: (staticRoute: StaticRenderInput) => Promise;
+ render: (staticRoute: SsgRenderInput) => Promise;
close: () => Promise;
}
@@ -38,7 +38,7 @@ export interface Logger {
}
/** @public */
-export interface StaticGenerateRenderOptions extends RenderOptions {
+export interface SsgRenderOptions extends RenderOptions {
/** File system directory where the static files should be written. */
outDir: string;
/**
@@ -99,7 +99,7 @@ export interface StaticGenerateRenderOptions extends RenderOptions {
}
/** @public */
-export interface StaticGenerateOptions extends StaticGenerateRenderOptions {
+export interface SsgOptions extends SsgRenderOptions {
/**
* Path to the SSR module exporting the default render function. In most cases it'll be
* `./src/entry.ssr.tsx`.
@@ -115,19 +115,17 @@ export interface StaticGenerateOptions extends StaticGenerateRenderOptions {
rootDir?: string;
}
-export interface StaticGenerateHandlerOptions
- extends StaticGenerateRenderOptions,
- ServerRenderOptions {}
+export interface SsgHandlerOptions extends SsgRenderOptions, ServerRenderOptions {}
-export type WorkerInputMessage = StaticRenderInput | WorkerCloseMessage;
+export type WorkerInputMessage = SsgRenderInput | WorkerCloseMessage;
-export type WorkerOutputMessage = StaticWorkerRenderResult | WorkerCloseMessage;
+export type WorkerOutputMessage = SsgWorkerRenderResult | WorkerCloseMessage;
-export interface StaticRenderInput extends StaticRoute {
+export interface SsgRenderInput extends SsgRoute {
type: 'render';
}
-export interface StaticRoute {
+export interface SsgRoute {
pathname: string;
params: Record | undefined;
}
@@ -136,7 +134,7 @@ export interface WorkerCloseMessage {
type: 'close';
}
-export interface StaticWorkerRenderResult {
+export interface SsgWorkerRenderResult {
type: 'render';
pathname: string;
url: string;
@@ -148,7 +146,7 @@ export interface StaticWorkerRenderResult {
}
/** @public */
-export interface StaticGenerateResult {
+export interface SsgResult {
duration: number;
rendered: number;
errors: number;
diff --git a/packages/qwik-router/src/static/worker-thread.ts b/packages/qwik-router/src/ssg/worker-thread.ts
similarity index 94%
rename from packages/qwik-router/src/static/worker-thread.ts
rename to packages/qwik-router/src/ssg/worker-thread.ts
index 497ea2dfb53..884a85b1ae3 100644
--- a/packages/qwik-router/src/static/worker-thread.ts
+++ b/packages/qwik-router/src/ssg/worker-thread.ts
@@ -6,10 +6,10 @@ import { pathToFileURL } from 'node:url';
import type { QwikSerializer } from '../middleware/request-handler/types';
import type { ClientPageData } from '../runtime/src/types';
import type {
- StaticGenerateHandlerOptions,
- StaticRoute,
+ SsgHandlerOptions,
+ SsgRoute,
StaticStreamWriter,
- StaticWorkerRenderResult,
+ SsgWorkerRenderResult,
System,
} from './types';
@@ -17,7 +17,7 @@ export async function workerThread(sys: System) {
const ssgOpts = sys.getOptions();
const pendingPromises = new Set>();
- const opts: StaticGenerateHandlerOptions = {
+ const opts: SsgHandlerOptions = {
...ssgOpts,
render: (await import(pathToFileURL(ssgOpts.renderModulePath).href)).default,
qwikRouterConfig: (await import(pathToFileURL(ssgOpts.qwikRouterConfigModulePath).href))
@@ -27,7 +27,7 @@ export async function workerThread(sys: System) {
sys.createWorkerProcess(async (msg) => {
switch (msg.type) {
case 'render': {
- return new Promise((resolve) => {
+ return new Promise((resolve) => {
workerRender(sys, opts, msg, pendingPromises, resolve);
});
}
@@ -45,15 +45,15 @@ export async function createSingleThreadWorker(sys: System) {
const ssgOpts = sys.getOptions();
const pendingPromises = new Set>();
- const opts: StaticGenerateHandlerOptions = {
+ const opts: SsgHandlerOptions = {
...ssgOpts,
render: (await import(pathToFileURL(ssgOpts.renderModulePath).href)).default,
qwikRouterConfig: (await import(pathToFileURL(ssgOpts.qwikRouterConfigModulePath).href))
.default,
};
- return (staticRoute: StaticRoute) => {
- return new Promise((resolve) => {
+ return (staticRoute: SsgRoute) => {
+ return new Promise((resolve) => {
workerRender(sys, opts, staticRoute, pendingPromises, resolve);
});
};
@@ -61,10 +61,10 @@ export async function createSingleThreadWorker(sys: System) {
async function workerRender(
sys: System,
- opts: StaticGenerateHandlerOptions,
- staticRoute: StaticRoute,
+ opts: SsgHandlerOptions,
+ staticRoute: SsgRoute,
pendingPromises: Set>,
- callback: (result: StaticWorkerRenderResult) => void
+ callback: (result: SsgWorkerRenderResult) => void
) {
const qwikSerializer: QwikSerializer = {
_deserialize,
@@ -74,7 +74,7 @@ async function workerRender(
// pathname and origin already normalized at this point
const url = new URL(staticRoute.pathname, opts.origin);
- const result: StaticWorkerRenderResult = {
+ const result: SsgWorkerRenderResult = {
type: 'render',
pathname: staticRoute.pathname,
url: url.href,
diff --git a/packages/qwik-router/src/static/deno/index.ts b/packages/qwik-router/src/static/deno/index.ts
deleted file mode 100644
index 1c62f3b6972..00000000000
--- a/packages/qwik-router/src/static/deno/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { StaticGenerateOptions } from '../types';
-
-export async function generate(_opts: StaticGenerateOptions) {
- console.error(`Deno not implemented`);
- Deno.exit(1);
-}
-
-declare const Deno: any;
diff --git a/packages/qwik-router/src/utils/fs.ts b/packages/qwik-router/src/utils/fs.ts
index c4bbb59af46..4ee726f340c 100644
--- a/packages/qwik-router/src/utils/fs.ts
+++ b/packages/qwik-router/src/utils/fs.ts
@@ -28,7 +28,7 @@ export function getPathnameFromDirPath(opts: NormalizedPluginOptions, dirPath: s
// ensure file system path uses / (POSIX) instead of \\ (windows)
let pathname = normalizePath(relFilePath);
- pathname = normalizePathname(pathname, opts.basePathname, opts.trailingSlash)!
+ pathname = normalizePathname(pathname, opts.basePathname)!
.split('/')
// remove grouped layout segments
.filter((segment) => !isGroupedLayoutName(segment))
@@ -42,7 +42,11 @@ export function getPathnameFromDirPath(opts: NormalizedPluginOptions, dirPath: s
export function getMenuPathname(opts: NormalizedPluginOptions, filePath: string) {
let pathname = normalizePath(relative(opts.routesDir, filePath));
pathname = `/` + normalizePath(dirname(pathname));
- return normalizePathname(pathname, opts.basePathname, true)!;
+ let result = normalizePathname(pathname, opts.basePathname)!;
+ if (!result.endsWith('/')) {
+ result += '/';
+ }
+ return result;
}
export function getExtension(fileName: string) {
diff --git a/packages/qwik-router/src/utils/fs.unit.ts b/packages/qwik-router/src/utils/fs.unit.ts
index ade081e51c3..f69e52124b2 100644
--- a/packages/qwik-router/src/utils/fs.unit.ts
+++ b/packages/qwik-router/src/utils/fs.unit.ts
@@ -256,7 +256,6 @@ test('createFileId, Menu', () => {
routesDir,
serverPluginsDir,
basePathname: t.basePathname,
- trailingSlash: t.trailingSlash,
mdxPlugins: {
remarkGfm: true,
rehypeSyntaxHighlight: true,
@@ -267,6 +266,7 @@ test('createFileId, Menu', () => {
rewriteRoutes: [],
defaultLoadersSerializationStrategy: 'never',
};
+ globalThis.__NO_TRAILING_SLASH__ = !t.trailingSlash;
const pathname = getPathnameFromDirPath(opts, t.dirPath);
assert.equal(pathname, t.expect, t.dirPath);
});
@@ -358,7 +358,6 @@ test('parseRouteIndexName', () => {
routesDir,
serverPluginsDir,
basePathname: t.basePathname,
- trailingSlash: t.trailingSlash,
mdxPlugins: {
remarkGfm: true,
rehypeSyntaxHighlight: true,
@@ -369,6 +368,7 @@ test('parseRouteIndexName', () => {
rewriteRoutes: [],
defaultLoadersSerializationStrategy: 'never',
};
+ globalThis.__NO_TRAILING_SLASH__ = !t.trailingSlash;
const pathname = getMenuPathname(opts, t.filePath);
assert.equal(pathname, t.expect);
});
diff --git a/packages/qwik-router/src/utils/pathname.ts b/packages/qwik-router/src/utils/pathname.ts
index 5fd688a1db3..42925235baf 100644
--- a/packages/qwik-router/src/utils/pathname.ts
+++ b/packages/qwik-router/src/utils/pathname.ts
@@ -1,10 +1,6 @@
import type { PathParams } from '../runtime/src';
-export function normalizePathname(
- pathname: string | undefined | null,
- basePathname: string,
- trailingSlash: boolean
-) {
+export function normalizePathname(pathname: string | undefined | null, basePathname: string) {
if (typeof pathname === 'string') {
pathname = pathname.trim();
@@ -22,7 +18,7 @@ export function normalizePathname(
pathname = new URL(basePathname + pathname, `https://qwik.dev`).pathname;
if (pathname !== basePathname) {
- if (trailingSlash) {
+ if (!globalThis.__NO_TRAILING_SLASH__) {
if (!pathname.endsWith('/')) {
const segments = pathname.split('/');
const lastSegment = segments[segments.length - 1];
diff --git a/packages/qwik-router/src/utils/pathname.unit.ts b/packages/qwik-router/src/utils/pathname.unit.ts
index 9d497012070..b31fc6808a0 100644
--- a/packages/qwik-router/src/utils/pathname.unit.ts
+++ b/packages/qwik-router/src/utils/pathname.unit.ts
@@ -115,7 +115,9 @@ test('normalizePathname', () => {
];
tests.forEach((t) => {
- const pathname = normalizePathname(t.pathname, t.basePathname, t.trailingSlash);
+ globalThis.__NO_TRAILING_SLASH__ = !t.trailingSlash;
+ const pathname = normalizePathname(t.pathname, t.basePathname);
+
assert.equal(pathname, t.expect);
});
});
@@ -179,5 +181,5 @@ test('dynamic pathname', () => {
function getPathname(t: { originalPathname: string; basePathname: string; params?: PathParams }) {
const p = parseRoutePathname(t.basePathname, t.originalPathname);
const d = getPathnameForDynamicRoute(t.originalPathname, p.paramNames, t.params);
- return normalizePathname(d, '/', false);
+ return normalizePathname(d, '/');
}
diff --git a/packages/qwik-router/ssg.d.ts b/packages/qwik-router/ssg.d.ts
new file mode 100644
index 00000000000..00861d96fd8
--- /dev/null
+++ b/packages/qwik-router/ssg.d.ts
@@ -0,0 +1,2 @@
+// re-export for typescript in old resolution mode
+export * from './lib/ssg';
diff --git a/packages/qwik-router/static.d.ts b/packages/qwik-router/static.d.ts
index b61c4bfedaa..00861d96fd8 100644
--- a/packages/qwik-router/static.d.ts
+++ b/packages/qwik-router/static.d.ts
@@ -1,2 +1,2 @@
// re-export for typescript in old resolution mode
-export * from './lib/static';
+export * from './lib/ssg';
diff --git a/packages/qwik-router/tsconfig.json b/packages/qwik-router/tsconfig.json
index a60aee6ff5b..8e931a3c81d 100644
--- a/packages/qwik-router/tsconfig.json
+++ b/packages/qwik-router/tsconfig.json
@@ -21,9 +21,7 @@
"@qwik.dev/router/adapters/shared/vite": [
"packages/qwik-router/src/adapters/shared/vite/index.ts"
],
- "@qwik.dev/router/adapters/static/vite": [
- "packages/qwik-router/src/adapters/static/vite/index.ts"
- ],
+ "@qwik.dev/router/adapters/ssg/vite": ["packages/qwik-router/src/adapters/ssg/vite/index.ts"],
"@qwik.dev/router/middleware/azure-swa": ["packages/qwik-router/src/middleware/azure-swa"],
"@qwik.dev/router/middleware/aws-lambda": ["packages/qwik-router/src/middleware/aws-lambda"],
"@qwik.dev/router/middleware/cloudflare-pages": [
@@ -36,7 +34,7 @@
"@qwik.dev/router/middleware/netlify-edge": [
"packages/qwik-router/src/middleware/netlify-edge"
],
- "@qwik.dev/router/static": ["packages/qwik-router/src/static"],
+ "@qwik.dev/router/ssg": ["packages/qwik-router/src/ssg"],
"@qwik.dev/router/vite": ["packages/qwik-router/src/buildtime/vite"],
"@qwik-router-config": ["packages/qwik-router/src/runtime/src/qwik-router-config.ts"],
diff --git a/packages/qwik/src/optimizer/src/index.ts b/packages/qwik/src/optimizer/src/index.ts
index 55bd8c0e25e..88f0af0a6cd 100644
--- a/packages/qwik/src/optimizer/src/index.ts
+++ b/packages/qwik/src/optimizer/src/index.ts
@@ -52,4 +52,5 @@ export type { BundleGraphAdder } from './plugins/bundle-graph';
export { qwikRollup } from './plugins/rollup';
export { qwikVite } from './plugins/vite';
-export { symbolMapper } from './plugins/vite-dev-server';
+/** @alpha @deprecated No longer needed, it is automatic now */
+export const symbolMapper = undefined;
diff --git a/packages/qwik/src/optimizer/src/plugins/plugin.ts b/packages/qwik/src/optimizer/src/plugins/plugin.ts
index 7bdb3dc7ff1..6f63e811949 100644
--- a/packages/qwik/src/optimizer/src/plugins/plugin.ts
+++ b/packages/qwik/src/optimizer/src/plugins/plugin.ts
@@ -76,7 +76,7 @@ export enum ExperimentalFeatures {
enableRequestRewrite = 'enableRequestRewrite',
/** Enable worker$ */
webWorker = 'webWorker',
- /** Enable the ability to use the Qwik Insights vite plugin and component */
+ /** Enable the ability to use the Qwik Insights vite plugin and `` component */
insights = 'insights',
}
@@ -107,15 +107,16 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
target: 'client',
buildMode: 'development',
debug: false,
- rootDir: null as any,
+ rootDir: undefined as any,
tsconfigFileNames: ['./tsconfig.json'],
- input: null as any,
- outDir: '',
- assetsDir: null as any,
+ input: undefined as any,
+ outDir: undefined as any,
+ assetsDir: undefined as any,
resolveQwikBuild: true,
- entryStrategy: null as any,
- srcDir: null as any,
- srcInputs: null as any,
+ entryStrategy: undefined as any,
+ srcDir: undefined as any,
+ ssrOutDir: undefined as any,
+ clientOutDir: undefined as any,
sourcemap: !!optimizerOptions.sourcemap,
manifestInput: null,
manifestOutput: null,
@@ -131,10 +132,16 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
};
let lazyNormalizePath: (id: string) => string;
+ let maybeFs: typeof import('fs') | undefined;
const init = async () => {
if (!internalOptimizer) {
internalOptimizer = await createOptimizer(optimizerOptions);
lazyNormalizePath = makeNormalizePath(internalOptimizer.sys);
+ try {
+ maybeFs = await internalOptimizer.sys.dynamicImport('node:fs');
+ } catch {
+ // ignore
+ }
}
};
@@ -161,7 +168,9 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
};
/** Note that as a side-effect this updates the internal plugin `opts` */
- const normalizeOptions = (inputOpts?: QwikPluginOptions) => {
+ const normalizeOptions = async (
+ inputOpts?: QwikPluginOptions
+ ): Promise => {
const updatedOpts: QwikPluginOptions = Object.assign({}, inputOpts);
const optimizer = getOptimizer();
@@ -220,81 +229,51 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
if (typeof updatedOpts.srcDir === 'string') {
opts.srcDir = normalizePath(path.resolve(opts.rootDir, updatedOpts.srcDir));
srcDir = opts.srcDir;
- opts.srcInputs = null;
- } else if (Array.isArray(updatedOpts.srcInputs)) {
- opts.srcInputs = [...updatedOpts.srcInputs];
- opts.srcDir = null;
} else {
opts.srcDir ||= srcDir;
}
+ opts.srcDir = normalizePath(path.resolve(opts.rootDir, normalizePath(opts.srcDir)));
if (Array.isArray(updatedOpts.tsconfigFileNames) && updatedOpts.tsconfigFileNames.length > 0) {
opts.tsconfigFileNames = updatedOpts.tsconfigFileNames;
}
- if (Array.isArray(opts.srcInputs)) {
- opts.srcInputs.forEach((i) => {
- i.path = normalizePath(path.resolve(opts.rootDir, i.path));
- });
- } else if (typeof opts.srcDir === 'string') {
- opts.srcDir = normalizePath(path.resolve(opts.rootDir, normalizePath(opts.srcDir)));
+ if (!updatedOpts.input && !opts.input) {
+ // we only provide inputs if none were provided by the user
+ if (opts.target === 'ssr') {
+ // this is for dev mode, prod will have own setting
+ opts.input = [path.resolve(srcDir, 'entry.ssr')];
+ } else if (opts.target === 'client') {
+ // not really an entry, just a starting point
+ opts.input = [path.resolve(srcDir, 'root')];
+ } else {
+ // others including lib should be ok already
+ opts.input = undefined!;
+ }
}
if (!updatedOpts.csr) {
- if (Array.isArray(updatedOpts.input)) {
- opts.input = [...updatedOpts.input];
- } else if (typeof updatedOpts.input === 'string') {
- opts.input = [updatedOpts.input];
- } else {
- if (opts.target === 'ssr') {
- // ssr input default
- opts.input ||= [path.resolve(srcDir, 'entry.ssr')];
- } else if (opts.target === 'client') {
- // client input default
- opts.input ||= [path.resolve(srcDir, 'root')];
- } else if (opts.target === 'lib') {
- if (typeof updatedOpts.input === 'object') {
- for (const key in updatedOpts.input) {
- const resolvedPaths: { [key: string]: string } = {};
- if (Object.hasOwnProperty.call(updatedOpts.input, key)) {
- const relativePath = updatedOpts.input[key];
- const absolutePath = path.resolve(opts.rootDir, relativePath);
- resolvedPaths[key] = absolutePath;
- }
-
- opts.input = { ...opts.input, ...resolvedPaths };
- }
- } else {
- // lib input default
- opts.input ||= [path.resolve(srcDir, 'index.ts')];
- }
- } else {
- opts.input ||= [];
- }
- }
- if (Array.isArray(opts.input)) {
- opts.input = opts.input.reduce((inputs, i) => {
- let input = i;
- if (!i.startsWith('@') && !i.startsWith('~') && !i.startsWith('#')) {
- input = normalizePath(path.resolve(opts.rootDir, i));
- }
- if (!inputs.includes(input)) {
- inputs.push(input);
- }
- return inputs;
- }, [] as string[]);
+ if (updatedOpts.outDir) {
+ // forced output directory
+ opts.outDir = normalizePath(path.resolve(opts.rootDir, normalizePath(updatedOpts.outDir)));
}
- if (typeof updatedOpts.outDir === 'string') {
- opts.outDir = normalizePath(path.resolve(opts.rootDir, normalizePath(updatedOpts.outDir)));
- } else if (!opts.outDir) {
- if (opts.target === 'ssr') {
- opts.outDir = normalizePath(path.resolve(opts.rootDir, SSR_OUT_DIR));
- } else if (opts.target === 'lib') {
- opts.outDir = normalizePath(path.resolve(opts.rootDir, LIB_OUT_DIR));
- } else {
- opts.outDir = normalizePath(path.resolve(opts.rootDir, CLIENT_OUT_DIR));
- }
+ // default output directory
+ opts.clientOutDir = normalizePath(
+ path.resolve(opts.rootDir, updatedOpts.clientOutDir || CLIENT_OUT_DIR)
+ );
+ opts.ssrOutDir = normalizePath(
+ path.resolve(opts.rootDir, updatedOpts.ssrOutDir || SSR_OUT_DIR)
+ );
+ if (opts.target === 'ssr') {
+ // server
+ opts.outDir ||= opts.ssrOutDir;
+ } else if (opts.target === 'lib') {
+ // library
+ opts.outDir ||= normalizePath(path.resolve(opts.rootDir, LIB_OUT_DIR));
+ } else {
+ // client
+ opts.outDir ||= opts.clientOutDir;
}
}
@@ -302,9 +281,31 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
opts.manifestOutput = updatedOpts.manifestOutput;
}
- const clientManifest = getValidManifest(updatedOpts.manifestInput);
- if (clientManifest) {
- opts.manifestInput = clientManifest;
+ if (updatedOpts.manifestInput) {
+ opts.manifestInput = getValidManifest(updatedOpts.manifestInput) || null;
+ }
+ if (
+ !opts.manifestInput &&
+ opts.target === 'ssr' &&
+ opts.buildMode === 'production' &&
+ maybeFs
+ ) {
+ let clientManifestPath = normalizePath(path.resolve(opts.clientOutDir, Q_MANIFEST_FILENAME));
+ if (!(await maybeFs.promises.stat(clientManifestPath).catch(() => false))) {
+ clientManifestPath = normalizePath(
+ path.resolve(opts.rootDir, CLIENT_OUT_DIR, Q_MANIFEST_FILENAME)
+ );
+ }
+ try {
+ const clientManifestStr = await maybeFs.promises.readFile(clientManifestPath, 'utf-8');
+ opts.manifestInput = getValidManifest(JSON.parse(clientManifestStr)) || null;
+ // eslint-disable-next-line no-console
+ console.info('Read client manifest from', clientManifestPath);
+ } catch (e) {
+ console.warn(
+ `could not read Qwik client manifest ${clientManifestPath}, ignoring. Make sure you provide it to the SSR renderer. (${e})`
+ );
+ }
}
if (typeof updatedOpts.transformedModuleOutput === 'function') {
@@ -313,6 +314,36 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
if (updatedOpts.scope !== undefined) {
opts.scope = updatedOpts.scope;
+ } else if (!opts.scope && maybeFs) {
+ // Use the package name for the scope
+ let pkgPath = '';
+ try {
+ let pkgDir = opts.rootDir;
+ while (true) {
+ pkgPath = path.resolve(pkgDir, 'package.json');
+ if (await maybeFs.promises.stat(pkgPath).catch(() => false)) {
+ break;
+ }
+ const parent = path.resolve(pkgDir, '..');
+ if (parent === pkgDir) {
+ break;
+ }
+ pkgDir = parent;
+ pkgPath = '';
+ }
+
+ if (pkgPath) {
+ const pkgString = await maybeFs.promises.readFile(pkgPath, 'utf-8');
+ const pkg = JSON.parse(pkgString);
+ if (typeof pkg.name === 'string') {
+ opts.scope = pkg.name;
+ }
+ }
+ } catch (e) {
+ console.warn(
+ `could not read ${pkgPath || 'package.json'} to determine package name, ignoring. (${e})`
+ );
+ }
}
if (typeof updatedOpts.resolveQwikBuild === 'boolean') {
@@ -395,20 +426,6 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
}
}
- const path = getPath();
-
- if (Array.isArray(opts.srcInputs)) {
- optimizer.sys.getInputFiles = async (rootDir) =>
- opts.srcInputs!.map((i) => {
- const relInput: TransformModuleInput = {
- path: normalizePath(path.relative(rootDir, i.path)),
- code: i.code,
- };
- return relInput;
- });
- debug(`buildStart() opts.srcInputs (${opts.srcInputs.length} files)`);
- }
-
debug(`transformedOutputs.clear()`);
clientTransformedOutputs.clear();
serverTransformedOutputs.clear();
@@ -918,6 +935,7 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
diagnosticsCallback = cb;
};
+ /** Convert windows backslashes to forward slashes if possible */
const normalizePath = (id: string) => lazyNormalizePath(id);
function getQwikBuildModule(isServer: boolean, _target: QwikBuildTarget) {
@@ -1056,9 +1074,6 @@ export const manifest = ${JSON.stringify(serverManifest)};\n`;
if (typeof opts.transformedModuleOutput === 'function') {
await opts.transformedModuleOutput(getTransformedOutputs());
}
-
- // TODO get rid of this with the vite environment api
- return manifestStr;
}
return {
@@ -1174,9 +1189,12 @@ export interface QwikPluginOptions {
manifestInput?: QwikManifest | null;
input?: string[] | string | { [entry: string]: string };
outDir?: string;
+ ssrOutDir?: string;
+ clientOutDir?: string;
assetsDir?: string;
srcDir?: string | null;
scope?: string | null;
+ /** @deprecated Not used */
srcInputs?: TransformModuleInput[] | null;
sourcemap?: boolean;
resolveQwikBuild?: boolean;
@@ -1204,9 +1222,12 @@ export interface QwikPluginOptions {
}
export interface NormalizedQwikPluginOptions
- extends Omit, 'vendorRoots' | 'experimental'> {
- input: string[] | { [entry: string]: string };
- experimental?: Record;
+ extends Omit<
+ Required,
+ 'input' | 'vendorRoots' | 'srcInputs' | 'experimental'
+ > {
+ input: string[] | { [entry: string]: string } | undefined;
+ experimental: Record | undefined;
}
export type QwikPlugin = ReturnType;
diff --git a/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts b/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts
index 1255f59811e..d37a262c1cf 100644
--- a/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts
+++ b/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts
@@ -15,7 +15,7 @@ test('types', () => () => {
test('defaults', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions();
+ const opts = await plugin.normalizeOptions();
assert.deepEqual(opts.target, 'client');
assert.deepEqual(opts.buildMode, 'development');
assert.deepEqual(opts.entryStrategy, { type: 'segment' });
@@ -27,12 +27,11 @@ test('defaults', async () => {
assert.deepEqual(opts.manifestInput, null);
assert.deepEqual(opts.manifestOutput, null);
assert.deepEqual(opts.srcDir, normalizePath(resolve(cwd, 'src')));
- assert.deepEqual(opts.srcInputs, null);
});
test('defaults (buildMode: production)', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ buildMode: 'production' });
+ const opts = await plugin.normalizeOptions({ buildMode: 'production' });
assert.deepEqual(opts.target, 'client');
assert.deepEqual(opts.buildMode, 'production');
assert.deepEqual(opts.entryStrategy, { type: 'smart' });
@@ -45,13 +44,12 @@ test('defaults (buildMode: production)', async () => {
assert.deepEqual(opts.manifestInput, null);
assert.deepEqual(opts.manifestOutput, null);
assert.deepEqual(opts.srcDir, normalizePath(resolve(cwd, 'src')));
- assert.deepEqual(opts.srcInputs, null);
assert.deepEqual(opts.entryStrategy, { type: 'smart' });
});
test('defaults (target: ssr)', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ target: 'ssr' });
+ const opts = await plugin.normalizeOptions({ target: 'ssr' });
assert.deepEqual(opts.target, 'ssr');
assert.deepEqual(opts.buildMode, 'development');
assert.deepEqual(opts.entryStrategy, { type: 'hoist' });
@@ -64,12 +62,11 @@ test('defaults (target: ssr)', async () => {
assert.deepEqual(opts.manifestInput, null);
assert.deepEqual(opts.manifestOutput, null);
assert.deepEqual(opts.srcDir, normalizePath(resolve(cwd, 'src')));
- assert.deepEqual(opts.srcInputs, null);
});
test('defaults (buildMode: production, target: ssr)', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ buildMode: 'production', target: 'ssr' });
+ const opts = await plugin.normalizeOptions({ buildMode: 'production', target: 'ssr' });
assert.deepEqual(opts.target, 'ssr');
assert.deepEqual(opts.buildMode, 'production');
assert.deepEqual(opts.entryStrategy, { type: 'hoist' });
@@ -82,24 +79,23 @@ test('defaults (buildMode: production, target: ssr)', async () => {
assert.deepEqual(opts.manifestInput, null);
assert.deepEqual(opts.manifestOutput, null);
assert.deepEqual(opts.srcDir, normalizePath(resolve(cwd, 'src')));
- assert.deepEqual(opts.srcInputs, null);
});
test('debug true', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ debug: true });
+ const opts = await plugin.normalizeOptions({ debug: true });
assert.deepEqual(opts.debug, true);
});
test('csr', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ csr: true });
- assert.deepEqual(opts.outDir, '');
+ const opts = await plugin.normalizeOptions({ csr: true });
+ assert.deepEqual(opts.outDir, undefined);
});
test('override entryStrategy', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({
+ const opts = await plugin.normalizeOptions({
entryStrategy: { type: 'component' },
buildMode: 'production',
});
@@ -108,7 +104,7 @@ test('override entryStrategy', async () => {
test('entryStrategy, smart', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({
+ const opts = await plugin.normalizeOptions({
entryStrategy: { type: 'smart' },
});
assert.deepEqual(opts.entryStrategy.type, 'smart');
@@ -116,15 +112,14 @@ test('entryStrategy, smart', async () => {
test('entryStrategy, segment no forceFullBuild', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ entryStrategy: { type: 'segment' } });
+ const opts = await plugin.normalizeOptions({ entryStrategy: { type: 'segment' } });
assert.deepEqual(opts.entryStrategy.type, 'segment');
});
test('entryStrategy, segment and srcInputs', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({
+ const opts = await plugin.normalizeOptions({
entryStrategy: { type: 'segment' },
- srcInputs: [],
});
assert.deepEqual(opts.entryStrategy.type, 'segment');
});
@@ -132,20 +127,20 @@ test('entryStrategy, segment and srcInputs', async () => {
test('rootDir, abs path', async () => {
const plugin = await mockPlugin();
const customRoot = normalizePath(resolve(cwd, 'abs-path'));
- const opts = plugin.normalizeOptions({ rootDir: customRoot });
+ const opts = await plugin.normalizeOptions({ rootDir: customRoot });
assert.deepEqual(opts.rootDir, customRoot);
});
test('rootDir, rel path', async () => {
const plugin = await mockPlugin();
const customRoot = 'rel-path';
- const opts = plugin.normalizeOptions({ rootDir: customRoot });
+ const opts = await plugin.normalizeOptions({ rootDir: customRoot });
assert.deepEqual(opts.rootDir, normalizePath(resolve(cwd, customRoot)));
});
test('tsconfigFileNames', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({
+ const opts = await plugin.normalizeOptions({
tsconfigFileNames: ['./tsconfig.json', './tsconfig.app.json'],
});
assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json', './tsconfig.app.json']);
@@ -153,7 +148,7 @@ test('tsconfigFileNames', async () => {
test('tsconfigFileNames, empty array fallback to default', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({
+ const opts = await plugin.normalizeOptions({
tsconfigFileNames: [],
});
assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json']);
@@ -161,31 +156,30 @@ test('tsconfigFileNames, empty array fallback to default', async () => {
test('input string', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ input: 'src/cmps/main.tsx' });
- assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'cmps', 'main.tsx'))]);
+ const opts = await plugin.normalizeOptions({ input: 'src/cmps/main.tsx' });
+ // we don't provide input so that we don't override the vite input
+ assert.deepEqual(opts.input, undefined);
});
test('input array', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({
+ const opts = await plugin.normalizeOptions({
input: ['src/cmps/a.tsx', 'src/cmps/b.tsx'],
});
- assert.deepEqual(opts.input, [
- normalizePath(resolve(cwd, 'src', 'cmps', 'a.tsx')),
- normalizePath(resolve(cwd, 'src', 'cmps', 'b.tsx')),
- ]);
+ // we don't provide input so that we don't override the vite input
+ assert.deepEqual(opts.input, undefined);
});
test('outDir', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ outDir: 'out' });
+ const opts = await plugin.normalizeOptions({ outDir: 'out' });
assert.deepEqual(opts.outDir, normalizePath(resolve(cwd, 'out')));
});
test('manifestOutput', async () => {
const plugin = await mockPlugin();
const manifestOutput = () => {};
- const opts = plugin.normalizeOptions({ manifestOutput });
+ const opts = await plugin.normalizeOptions({ manifestOutput });
assert.deepEqual(opts.manifestOutput, manifestOutput);
});
@@ -198,19 +192,19 @@ test('manifestInput', async () => {
bundles: {},
version: '1',
};
- const opts = plugin.normalizeOptions({ manifestInput });
+ const opts = await plugin.normalizeOptions({ manifestInput });
assert.deepEqual(opts.manifestInput, manifestInput);
});
test('resolveQwikBuild true', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ resolveQwikBuild: true });
+ const opts = await plugin.normalizeOptions({ resolveQwikBuild: true });
assert.deepEqual(opts.resolveQwikBuild, true);
});
test('resolveQwikBuild false', async () => {
const plugin = await mockPlugin();
- const opts = plugin.normalizeOptions({ resolveQwikBuild: false });
+ const opts = await plugin.normalizeOptions({ resolveQwikBuild: false });
assert.deepEqual(opts.resolveQwikBuild, false);
});
@@ -221,7 +215,7 @@ test('experimental[]', async () => {
// we can't test this without a flag
return;
}
- const opts = plugin.normalizeOptions({ experimental: [flag] });
+ const opts = await plugin.normalizeOptions({ experimental: [flag] });
assert.deepEqual(opts.experimental, { [flag]: true } as any);
});
diff --git a/packages/qwik/src/optimizer/src/plugins/rollup.ts b/packages/qwik/src/optimizer/src/plugins/rollup.ts
index 545956f35ec..5c38b5a1bb6 100644
--- a/packages/qwik/src/optimizer/src/plugins/rollup.ts
+++ b/packages/qwik/src/optimizer/src/plugins/rollup.ts
@@ -66,9 +66,9 @@ export function qwikRollup(qwikRollupOpts: QwikRollupPluginOptions = {}): any {
experimental: qwikRollupOpts.experimental,
};
- const opts = qwikPlugin.normalizeOptions(pluginOpts);
+ const opts = await qwikPlugin.normalizeOptions(pluginOpts);
- if (!inputOpts.input) {
+ if (opts.input) {
inputOpts.input = opts.input;
}
@@ -151,6 +151,35 @@ export function normalizeRollupOutputOptions(
};
}
+const getChunkFileName = (
+ prefix: string,
+ opts: NormalizedQwikPluginOptions,
+ optimizer: Optimizer
+) => {
+ if (opts.buildMode === 'production' && !opts.debug) {
+ return `${prefix}build/q-[hash].js`;
+ } else {
+ // Friendlier names in dev or preview with debug mode
+ return (chunkInfo: Rollup.PreRenderedChunk) => {
+ if (chunkInfo.moduleIds?.some((id) => id.endsWith('core.prod.mjs'))) {
+ return `${prefix}build/core.js`;
+ }
+ if (chunkInfo.moduleIds?.some((id) => id.endsWith('qwik-router/lib/index.qwik.mjs'))) {
+ return `${prefix}build/qwik-router.js`;
+ }
+
+ // The chunk name can often be a path. We sanitize it to use dashes instead of slashes, to keep the same folder structure as without debug:true.
+ // Besides, Rollup doesn't accept absolute or relative paths as inputs for the [name] placeholder for the same reason.
+ const relativePath = optimizer.sys.path.relative(optimizer.sys.cwd(), chunkInfo.name);
+ const sanitized = relativePath
+ .replace(/^(\.\.\/)+/, '')
+ .replace(/^\/+/, '')
+ .replace(/\//g, '-');
+ return `${prefix}build/${sanitized}.js`;
+ };
+ }
+};
+
export function normalizeRollupOutputOptionsObject(
qwikPlugin: QwikPlugin,
rollupOutputOptsObj: Rollup.OutputOptions | undefined,
@@ -160,79 +189,40 @@ export function normalizeRollupOutputOptionsObject(
const opts = qwikPlugin.getOptions();
const optimizer = qwikPlugin.getOptimizer();
const manualChunks = qwikPlugin.manualChunks;
- if (opts.target === 'client') {
- // client output
- if (!outputOpts.assetFileNames) {
- // SEO likes readable asset names
- const assetFileNames = 'assets/[hash]-[name].[ext]';
- outputOpts.assetFileNames = useAssetsDir
- ? `${opts.assetsDir}/${assetFileNames}`
- : assetFileNames;
- }
- let fileName: string | ((chunkInfo: Rollup.PreRenderedChunk) => string) | undefined;
- if (opts.buildMode === 'production' && !opts.debug) {
- fileName = 'build/q-[hash].js';
- } else {
- // Friendlier names in dev or preview with debug mode
- fileName = (chunkInfo) => {
- if (chunkInfo.moduleIds?.some((id) => id.endsWith('core.prod.mjs'))) {
- return 'build/core.js';
- }
- if (chunkInfo.moduleIds?.some((id) => id.endsWith('qwik-router/lib/index.qwik.mjs'))) {
- return 'build/qwik-router.js';
- }
-
- // The chunk name can often be a path. We sanitize it to use dashes instead of slashes, to keep the same folder structure as without debug:true.
- // Besides, Rollup doesn't accept absolute or relative paths as inputs for the [name] placeholder for the same reason.
- const path = optimizer.sys.path;
- const relativePath = path.relative(optimizer.sys.cwd(), chunkInfo.name);
- const sanitized = relativePath
- .replace(/^(\.\.\/)+/, '')
- .replace(/^\/+/, '')
- .replace(/\//g, '-');
- return `build/${sanitized}.js`;
- };
- }
- // client development/debug output
- const getFilePath = (fileNamePattern: string | ((info: Rollup.PreRenderedChunk) => string)) =>
- typeof fileNamePattern === 'string'
- ? useAssetsDir
- ? `${opts.assetsDir}/${fileNamePattern}`
- : fileNamePattern
- : useAssetsDir
- ? (chunkInfo: Rollup.PreRenderedChunk) =>
- `${opts.assetsDir}/${fileNamePattern(chunkInfo)}`
- : (chunkInfo: Rollup.PreRenderedChunk) => fileNamePattern(chunkInfo);
+ if (!outputOpts.assetFileNames) {
+ // SEO likes readable asset names
+ // assetsDir allows assets to be in a deeper directory for serving, e.g. Astro
+ outputOpts.assetFileNames = `${useAssetsDir ? `${opts.assetsDir}/` : ''}assets/[hash]-[name].[ext]`;
+ }
+ const chunkFileName = getChunkFileName(useAssetsDir ? `${opts.assetsDir}` : '', opts, optimizer);
+ if (opts.target === 'client') {
+ // client output
if (!outputOpts.entryFileNames) {
- outputOpts.entryFileNames = getFilePath(fileName);
+ // we don't treat entries specially for the client
+ outputOpts.entryFileNames = chunkFileName;
}
if (!outputOpts.chunkFileNames) {
- outputOpts.chunkFileNames = getFilePath(fileName);
+ outputOpts.chunkFileNames = chunkFileName;
}
- } else if (opts.buildMode === 'production') {
- // server production output
- // everything in same dir so './@qwik-router...' imports work from entry and chunks
- if (!outputOpts.chunkFileNames) {
- outputOpts.chunkFileNames = 'q-[hash].js';
- }
- }
- // all other cases, like lib output
- if (!outputOpts.assetFileNames) {
- outputOpts.assetFileNames = 'assets/[hash]-[name].[ext]';
- }
- if (opts.target === 'client') {
// client should always be es
outputOpts.format = 'es';
const prevManualChunks = outputOpts.manualChunks;
if (prevManualChunks && typeof prevManualChunks !== 'function') {
throw new Error('manualChunks must be a function');
}
+
+ // We need custom chunking for the client build
outputOpts.manualChunks = prevManualChunks
? (id, meta) => prevManualChunks(id, meta) || manualChunks(id, meta)
: manualChunks;
+ } else {
+ // server production output, try to be similar to client
+ if (!outputOpts.chunkFileNames) {
+ outputOpts.chunkFileNames = chunkFileName;
+ }
}
if (!outputOpts.dir) {
diff --git a/packages/qwik/src/optimizer/src/plugins/rollup.unit.ts b/packages/qwik/src/optimizer/src/plugins/rollup.unit.ts
index d0187bdae81..523ff42106f 100644
--- a/packages/qwik/src/optimizer/src/plugins/rollup.unit.ts
+++ b/packages/qwik/src/optimizer/src/plugins/rollup.unit.ts
@@ -58,11 +58,10 @@ test('rollup default set input options, ssr', async () => {
input: normalizePath(resolve(cwd, 'src', 'my.ssr.tsx')),
});
const opts: NormalizedQwikPluginOptions = plugin.api.getOptions();
-
assert.deepEqual(typeof rollupInputOpts.onwarn, 'function');
assert.deepEqual(rollupInputOpts.treeshake, undefined);
assert.deepEqual(rollupInputOpts.input, normalizePath(resolve(cwd, 'src', 'my.ssr.tsx')));
- assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'my.ssr.tsx'))]);
+ assert.deepEqual(opts.input, undefined);
});
test('rollup default output options, client', async () => {
diff --git a/packages/qwik/src/optimizer/src/plugins/vite-dev-server.ts b/packages/qwik/src/optimizer/src/plugins/vite-dev-server.ts
index bf4cc7e2434..21d4dbefda7 100644
--- a/packages/qwik/src/optimizer/src/plugins/vite-dev-server.ts
+++ b/packages/qwik/src/optimizer/src/plugins/vite-dev-server.ts
@@ -4,22 +4,15 @@ import type { IncomingMessage, ServerResponse } from 'http';
import { magenta } from 'kleur/colors';
import type { Connect, ViteDevServer } from 'vite';
-import type {
- OptimizerSystem,
- Path,
- ServerQwikManifest,
- SymbolMapper,
- SymbolMapperFn,
-} from '../types';
+import type { OptimizerSystem, Path, ServerQwikManifest } from '../types';
import clickToComponent from './click-to-component.html?raw';
import errorHost from './error-host.html?raw';
import imageDevTools from './image-size-runtime.html?raw';
import perfWarning from './perf-warning.html?raw';
-import { type NormalizedQwikPluginOptions, QWIK_HANDLERS_ID } from './plugin';
+import { type NormalizedQwikPluginOptions } from './plugin';
import type { QwikViteDevResponse } from './vite';
import { VITE_ERROR_OVERLAY_STYLES } from './vite-error';
import { formatError, parseId } from './vite-utils';
-import { SYNC_QRL } from 'packages/qwik/src/core/shared/qrl/qrl-utils';
function getOrigin(req: IncomingMessage) {
const { PROTOCOL_HEADER, HOST_HEADER } = process.env;
@@ -33,50 +26,6 @@ function getOrigin(req: IncomingMessage) {
return `${protocol}://${host}`;
}
-function createSymbolMapper(base: string): SymbolMapperFn {
- return (
- symbolName: string,
- _mapper: SymbolMapper | undefined,
- parent: string | undefined
- ): [string, string] => {
- if (symbolName === SYNC_QRL) {
- return [symbolName, ''];
- }
- if (!parent) {
- // Core symbols
- if (symbolName.startsWith('_')) {
- return [symbolName, `${base}${QWIK_HANDLERS_ID}`];
- }
- console.error(
- 'qwik vite-dev-server symbolMapper: unknown qrl requested without parent:',
- symbolName
- );
- return [symbolName, `${base}${symbolName}.js`];
- }
- // In dev mode, the `parent` is the Vite URL for the parent, not the real absolute path.
- // It is always absolute but when on Windows that's without a /
- const qrlFile = `${base}${parent.startsWith('/') ? parent.slice(1) : parent}_${symbolName}.js`;
- return [symbolName, qrlFile];
- };
-}
-
-let lazySymbolMapper: ReturnType | null = null;
-/**
- * @beta
- * For a given symbol (QRL such as `onKeydown$`) the server needs to know which bundle the symbol is in.
- *
- * Normally this is provided by Qwik's `q-manifest` . But `q-manifest` only exists after a full client build.
- *
- * This would be a problem in dev mode. So in dev mode the symbol is mapped to the expected URL using the symbolMapper function below. For Vite the given path is fixed for a given symbol.
- */
-export let symbolMapper: ReturnType = (symbolName, mapper, parent) => {
- // This is a fallback in case the symbolMapper is copied early
- if (lazySymbolMapper) {
- return lazySymbolMapper(symbolName, mapper, parent);
- }
- throw new Error('symbolMapper not initialized');
-};
-
export async function configureDevServer(
base: string,
server: ViteDevServer,
@@ -84,14 +33,8 @@ export async function configureDevServer(
sys: OptimizerSystem,
path: Path,
isClientDevOnly: boolean,
- clientDevInput: string | undefined,
- devSsrServer: boolean
+ clientDevInput: string | undefined
) {
- symbolMapper = lazySymbolMapper = createSymbolMapper(base);
- if (!devSsrServer) {
- // we just needed the symbolMapper
- return;
- }
const hasQwikRouter = server.config.plugins?.some(
(plugin) => plugin.name === 'vite-plugin-qwik-router'
);
@@ -140,6 +83,14 @@ export async function configureDevServer(
}
const firstInput = opts.input && Object.values(opts.input)[0];
+ if (!firstInput) {
+ console.error(`no entry found for dev server`);
+ res.statusCode ||= 404;
+ res.setHeader('Content-Type', 'text/plain');
+ res.writeHead(res.statusCode);
+ res.end('No entry found for dev server');
+ return;
+ }
const ssrModule = await server.ssrLoadModule(firstInput);
const render: Render = ssrModule.default ?? ssrModule.render;
@@ -214,7 +165,6 @@ export async function configureDevServer(
stream: res,
snapshot: !isClientDevOnly,
manifest: isClientDevOnly ? undefined : manifest,
- symbolMapper: isClientDevOnly ? undefined : symbolMapper,
serverData,
containerAttributes: { ...serverData.containerAttributes },
};
diff --git a/packages/qwik/src/optimizer/src/plugins/vite.ts b/packages/qwik/src/optimizer/src/plugins/vite.ts
index ceecf43f1b1..97569ba8818 100644
--- a/packages/qwik/src/optimizer/src/plugins/vite.ts
+++ b/packages/qwik/src/optimizer/src/plugins/vite.ts
@@ -12,7 +12,6 @@ import type {
import { type BundleGraphAdder } from './bundle-graph';
import { getImageSizeServer } from './image-size-server';
import {
- CLIENT_OUT_DIR,
QWIK_BUILD_ID,
QWIK_CLIENT_MANIFEST_ID,
QWIK_CORE_ID,
@@ -20,7 +19,6 @@ import {
QWIK_CORE_SERVER,
QWIK_JSX_DEV_RUNTIME_ID,
QWIK_JSX_RUNTIME_ID,
- SSR_OUT_DIR,
TRANSFORM_REGEX,
createQwikPlugin,
type ExperimentalFeatures,
@@ -56,7 +54,6 @@ type P = VitePlugin & { api: T; config: Extract['config'], F
export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
let isClientDevOnly = false;
let clientDevInput: undefined | string = undefined;
- let tmpClientManifestPath: undefined | string = undefined;
let viteCommand: 'build' | 'serve' = 'serve';
let manifestInput: QwikManifest | null = null;
let clientOutDir: string | null = null;
@@ -140,7 +137,13 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
qwikViteOpts.entryStrategy = { type: 'inline' };
}
}
-
+ // Special case: build.ssr can be the input for the ssr build
+ const ssrInput =
+ target === 'ssr'
+ ? typeof viteConfig.build?.ssr === 'string'
+ ? viteConfig.build.ssr
+ : qwikViteOpts.ssr?.input
+ : undefined;
const shouldFindVendors =
!qwikViteOpts.disableVendorScan && (target !== 'lib' || viteCommand === 'serve');
viteAssetsDir = viteConfig.build?.assetsDir;
@@ -157,106 +160,39 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
resolveQwikBuild: true,
transformedModuleOutput: qwikViteOpts.transformedModuleOutput,
outDir: viteConfig.build?.outDir,
+ ssrOutDir: qwikViteOpts.ssr?.outDir || viteConfig.build?.outDir,
+ clientOutDir:
+ qwikViteOpts.client?.outDir ||
+ // When ssr is true, this is probably an adapter build and not where the client build is
+ (viteConfig.build?.ssr ? undefined : viteConfig.build?.outDir),
assetsDir: useAssetsDir ? viteAssetsDir : undefined,
devTools: qwikViteOpts.devTools,
sourcemap: !!viteConfig.build?.sourcemap,
lint: qwikViteOpts.lint,
experimental: qwikViteOpts.experimental,
+ input: viteConfig.build?.rollupOptions?.input || ssrInput,
+ manifestInput: qwikViteOpts.ssr?.manifestInput,
+ manifestOutput: qwikViteOpts.client?.manifestOutput,
};
- if (!qwikViteOpts.csr) {
- if (target === 'ssr') {
- // ssr
- if (typeof viteConfig.build?.ssr === 'string') {
- // from --ssr flag user config
- // entry.server.ts (express/cloudflare/netlify)
- pluginOpts.input = viteConfig.build.ssr;
- } else if (typeof qwikViteOpts.ssr?.input === 'string') {
- // entry.ssr.tsx input (exports render())
- pluginOpts.input = qwikViteOpts.ssr.input;
- }
-
- if (qwikViteOpts.ssr?.outDir) {
- pluginOpts.outDir = qwikViteOpts.ssr.outDir;
- }
- pluginOpts.manifestInput = qwikViteOpts.ssr?.manifestInput;
- } else if (target === 'client') {
- // client
- pluginOpts.input = qwikViteOpts.client?.input;
- if (qwikViteOpts.client?.outDir) {
- pluginOpts.outDir = qwikViteOpts.client.outDir;
- }
- pluginOpts.manifestOutput = qwikViteOpts.client?.manifestOutput;
- } else {
- if (typeof viteConfig.build?.lib === 'object') {
- pluginOpts.input = viteConfig.build?.lib.entry;
- }
- }
- if (sys.env === 'node' || sys.env === 'bun') {
- const fs: typeof import('fs') = await sys.dynamicImport('node:fs');
-
- try {
- const rootDir = pluginOpts.rootDir ?? sys.cwd();
- const packageJsonPath = sys.path.join(rootDir, 'package.json');
- const pkgString = await fs.promises.readFile(packageJsonPath, 'utf-8');
-
- try {
- const data = JSON.parse(pkgString);
-
- if (typeof data.name === 'string') {
- pluginOpts.scope = data.name;
- }
- } catch (e) {
- console.error(e);
- }
- } catch {
- // error reading package.json from Node.js fs, ok to ignore
- }
-
- // In a Node.js environment, create a path to a q-manifest.json file within the
- // OS tmp directory. This path should always be the same for both client and ssr.
- // Client build will write to this path, and SSR will read from it. For this reason,
- // the Client build should always start and finish before the SSR build.
- const nodeOs: typeof import('os') = await sys.dynamicImport('node:os');
-
- // Additionally, we add a suffix to scope the file to the current application so that
- // different applications can be run in parallel without generating conflicts.
- const scopeSuffix = pluginOpts.scope ? `-${pluginOpts.scope.replace(/\//g, '--')}` : '';
-
- tmpClientManifestPath = path.join(
- nodeOs.tmpdir(),
- `vite-plugin-qwik-q-manifest${scopeSuffix}.json`
- );
- if (target === 'ssr' && !pluginOpts.manifestInput) {
- // This is a SSR build so we should load the client build's manifest
- // so it can be used as the manifestInput of the SSR build
- try {
- const clientManifestStr = await fs.promises.readFile(tmpClientManifestPath, 'utf-8');
- pluginOpts.manifestInput = JSON.parse(clientManifestStr);
- } catch {
- // ignore
- }
- }
- }
+ const opts = await qwikPlugin.normalizeOptions(pluginOpts);
+ if (ssrInput) {
+ // make sure vite uses the ssr input
+ opts.input ||= [ssrInput];
}
- const opts = qwikPlugin.normalizeOptions(pluginOpts);
- manifestInput = pluginOpts.manifestInput || null;
+ manifestInput = opts.manifestInput;
srcDir = opts.srcDir;
rootDir = opts.rootDir;
if (!qwikViteOpts.csr) {
- clientOutDir = qwikPlugin.normalizePath(
- sys.path.resolve(opts.rootDir, qwikViteOpts.client?.outDir || CLIENT_OUT_DIR)
- );
+ clientOutDir = opts.clientOutDir;
clientPublicOutDir = viteConfig.base
? path.join(clientOutDir, viteConfig.base)
: clientOutDir;
- ssrOutDir = qwikPlugin.normalizePath(
- sys.path.resolve(opts.rootDir, qwikViteOpts.ssr?.outDir || SSR_OUT_DIR)
- );
+ ssrOutDir = opts.ssrOutDir;
if (typeof qwikViteOpts.client?.devInput === 'string') {
clientDevInput = path.resolve(opts.rootDir, qwikViteOpts.client.devInput);
@@ -345,6 +281,8 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
* https://github.com/QwikDev/qwik/issues/7226#issuecomment-2647122505
*/
maxParallelFileOps: 1,
+ // This will amend the existing input
+ input: opts.input,
output: {
manualChunks: qwikPlugin.manualChunks,
},
@@ -368,7 +306,7 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
updatedViteConfig.build!.outDir = buildOutputDir;
const origOnwarn = updatedViteConfig.build!.rollupOptions?.onwarn;
updatedViteConfig.build!.rollupOptions = {
- input: opts.input,
+ ...updatedViteConfig.build!.rollupOptions,
output: normalizeRollupOutputOptions(
qwikPlugin,
viteConfig.build?.rollupOptions?.output,
@@ -390,7 +328,7 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
updatedViteConfig.publicDir = false;
updatedViteConfig.build!.ssr = true;
if (viteConfig.build?.minify == null && buildMode === 'production') {
- updatedViteConfig.build!.minify = 'esbuild';
+ updatedViteConfig.build!.minify = true;
}
}
} else if (opts.target === 'client') {
@@ -447,6 +385,8 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
},
async buildStart() {
+ injections.length = 0;
+
// Using vite.resolveId to check file if exist
// for example input might be virtual file
const resolver = this.resolve.bind(this);
@@ -564,22 +504,10 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
}
}
- const clientManifestStr = await qwikPlugin.generateManifest(
- this,
- rollupBundle,
- bundleGraphAdders,
- {
- injections,
- platform: { vite: '' },
- }
- );
-
- const sys = qwikPlugin.getSys();
- if (tmpClientManifestPath && (sys.env === 'node' || sys.env === 'bun')) {
- // Client build should write the manifest to a tmp dir
- const fs: typeof import('fs') = await sys.dynamicImport('node:fs');
- await fs.promises.writeFile(tmpClientManifestPath, clientManifestStr);
- }
+ await qwikPlugin.generateManifest(this, rollupBundle, bundleGraphAdders, {
+ injections,
+ platform: { vite: '' },
+ });
}
},
},
@@ -639,7 +567,8 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
configureServer(server: ViteDevServer) {
qwikPlugin.configureServer(server);
- const devSsrServer = 'devSsrServer' in qwikViteOpts ? !!qwikViteOpts.devSsrServer : true;
+ const devSsrServer =
+ !qwikViteOpts.csr && ('devSsrServer' in qwikViteOpts ? !!qwikViteOpts.devSsrServer : true);
const imageDevTools =
qwikViteOpts.devTools && 'imageDevTools' in qwikViteOpts.devTools
? qwikViteOpts.devTools.imageDevTools
@@ -649,7 +578,7 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
server.middlewares.use(getImageSizeServer(qwikPlugin.getSys(), rootDir!, srcDir!));
}
- if (!qwikViteOpts.csr) {
+ if (devSsrServer) {
const plugin = async () => {
const opts = qwikPlugin.getOptions();
const sys = qwikPlugin.getSys();
@@ -661,11 +590,10 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
sys,
path,
isClientDevOnly,
- clientDevInput,
- devSsrServer
+ clientDevInput
);
};
- // TODO: Removed the "__qwikCityNew" condition in V3
+ // TODO: Remove the "__qwikCityNew" condition in V3
const isNEW =
(globalThis as any).__qwikRouterNew === true ||
(globalThis as any).__qwikCityNew === true ||
diff --git a/packages/qwik/src/optimizer/src/plugins/vite.unit.ts b/packages/qwik/src/optimizer/src/plugins/vite.unit.ts
index 31731e7995b..6963d75a092 100644
--- a/packages/qwik/src/optimizer/src/plugins/vite.unit.ts
+++ b/packages/qwik/src/optimizer/src/plugins/vite.unit.ts
@@ -307,7 +307,8 @@ test('command: build, --ssr entry.server.tsx', async () => {
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'entry.server.tsx'))]);
assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]');
- assert.deepEqual(outputOptions.chunkFileNames, undefined);
+ assert.isFunction(outputOptions.chunkFileNames);
+ assert.deepEqual((outputOptions.chunkFileNames as any)({ name: 'hello' }), 'build/hello.js');
assert.deepEqual(outputOptions.entryFileNames, undefined);
assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'server')));
@@ -365,7 +366,7 @@ test('command: serve, --mode ssr with build.assetsDir', async () => {
{ build: { emptyOutDir: true, assetsDir: 'my-assets-dir' } },
{ command: 'serve', mode: 'ssr' }
))!;
- const opts = await plugin.api?.getOptions();
+ const opts = plugin.api?.getOptions();
const build = c.build!;
const rollupOptions = build!.rollupOptions!;
@@ -451,10 +452,11 @@ test('command: build, --mode lib', async () => {
assert.deepEqual(opts.buildMode, 'development');
assert.deepEqual(build.minify, false);
assert.deepEqual(build.ssr, undefined);
- assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'index.ts'))]);
+ assert.deepEqual(rollupOptions.input, undefined);
assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]');
- assert.deepEqual(outputOptions.chunkFileNames, undefined);
+ assert.isFunction(outputOptions.chunkFileNames);
+ assert.deepEqual((outputOptions.chunkFileNames as any)({ name: 'hello' }), 'build/hello.js');
assert.deepEqual(c.build.outDir, normalizePath(resolve(cwd, 'lib')));
assert.deepEqual(build.emptyOutDir, undefined);
@@ -506,14 +508,15 @@ test('command: build, --mode lib with multiple outputs', async () => {
assert.deepEqual(opts.buildMode, 'development');
assert.deepEqual(build.minify, false);
assert.deepEqual(build.ssr, undefined);
- assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'index.ts'))]);
+ assert.deepEqual(rollupOptions.input, undefined);
assert.ok(Array.isArray(outputOptions));
assert.lengthOf(outputOptions, 4);
outputOptions.forEach((outputOptionsObj) => {
assert.deepEqual(outputOptionsObj.assetFileNames, 'assets/[hash]-[name].[ext]');
- assert.deepEqual(outputOptionsObj.chunkFileNames, undefined);
+ assert.isFunction(outputOptionsObj.chunkFileNames);
+ assert.deepEqual((outputOptionsObj.chunkFileNames as any)({ name: 'hello' }), 'build/hello.js');
});
assert.deepEqual(c.build.outDir, normalizePath(resolve(cwd, 'lib')));
diff --git a/packages/qwik/src/optimizer/src/qwik.optimizer.api.md b/packages/qwik/src/optimizer/src/qwik.optimizer.api.md
index 390e81d8217..80ebfd9b51d 100644
--- a/packages/qwik/src/optimizer/src/qwik.optimizer.api.md
+++ b/packages/qwik/src/optimizer/src/qwik.optimizer.api.md
@@ -406,10 +406,8 @@ export type SourceMapsOption = 'external' | 'inline' | undefined | null;
// @public (undocumented)
export type SymbolMapper = Record;
-// Warning: (ae-forgotten-export) The symbol "createSymbolMapper" needs to be exported by the entry point index.d.ts
-//
-// @beta
-export let symbolMapper: ReturnType;
+// @alpha @deprecated (undocumented)
+export const symbolMapper: undefined;
// @public (undocumented)
export type SymbolMapperFn = (symbolName: string, mapper: SymbolMapper | undefined, parent?: string) => readonly [symbol: string, chunk: string] | undefined;
diff --git a/packages/qwik/src/server/platform.ts b/packages/qwik/src/server/platform.ts
index fe5e0f7c671..d6a9c59fe0e 100644
--- a/packages/qwik/src/server/platform.ts
+++ b/packages/qwik/src/server/platform.ts
@@ -1,11 +1,43 @@
-import type { SerializeDocumentOptions } from './types';
import { setPlatform } from '@qwik.dev/core';
-import type { ResolvedManifest } from '@qwik.dev/core/optimizer';
-import type { CorePlatformServer } from './qwik-types';
+import { isDev } from '@qwik.dev/core/build';
+import type { ResolvedManifest, SymbolMapperFn } from '@qwik.dev/core/optimizer';
import { SYNC_QRL } from './qwik-copy';
+import type { CorePlatformServer, SymbolMapper } from './qwik-types';
+import type { SerializeDocumentOptions } from './types';
declare const require: (module: string) => Record;
+/**
+ * In dev mode, we create predicatable QRL segment filenames so we can recover the parent path in
+ * the vite plugin, because we don't have a manifest
+ */
+const getDevSegmentPath = (
+ mapper: SymbolMapper | undefined,
+ hash: string,
+ symbolName: string,
+ parent?: string
+): ReturnType => {
+ const existing = mapper?.[hash];
+ if (existing) {
+ return existing;
+ }
+ if (symbolName === SYNC_QRL) {
+ return [symbolName, ''];
+ }
+ if (!parent) {
+ // Core symbols
+ if (symbolName.startsWith('_') && symbolName.length < 6) {
+ return [symbolName, `${import.meta.env.BASE_URL}@qwik-handlers`];
+ }
+ console.error('qwik symbolMapper: unknown qrl requested without parent:', symbolName);
+ return [symbolName, `${import.meta.env.BASE_URL}${symbolName}.js`];
+ }
+ // In dev mode, the `parent` is the Vite URL for the parent, not the real absolute path.
+ // It is always absolute but when on Windows that's without a /
+ const qrlFile = `${import.meta.env.BASE_URL}${parent.startsWith('/') ? parent.slice(1) : parent}_${symbolName}.js`;
+ return [symbolName, qrlFile];
+};
+
export function createPlatform(
opts: SerializeDocumentOptions,
resolvedManifest: ResolvedManifest | undefined
@@ -14,9 +46,11 @@ export function createPlatform(
const mapperFn = opts.symbolMapper
? opts.symbolMapper
: (symbolName: string, _chunk: any, parent?: string): readonly [string, string] | undefined => {
- if (mapper) {
+ if (mapper || (isDev && import.meta.env.MODE !== 'test')) {
const hash = getSymbolHash(symbolName);
- const result = mapper[hash];
+ const result = !isDev
+ ? mapper![hash]
+ : getDevSegmentPath(mapper, hash, symbolName, parent);
if (!result) {
if (hash === SYNC_QRL) {
return [hash, ''] as const;
@@ -25,10 +59,6 @@ export function createPlatform(
if (isRegistered) {
return [symbolName, '_'] as const;
}
- if (parent) {
- // In dev mode, SSR may need to refer to a symbol that wasn't built yet on the client
- return [symbolName, `${parent}?qrl=${symbolName}`] as const;
- }
console.error('Cannot resolve symbol', symbolName, 'in', mapper, parent);
}
return result;
diff --git a/scripts/api.ts b/scripts/api.ts
index 0803c849c3d..1708b548921 100644
--- a/scripts/api.ts
+++ b/scripts/api.ts
@@ -141,8 +141,8 @@ export async function apiExtractorQwikRouter(config: BuildConfig) {
);
createTypesApi(
config,
- join(config.packagesDir, 'qwik-router', 'src', 'adapters', 'static', 'vite'),
- join(config.packagesDir, 'qwik-router', 'lib', 'adapters', 'static', 'vite', 'index.d.ts')
+ join(config.packagesDir, 'qwik-router', 'src', 'adapters', 'ssg', 'vite'),
+ join(config.packagesDir, 'qwik-router', 'lib', 'adapters', 'ssg', 'vite', 'index.d.ts')
);
createTypesApi(
config,
@@ -196,8 +196,8 @@ export async function apiExtractorQwikRouter(config: BuildConfig) {
);
createTypesApi(
config,
- join(config.packagesDir, 'qwik-router', 'src', 'static'),
- join(config.packagesDir, 'qwik-router', 'lib', 'static', 'index.d.ts')
+ join(config.packagesDir, 'qwik-router', 'src', 'ssg'),
+ join(config.packagesDir, 'qwik-router', 'lib', 'ssg', 'index.d.ts')
);
createTypesApi(
config,
diff --git a/scripts/qwik-router.ts b/scripts/qwik-router.ts
index 1b9bc208f90..3b9362a4a47 100644
--- a/scripts/qwik-router.ts
+++ b/scripts/qwik-router.ts
@@ -21,7 +21,7 @@ export async function buildQwikRouter(config: BuildConfig) {
buildAdapterNodeServerVite(config),
buildAdapterNetlifyEdgeVite(config),
buildAdapterSharedVite(config),
- buildAdapterStaticVite(config),
+ buildAdapterSsgVite(config),
buildAdapterVercelEdgeVite(config),
buildMiddlewareCloudflarePages(config),
buildMiddlewareNetlifyEdge(config),
@@ -33,9 +33,9 @@ export async function buildQwikRouter(config: BuildConfig) {
buildMiddlewareRequestHandler(config),
buildMiddlewareVercelEdge(config),
buildMiddlewareFirebase(config),
- buildStatic(config),
- buildStaticNode(config),
- buildStaticDeno(config),
+ buildSsg(config),
+ buildSsgNode(config),
+ buildSsgDeno(config),
]);
await buildRuntime(config);
@@ -167,7 +167,7 @@ async function buildServiceWorker(config: BuildConfig) {
async function buildAdapterAzureSwaVite(config: BuildConfig) {
const entryPoints = [join(config.srcQwikRouterDir, 'adapters', 'azure-swa', 'vite', 'index.ts')];
- const external = ['vite', 'fs', 'path', '@qwik.dev/router/static'];
+ const external = ['vite', 'fs', 'path', '@qwik.dev/router/ssg'];
await build({
entryPoints,
@@ -377,7 +377,7 @@ async function buildAdapterSharedVite(config: BuildConfig) {
format: 'esm',
external: ADAPTER_EXTERNALS,
plugins: [
- resolveStatic('../../../static/index.mjs'),
+ resolveSsg('../../../ssg/index.mjs'),
resolveRequestHandler('../../../middleware/request-handler/index.mjs'),
],
});
@@ -391,35 +391,35 @@ async function buildAdapterSharedVite(config: BuildConfig) {
format: 'cjs',
external: ADAPTER_EXTERNALS,
plugins: [
- resolveStatic('../../../static/index.cjs'),
+ resolveSsg('../../../ssg/index.cjs'),
resolveRequestHandler('../../../middleware/request-handler/index.cjs'),
],
});
}
-async function buildAdapterStaticVite(config: BuildConfig) {
- const entryPoints = [join(config.srcQwikRouterDir, 'adapters', 'static', 'vite', 'index.ts')];
+async function buildAdapterSsgVite(config: BuildConfig) {
+ const entryPoints = [join(config.srcQwikRouterDir, 'adapters', 'ssg', 'vite', 'index.ts')];
await build({
entryPoints,
- outfile: join(config.distQwikRouterPkgDir, 'adapters', 'static', 'vite', 'index.mjs'),
+ outfile: join(config.distQwikRouterPkgDir, 'adapters', 'ssg', 'vite', 'index.mjs'),
bundle: true,
platform: 'node',
target: nodeTarget,
format: 'esm',
external: ADAPTER_EXTERNALS,
- plugins: [resolveStatic('../../../static/index.mjs')],
+ plugins: [resolveSsg('../../../ssg/index.mjs')],
});
await build({
entryPoints,
- outfile: join(config.distQwikRouterPkgDir, 'adapters', 'static', 'vite', 'index.cjs'),
+ outfile: join(config.distQwikRouterPkgDir, 'adapters', 'ssg', 'vite', 'index.cjs'),
bundle: true,
platform: 'node',
target: nodeTarget,
format: 'cjs',
external: ADAPTER_EXTERNALS,
- plugins: [resolveStatic('../../../static/index.cjs')],
+ plugins: [resolveSsg('../../../ssg/index.cjs')],
});
}
@@ -623,12 +623,12 @@ async function buildMiddlewareFirebase(config: BuildConfig) {
});
}
-async function buildStatic(config: BuildConfig) {
- const entryPoints = [join(config.srcQwikRouterDir, 'static', 'index.ts')];
+async function buildSsg(config: BuildConfig) {
+ const entryPoints = [join(config.srcQwikRouterDir, 'ssg', 'index.ts')];
await build({
entryPoints,
- outfile: join(config.distQwikRouterPkgDir, 'static', 'index.mjs'),
+ outfile: join(config.distQwikRouterPkgDir, 'ssg', 'index.mjs'),
bundle: true,
platform: 'neutral',
format: 'esm',
@@ -636,7 +636,7 @@ async function buildStatic(config: BuildConfig) {
await build({
entryPoints,
- outfile: join(config.distQwikRouterPkgDir, 'static', 'index.cjs'),
+ outfile: join(config.distQwikRouterPkgDir, 'ssg', 'index.cjs'),
bundle: true,
platform: 'node',
target: nodeTarget,
@@ -644,12 +644,12 @@ async function buildStatic(config: BuildConfig) {
});
}
-async function buildStaticDeno(config: BuildConfig) {
- const entryPoints = [join(config.srcQwikRouterDir, 'static', 'deno', 'index.ts')];
+async function buildSsgDeno(config: BuildConfig) {
+ const entryPoints = [join(config.srcQwikRouterDir, 'ssg', 'deno', 'index.ts')];
await build({
entryPoints,
- outfile: join(config.distQwikRouterPkgDir, 'static', 'deno.mjs'),
+ outfile: join(config.distQwikRouterPkgDir, 'ssg', 'deno.mjs'),
bundle: true,
platform: 'neutral',
format: 'esm',
@@ -657,8 +657,8 @@ async function buildStaticDeno(config: BuildConfig) {
});
}
-async function buildStaticNode(config: BuildConfig) {
- const entryPoints = [join(config.srcQwikRouterDir, 'static', 'node', 'index.ts')];
+async function buildSsgNode(config: BuildConfig) {
+ const entryPoints = [join(config.srcQwikRouterDir, 'ssg', 'node', 'index.ts')];
const external = [
'@qwik.dev/core',
@@ -679,7 +679,7 @@ async function buildStaticNode(config: BuildConfig) {
await build({
entryPoints,
- outfile: join(config.distQwikRouterPkgDir, 'static', 'node.mjs'),
+ outfile: join(config.distQwikRouterPkgDir, 'ssg', 'node.mjs'),
bundle: true,
platform: 'node',
target: nodeTarget,
@@ -690,7 +690,7 @@ async function buildStaticNode(config: BuildConfig) {
await build({
entryPoints,
- outfile: join(config.distQwikRouterPkgDir, 'static', 'node.cjs'),
+ outfile: join(config.distQwikRouterPkgDir, 'ssg', 'node.cjs'),
bundle: true,
platform: 'node',
target: nodeTarget,
@@ -704,8 +704,8 @@ function resolveRequestHandler(path: string) {
return importPath(/middleware\/request-handler/, path);
}
-function resolveStatic(path: string) {
- return importPath(/static$/, path);
+function resolveSsg(path: string) {
+ return importPath(/ssg$/, path);
}
function resolveAdapterShared(path: string) {
@@ -720,7 +720,7 @@ const ADAPTER_EXTERNALS = [
'@qwik.dev/core/server',
'@qwik.dev/core/optimizer',
'@qwik.dev/router',
- '@qwik.dev/router/static',
+ '@qwik.dev/router/ssg',
'@qwik.dev/router/middleware/request-handler',
];
@@ -729,7 +729,7 @@ const MIDDLEWARE_EXTERNALS = [
'@qwik.dev/core/optimizer',
'@qwik.dev/core/server',
'@qwik.dev/router',
- '@qwik.dev/router/static',
+ '@qwik.dev/router/ssg',
'@qwik-router-config',
'@qwik-router-not-found-paths',
'@qwik-router-static-paths',
diff --git a/starters/adapters/aws-lambda/adapters/aws-lambda/vite.config.mts b/starters/adapters/aws-lambda/adapters/aws-lambda/vite.config.mts
index c82e07b31a8..87113c81ac6 100755
--- a/starters/adapters/aws-lambda/adapters/aws-lambda/vite.config.mts
+++ b/starters/adapters/aws-lambda/adapters/aws-lambda/vite.config.mts
@@ -13,7 +13,7 @@ export default extendConfig(baseConfig, () => {
minify: false,
ssr: true,
rollupOptions: {
- input: ["./src/entry_aws-lambda.tsx", "@qwik-router-config"],
+ input: ["./src/entry_aws-lambda.tsx"],
},
},
plugins: [nodeServerAdapter({ name: "aws-lambda" })],
diff --git a/starters/adapters/aws-lambda/src/entry_aws-lambda.tsx b/starters/adapters/aws-lambda/src/entry_aws-lambda.tsx
index 2648f266ade..73ae6ec3d25 100755
--- a/starters/adapters/aws-lambda/src/entry_aws-lambda.tsx
+++ b/starters/adapters/aws-lambda/src/entry_aws-lambda.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/aws/
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import {
createQwikRouter,
type PlatformAwsLambda,
@@ -20,10 +19,7 @@ declare global {
interface QwikRouterPlatform extends PlatformAwsLambda {}
}
-export const { handle } = createQwikRouter({
- render,
- qwikRouterConfig,
-});
+export const { handle } = createQwikRouter({ render });
export const qwikApp = serverless({ handle }, { binary: true });
// handler is the default export for the lambda functions
diff --git a/starters/adapters/azure-swa/adapters/azure-swa/vite.config.mts b/starters/adapters/azure-swa/adapters/azure-swa/vite.config.mts
index ba1c28f3f1b..7315be0375f 100644
--- a/starters/adapters/azure-swa/adapters/azure-swa/vite.config.mts
+++ b/starters/adapters/azure-swa/adapters/azure-swa/vite.config.mts
@@ -8,7 +8,7 @@ export default extendConfig(baseConfig, () => {
ssr: true,
outDir: "azure-functions/render",
rollupOptions: {
- input: ["src/entry.azure-swa.tsx", "@qwik-router-config"],
+ input: ["src/entry.azure-swa.tsx"],
output: {
entryFileNames: `[name].[hash].mjs`,
chunkFileNames: `[name].[hash].mjs`,
diff --git a/starters/adapters/azure-swa/src/entry.azure-swa.tsx b/starters/adapters/azure-swa/src/entry.azure-swa.tsx
index 31c9041a334..ade00a111de 100644
--- a/starters/adapters/azure-swa/src/entry.azure-swa.tsx
+++ b/starters/adapters/azure-swa/src/entry.azure-swa.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/azure-swa/
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import {
createQwikRouter,
type PlatformAzure,
@@ -18,4 +17,4 @@ declare global {
interface QwikRouterPlatform extends PlatformAzure {}
}
-export default createQwikRouter({ render, qwikRouterConfig });
+export default createQwikRouter({ render });
diff --git a/starters/adapters/bun/adapters/bun/vite.config.mts b/starters/adapters/bun/adapters/bun/vite.config.mts
index 0b084c77d0a..7a9e52d6ae5 100644
--- a/starters/adapters/bun/adapters/bun/vite.config.mts
+++ b/starters/adapters/bun/adapters/bun/vite.config.mts
@@ -11,7 +11,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ["src/entry.bun.ts", "@qwik-router-config"],
+ input: ["src/entry.bun.ts"],
},
minify: false,
},
diff --git a/starters/adapters/bun/src/entry.bun.ts b/starters/adapters/bun/src/entry.bun.ts
index fec8caea392..57008a56f9e 100644
--- a/starters/adapters/bun/src/entry.bun.ts
+++ b/starters/adapters/bun/src/entry.bun.ts
@@ -8,14 +8,12 @@
* - https://bun.sh/docs/api/http
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import { createQwikRouter } from "@qwik.dev/router/middleware/bun";
import render from "./entry.ssr";
// Create the Qwik Router Bun middleware
const { router, notFound, staticFile } = createQwikRouter({
render,
- qwikRouterConfig,
static: {
cacheControl: "public, max-age=31536000, immutable",
},
diff --git a/starters/adapters/cloud-run/adapters/cloud-run/vite.config.mts b/starters/adapters/cloud-run/adapters/cloud-run/vite.config.mts
index b282e4ced32..603f91c4da6 100644
--- a/starters/adapters/cloud-run/adapters/cloud-run/vite.config.mts
+++ b/starters/adapters/cloud-run/adapters/cloud-run/vite.config.mts
@@ -7,7 +7,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ["src/entry.cloud-run.tsx", "@qwik-router-config"],
+ input: ["src/entry.cloud-run.tsx"],
},
},
plugins: [cloudRunAdapter()],
diff --git a/starters/adapters/cloud-run/src/entry.cloud-run.tsx b/starters/adapters/cloud-run/src/entry.cloud-run.tsx
index 10d19256300..c1f36a4349c 100644
--- a/starters/adapters/cloud-run/src/entry.cloud-run.tsx
+++ b/starters/adapters/cloud-run/src/entry.cloud-run.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/gcp-cloud-run/
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import {
createQwikRouter,
type PlatformNode,
@@ -50,7 +49,6 @@ const DEFAULT_HEADERS = {
const { router, notFound, staticFile } = createQwikRouter({
render,
- qwikRouterConfig,
static: {
cacheControl: "public, max-age=31536000, immutable",
},
diff --git a/starters/adapters/cloudflare-pages/adapters/cloudflare-pages/vite.config.mts b/starters/adapters/cloudflare-pages/adapters/cloudflare-pages/vite.config.mts
index 46de395d49f..bc5079b4f25 100644
--- a/starters/adapters/cloudflare-pages/adapters/cloudflare-pages/vite.config.mts
+++ b/starters/adapters/cloudflare-pages/adapters/cloudflare-pages/vite.config.mts
@@ -7,7 +7,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ["src/entry.cloudflare-pages.tsx", "@qwik-router-config"],
+ input: ["src/entry.cloudflare-pages.tsx"],
},
},
plugins: [cloudflarePagesAdapter()],
diff --git a/starters/adapters/cloudflare-pages/src/entry.cloudflare-pages.tsx b/starters/adapters/cloudflare-pages/src/entry.cloudflare-pages.tsx
index 10447b03cd2..5ef2e523fd6 100644
--- a/starters/adapters/cloudflare-pages/src/entry.cloudflare-pages.tsx
+++ b/starters/adapters/cloudflare-pages/src/entry.cloudflare-pages.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/cloudflare-pages/
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import {
createQwikRouter,
type PlatformCloudflarePages,
@@ -18,6 +17,6 @@ declare global {
interface QwikRouterPlatform extends PlatformCloudflarePages {}
}
-const fetch = createQwikRouter({ render, qwikRouterConfig });
+const fetch = createQwikRouter({ render });
export { fetch };
diff --git a/starters/adapters/deno/adapters/deno/vite.config.mts b/starters/adapters/deno/adapters/deno/vite.config.mts
index aa12b1e1dc4..bb43565fa66 100644
--- a/starters/adapters/deno/adapters/deno/vite.config.mts
+++ b/starters/adapters/deno/adapters/deno/vite.config.mts
@@ -7,7 +7,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ["src/entry.deno.ts", "@qwik-router-config"],
+ input: ["src/entry.deno.ts"],
},
minify: false,
},
diff --git a/starters/adapters/deno/src/entry.deno.ts b/starters/adapters/deno/src/entry.deno.ts
index 01e49772a82..cd401b2d90c 100644
--- a/starters/adapters/deno/src/entry.deno.ts
+++ b/starters/adapters/deno/src/entry.deno.ts
@@ -8,14 +8,12 @@
* - https://docs.deno.com/runtime/tutorials/http_server
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import { createQwikRouter } from "@qwik.dev/router/middleware/deno";
import render from "./entry.ssr";
// Create the Qwik Router Deno middleware
const { router, notFound, staticFile } = createQwikRouter({
render,
- qwikRouterConfig,
static: {
cacheControl: "public, max-age=31536000, immutable",
},
diff --git a/starters/adapters/express/adapters/express/vite.config.mts b/starters/adapters/express/adapters/express/vite.config.mts
index aced53fd5ce..e55ed3cac65 100644
--- a/starters/adapters/express/adapters/express/vite.config.mts
+++ b/starters/adapters/express/adapters/express/vite.config.mts
@@ -7,7 +7,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ["src/entry.express.tsx", "@qwik-router-config"],
+ input: ["src/entry.express.tsx"],
},
},
plugins: [nodeServerAdapter({ name: "express" })],
diff --git a/starters/adapters/express/src/entry.express.tsx b/starters/adapters/express/src/entry.express.tsx
index 12cedfc9510..7da72db8bf2 100644
--- a/starters/adapters/express/src/entry.express.tsx
+++ b/starters/adapters/express/src/entry.express.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/node/
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import {
createQwikRouter,
type PlatformNode,
@@ -33,7 +32,6 @@ const PORT = process.env.PORT ?? 3000;
// Create the Qwik Router Node middleware
const { router, notFound } = createQwikRouter({
render,
- qwikRouterConfig,
// getOrigin(req) {
// // If deploying under a proxy, you may need to build the origin from the request headers
// // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto
diff --git a/starters/adapters/fastify/adapters/fastify/vite.config.mts b/starters/adapters/fastify/adapters/fastify/vite.config.mts
index d9e89807ff1..9009ce633b0 100644
--- a/starters/adapters/fastify/adapters/fastify/vite.config.mts
+++ b/starters/adapters/fastify/adapters/fastify/vite.config.mts
@@ -7,7 +7,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ["src/entry.fastify.tsx", "@qwik-router-config"],
+ input: ["src/entry.fastify.tsx"],
},
},
plugins: [nodeServerAdapter({ name: "fastify" })],
diff --git a/starters/adapters/fastify/src/plugins/fastify-qwik.ts b/starters/adapters/fastify/src/plugins/fastify-qwik.ts
index 1f8a7f483a8..859f0886d34 100644
--- a/starters/adapters/fastify/src/plugins/fastify-qwik.ts
+++ b/starters/adapters/fastify/src/plugins/fastify-qwik.ts
@@ -1,5 +1,4 @@
import fastifyStatic from "@fastify/static";
-import qwikRouterConfig from "@qwik-router-config";
import { createQwikRouter } from "@qwik.dev/router/middleware/node";
import type { FastifyPluginAsync } from "fastify";
import fastifyPlugin from "fastify-plugin";
@@ -12,7 +11,7 @@ export interface FastifyQwikOptions {
assetsDir: string;
}
-const { router, notFound } = createQwikRouter({ render, qwikRouterConfig });
+const { router, notFound } = createQwikRouter({ render });
const qwikPlugin: FastifyPluginAsync = async (
fastify,
diff --git a/starters/adapters/firebase/adapters/firebase/vite.config.mts b/starters/adapters/firebase/adapters/firebase/vite.config.mts
index 7ca9fb9b626..9043a67bcea 100755
--- a/starters/adapters/firebase/adapters/firebase/vite.config.mts
+++ b/starters/adapters/firebase/adapters/firebase/vite.config.mts
@@ -12,7 +12,7 @@ export default extendConfig(baseConfig, () => {
minify: false,
ssr: true,
rollupOptions: {
- input: ["./src/entry-firebase.tsx", "@qwik-router-config"],
+ input: ["./src/entry-firebase.tsx"],
},
outDir: "./functions/server",
},
diff --git a/starters/adapters/firebase/src/entry-firebase.tsx b/starters/adapters/firebase/src/entry-firebase.tsx
index 4bbeb8d7ad7..9a1d7511ae4 100755
--- a/starters/adapters/firebase/src/entry-firebase.tsx
+++ b/starters/adapters/firebase/src/entry-firebase.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/firebase/
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import {
createQwikRouter,
type PlatformFirebase,
@@ -18,4 +17,4 @@ declare global {
interface QwikRouterPlatform extends PlatformFirebase {}
}
-export default createQwikRouter({ render, qwikRouterConfig });
+export default createQwikRouter({ render });
diff --git a/starters/adapters/netlify-edge/adapters/netlify-edge/vite.config.mts b/starters/adapters/netlify-edge/adapters/netlify-edge/vite.config.mts
index 41ea67d9da4..5465edf30c7 100644
--- a/starters/adapters/netlify-edge/adapters/netlify-edge/vite.config.mts
+++ b/starters/adapters/netlify-edge/adapters/netlify-edge/vite.config.mts
@@ -7,7 +7,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ["src/entry.netlify-edge.tsx", "@qwik-router-config"],
+ input: ["src/entry.netlify-edge.tsx"],
},
outDir: ".netlify/edge-functions/entry.netlify-edge",
},
diff --git a/starters/adapters/netlify-edge/src/entry.netlify-edge.tsx b/starters/adapters/netlify-edge/src/entry.netlify-edge.tsx
index e08f0a3a1b4..c5f58696839 100644
--- a/starters/adapters/netlify-edge/src/entry.netlify-edge.tsx
+++ b/starters/adapters/netlify-edge/src/entry.netlify-edge.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/netlify-edge/
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import {
createQwikRouter,
type PlatformNetlify,
@@ -18,4 +17,4 @@ declare global {
interface QwikRouterPlatform extends PlatformNetlify {}
}
-export default createQwikRouter({ render, qwikRouterConfig });
+export default createQwikRouter({ render });
diff --git a/starters/adapters/node-server/adapters/node-server/vite.config.mts b/starters/adapters/node-server/adapters/node-server/vite.config.mts
index 852ee71aa7f..baf5513ff5b 100644
--- a/starters/adapters/node-server/adapters/node-server/vite.config.mts
+++ b/starters/adapters/node-server/adapters/node-server/vite.config.mts
@@ -7,7 +7,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ["src/entry.node-server.tsx", "@qwik-router-config"],
+ input: ["src/entry.node-server.tsx"],
},
},
plugins: [nodeServerAdapter({ name: "node-server" })],
diff --git a/starters/adapters/node-server/src/entry.node-server.tsx b/starters/adapters/node-server/src/entry.node-server.tsx
index 0d2cd8b15e7..0412522e451 100644
--- a/starters/adapters/node-server/src/entry.node-server.tsx
+++ b/starters/adapters/node-server/src/entry.node-server.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/node/
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import { createQwikRouter } from "@qwik.dev/router/middleware/node";
import { createServer } from "node:http";
import render from "./entry.ssr";
@@ -18,7 +17,6 @@ const PORT = process.env.PORT ?? 3004;
// Create the Qwik Router express middleware
const { router, notFound, staticFile } = createQwikRouter({
render,
- qwikRouterConfig,
static: {
cacheControl: "public, max-age=31536000, immutable",
},
diff --git a/starters/adapters/static/README.md b/starters/adapters/ssg/README.md
similarity index 100%
rename from starters/adapters/static/README.md
rename to starters/adapters/ssg/README.md
diff --git a/starters/adapters/static/adapters/static/vite.config.mts b/starters/adapters/ssg/adapters/ssg/vite.config.mts
similarity index 79%
rename from starters/adapters/static/adapters/static/vite.config.mts
rename to starters/adapters/ssg/adapters/ssg/vite.config.mts
index c734c7908d2..d93fbe5614d 100644
--- a/starters/adapters/static/adapters/static/vite.config.mts
+++ b/starters/adapters/ssg/adapters/ssg/vite.config.mts
@@ -1,4 +1,4 @@
-import { staticAdapter } from "@qwik.dev/router/adapters/static/vite";
+import { ssgAdapter } from "@qwik.dev/router/adapters/ssg/vite";
import { extendConfig } from "@qwik.dev/router/vite";
import baseConfig from "../../vite.config.mts";
@@ -11,7 +11,7 @@ export default extendConfig(baseConfig, () => {
},
},
plugins: [
- staticAdapter({
+ ssgAdapter({
origin: "https://yoursite.qwik.dev",
}),
],
diff --git a/starters/adapters/ssg/package.json b/starters/adapters/ssg/package.json
new file mode 100644
index 00000000000..faec4a1653e
--- /dev/null
+++ b/starters/adapters/ssg/package.json
@@ -0,0 +1,19 @@
+{
+ "description": "Static Site Generator",
+ "scripts": {
+ "build.server": "vite build -c adapters/ssg/vite.config.mts"
+ },
+ "__qwik__": {
+ "priority": 10,
+ "displayName": "Adapter: Static Site Generation (.html files)",
+ "docs": [
+ "https://qwik.dev/docs/guides/static-site-generation/"
+ ],
+ "nextSteps": {
+ "lines": [
+ "You have to change the 'origin' url under ssgAdapter",
+ "inside './adapters/ssg/vite.config.mts'"
+ ]
+ }
+ }
+}
diff --git a/starters/adapters/static/package.json b/starters/adapters/static/package.json
deleted file mode 100644
index 0d275dc1fa3..00000000000
--- a/starters/adapters/static/package.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "description": "Static Site Generator",
- "scripts": {
- "build.server": "vite build -c adapters/static/vite.config.mts"
- },
- "__qwik__": {
- "priority": 10,
- "displayName": "Adapter: Static site (.html files)",
- "docs": [
- "https://qwik.dev/docs/guides/static-site-generation/"
- ],
- "nextSteps": {
- "lines": [
- "You have to change the 'origin' url under staticAdapter",
- "inside './adapters/static/vite.config.mts'"
- ]
- }
- }
-}
diff --git a/starters/adapters/vercel-edge/adapters/vercel-edge/vite.config.mts b/starters/adapters/vercel-edge/adapters/vercel-edge/vite.config.mts
index c2147113630..c50bcc0a124 100644
--- a/starters/adapters/vercel-edge/adapters/vercel-edge/vite.config.mts
+++ b/starters/adapters/vercel-edge/adapters/vercel-edge/vite.config.mts
@@ -7,7 +7,7 @@ export default extendConfig(baseConfig, () => {
build: {
ssr: true,
rollupOptions: {
- input: ["src/entry.vercel-edge.tsx", "@qwik-router-config"],
+ input: ["src/entry.vercel-edge.tsx"],
},
outDir: ".vercel/output/functions/_qwik-router.func",
},
diff --git a/starters/adapters/vercel-edge/src/entry.vercel-edge.tsx b/starters/adapters/vercel-edge/src/entry.vercel-edge.tsx
index 208a0497ddb..fd31026de50 100644
--- a/starters/adapters/vercel-edge/src/entry.vercel-edge.tsx
+++ b/starters/adapters/vercel-edge/src/entry.vercel-edge.tsx
@@ -7,7 +7,6 @@
* - https://qwik.dev/docs/deployments/vercel-edge/
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import {
createQwikRouter,
type PlatformVercel,
@@ -18,4 +17,4 @@ declare global {
interface QwikRouterPlatform extends PlatformVercel {}
}
-export default createQwikRouter({ render, qwikRouterConfig });
+export default createQwikRouter({ render });
diff --git a/starters/apps/base/src/entry.preview.tsx b/starters/apps/base/src/entry.preview.tsx
index 7b33ba14fe9..860ecaca285 100644
--- a/starters/apps/base/src/entry.preview.tsx
+++ b/starters/apps/base/src/entry.preview.tsx
@@ -10,12 +10,10 @@
* - https://vitejs.dev/config/preview-options.html#preview-options
*
*/
-import qwikRouterConfig from "@qwik-router-config";
import { createQwikRouter } from "@qwik.dev/router/middleware/node";
-// make sure qwikRouterConfig is imported before entry
import render from "./entry.ssr";
/**
* The default export is the QwikRouter adapter used by Vite preview.
*/
-export default createQwikRouter({ render, qwikRouterConfig });
+export default createQwikRouter({ render });
diff --git a/starters/apps/base/src/entry.ssr.tsx b/starters/apps/base/src/entry.ssr.tsx
index 875f768696d..62fefc67a42 100644
--- a/starters/apps/base/src/entry.ssr.tsx
+++ b/starters/apps/base/src/entry.ssr.tsx
@@ -1,14 +1,10 @@
/**
* WHAT IS THIS FILE?
*
- * SSR entry point, in all cases the application is rendered outside the browser, this
- * entry point will be the common one.
- *
- * - Server (express, cloudflare...)
- * - npm run start
- * - npm run preview
- * - npm run build
+ * SSR renderer function, used for all build/dev targets except client-only.
*
+ * Note that except for client-only, this is the only place the Qwik renderer is called.
+ * On the client, containers resume and do not call render.
*/
import {
renderToStream,
diff --git a/starters/apps/library/src/entry.dev.tsx b/starters/apps/library/src/entry.dev.tsx
deleted file mode 100644
index dba2a868c7b..00000000000
--- a/starters/apps/library/src/entry.dev.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * WHAT IS THIS FILE?
- *
- * Development entry point using only client-side modules:
- * - Do not use this mode in production!
- * - No SSR
- * - No portion of the application is pre-rendered on the server.
- * - All of the application is running eagerly in the browser.
- * - More code is transferred to the browser than in SSR mode.
- * - Optimizer/Serialization/Deserialization code is not exercised!
- */
-import { render, type RenderOptions } from "@qwik.dev/core";
-import Root from "./root";
-
-export default function (opts: RenderOptions) {
- return render(document, , opts);
-}
diff --git a/starters/apps/library/src/entry.ssr.tsx b/starters/apps/library/src/entry.ssr.tsx
deleted file mode 100644
index 23f36fab3c4..00000000000
--- a/starters/apps/library/src/entry.ssr.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * WHAT IS THIS FILE?
- *
- * SSR entry point, in all cases the application is rendered outside the browser, this
- * entry point will be the common one.
- *
- * - Server (express, cloudflare...)
- * - npm run start
- * - npm run preview
- * - npm run build
- *
- */
-import {
- renderToStream,
- type RenderToStreamOptions,
-} from "@qwik.dev/core/server";
-import Root from "./root";
-
-export default function (opts: RenderToStreamOptions) {
- return renderToStream(, opts);
-}
diff --git a/starters/apps/library/src/root.tsx b/starters/apps/library/src/root.tsx
index 2850296ea94..eeb5067ae8d 100644
--- a/starters/apps/library/src/root.tsx
+++ b/starters/apps/library/src/root.tsx
@@ -6,9 +6,15 @@ export default () => {
<>
- Qwik Blank App
+ Qwik Library Starter
+ Qwik Library Starter
+
+ This is a Qwik library starter. Make your components and export them
+ from `src/index.ts`. This playground app will not be bundled with your
+ library.
+
diff --git a/starters/apps/library/vite.config.mts b/starters/apps/library/vite.config.mts
index d1920e36af6..715e8af28c0 100644
--- a/starters/apps/library/vite.config.mts
+++ b/starters/apps/library/vite.config.mts
@@ -12,8 +12,9 @@ export default defineConfig(() => {
build: {
target: "es2020",
lib: {
- entry: "./src/index.ts",
- formats: ["es", "cjs"],
+ entry: "./src/index",
+ formats: ["es", "cjs"] as const,
+ // This adds .qwik so all files are processed by the optimizer
fileName: (format, entryName) =>
`${entryName}.qwik.${format === "es" ? "mjs" : "cjs"}`,
},
diff --git a/starters/apps/preloader-test/src/entry.preview.tsx b/starters/apps/preloader-test/src/entry.preview.tsx
index c20cc8ab962..53576e5fc34 100644
--- a/starters/apps/preloader-test/src/entry.preview.tsx
+++ b/starters/apps/preloader-test/src/entry.preview.tsx
@@ -11,11 +11,9 @@
*
*/
import { createQwikRouter } from "@qwik.dev/router/middleware/node";
-import qwikRouterConfig from "@qwik-router-config";
-// make sure qwikCityPlan is imported before entry
import render from "./entry.ssr";
/**
* The default export is the QwikCity adapter used by Vite preview.
*/
-export default createQwikRouter({ render, qwikRouterConfig });
+export default createQwikRouter({ render });
diff --git a/starters/dev-server.ts b/starters/dev-server.ts
index 65a97aaccb0..c149b9a1fd9 100644
--- a/starters/dev-server.ts
+++ b/starters/dev-server.ts
@@ -143,11 +143,9 @@ async function buildApp(
load(id) {
if (id.endsWith(qwikRouterVirtualEntry)) {
return `import { createQwikRouter } from '@qwik.dev/router/middleware/node';
-import qwikRouterConfig from '@qwik-router-config';
import render from '${escapeChars(resolve(appSrcDir, "entry.ssr"))}';
const { router, notFound } = createQwikRouter({
render,
- qwikRouterConfig,
base: '${basePath}build/',
});
export {
@@ -241,6 +239,9 @@ export {
...plugins,
optimizer.qwikVite({
experimental: ["preventNavigate", "enableRequestRewrite"],
+ ssr: {
+ manifestInput: clientManifest,
+ },
}),
],
define: {
|