Skip to content

Commit cc53b20

Browse files
committedSep 30, 2024
Initial commit ⚡️
0 parents  commit cc53b20

24 files changed

+768
-0
lines changed
 

‎.eslintignore

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
**/*.log
2+
**/.DS_Store
3+
*.
4+
.vscode/settings.json
5+
.history
6+
.yarn
7+
bazel-*
8+
bazel-bin
9+
bazel-out
10+
bazel-qwik
11+
bazel-testlogs
12+
dist
13+
dist-dev
14+
lib
15+
lib-types
16+
etc
17+
external
18+
node_modules
19+
temp
20+
tsc-out
21+
tsdoc-metadata.json
22+
target
23+
output
24+
rollup.config.js
25+
build
26+
.cache
27+
.vscode
28+
.rollup.cache
29+
dist
30+
tsconfig.tsbuildinfo
31+
vite.config.ts
32+
*.spec.tsx
33+
*.spec.ts
34+
.netlify
35+
pnpm-lock.yaml
36+
package-lock.json
37+
yarn.lock
38+
server

‎.eslintrc.cjs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
module.exports = {
2+
root: true,
3+
env: {
4+
browser: true,
5+
es2021: true,
6+
node: true,
7+
},
8+
extends: [
9+
"eslint:recommended",
10+
"plugin:@typescript-eslint/recommended",
11+
"plugin:qwik/recommended",
12+
],
13+
parser: "@typescript-eslint/parser",
14+
parserOptions: {
15+
tsconfigRootDir: __dirname,
16+
project: ["./tsconfig.json"],
17+
ecmaVersion: 2021,
18+
sourceType: "module",
19+
ecmaFeatures: {
20+
jsx: true,
21+
},
22+
},
23+
plugins: ["@typescript-eslint"],
24+
rules: {
25+
"@typescript-eslint/no-explicit-any": "off",
26+
"@typescript-eslint/explicit-module-boundary-types": "off",
27+
"@typescript-eslint/no-inferrable-types": "off",
28+
"@typescript-eslint/no-non-null-assertion": "off",
29+
"@typescript-eslint/no-empty-interface": "off",
30+
"@typescript-eslint/no-namespace": "off",
31+
"@typescript-eslint/no-empty-function": "off",
32+
"@typescript-eslint/no-this-alias": "off",
33+
"@typescript-eslint/ban-types": "off",
34+
"@typescript-eslint/ban-ts-comment": "off",
35+
"prefer-spread": "off",
36+
"no-case-declarations": "off",
37+
"no-console": "off",
38+
"@typescript-eslint/no-unused-vars": ["error"],
39+
"@typescript-eslint/consistent-type-imports": "warn",
40+
"@typescript-eslint/no-unnecessary-condition": "warn",
41+
},
42+
};

‎.gitignore

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Build
2+
/dist
3+
/lib
4+
/lib-types
5+
/server
6+
7+
# Development
8+
node_modules
9+
.env
10+
*.local
11+
12+
# Cache
13+
.cache
14+
.mf
15+
.rollup.cache
16+
tsconfig.tsbuildinfo
17+
18+
# Logs
19+
logs
20+
*.log
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*
24+
pnpm-debug.log*
25+
lerna-debug.log*
26+
27+
# Editor
28+
.vscode/*
29+
!.vscode/launch.json
30+
!.vscode/*.code-snippets
31+
32+
.idea
33+
.DS_Store
34+
*.suo
35+
*.ntvs*
36+
*.njsproj
37+
*.sln
38+
*.sw?
39+
40+
# Yarn
41+
.yarn/*
42+
!.yarn/releases

‎.prettierignore

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
**/*.log
2+
**/.DS_Store
3+
*.
4+
.vscode/settings.json
5+
.history
6+
.yarn
7+
bazel-*
8+
bazel-bin
9+
bazel-out
10+
bazel-qwik
11+
bazel-testlogs
12+
dist
13+
dist-dev
14+
lib
15+
lib-types
16+
etc
17+
external
18+
node_modules
19+
temp
20+
tsc-out
21+
tsdoc-metadata.json
22+
target
23+
output
24+
rollup.config.js
25+
build
26+
.cache
27+
.vscode
28+
.rollup.cache
29+
tsconfig.tsbuildinfo
30+
vite.config.ts
31+
*.spec.tsx
32+
*.spec.ts
33+
.netlify
34+
pnpm-lock.yaml
35+
package-lock.json
36+
yarn.lock
37+
server

‎.vscode/launch.json

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Launch Chrome",
9+
"request": "launch",
10+
"type": "chrome",
11+
"url": "http://localhost:5173",
12+
"webRoot": "${workspaceFolder}"
13+
},
14+
{
15+
"type": "node",
16+
"name": "dev.debug",
17+
"request": "launch",
18+
"skipFiles": ["<node_internals>/**"],
19+
"cwd": "${workspaceFolder}",
20+
"program": "${workspaceFolder}/node_modules/vite/bin/vite.js",
21+
"args": ["--mode", "ssr", "--force"]
22+
}
23+
]
24+
}

‎.vscode/qwik-city.code-snippets

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"onRequest": {
3+
"scope": "javascriptreact,typescriptreact",
4+
"prefix": "qonRequest",
5+
"description": "onRequest function for a route index",
6+
"body": [
7+
"export const onRequest: RequestHandler = (request) => {",
8+
" $0",
9+
"};",
10+
],
11+
},
12+
"loader$": {
13+
"scope": "javascriptreact,typescriptreact",
14+
"prefix": "qloader$",
15+
"description": "loader$()",
16+
"body": ["export const $1 = routeLoader$(() => {", " $0", "});"],
17+
},
18+
"action$": {
19+
"scope": "javascriptreact,typescriptreact",
20+
"prefix": "qaction$",
21+
"description": "action$()",
22+
"body": ["export const $1 = routeAction$((data) => {", " $0", "});"],
23+
},
24+
"Full Page": {
25+
"scope": "javascriptreact,typescriptreact",
26+
"prefix": "qpage",
27+
"description": "Simple page component",
28+
"body": [
29+
"import { component$ } from '@builder.io/qwik';",
30+
"",
31+
"export default component$(() => {",
32+
" $0",
33+
"});",
34+
],
35+
},
36+
}

‎.vscode/qwik.code-snippets

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{
2+
"Qwik component (simple)": {
3+
"scope": "javascriptreact,typescriptreact",
4+
"prefix": "qcomponent$",
5+
"description": "Simple Qwik component",
6+
"body": [
7+
"export const ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}} = component$(() => {",
8+
" return <${2:div}>$4</$2>",
9+
"});",
10+
],
11+
},
12+
"Qwik component (props)": {
13+
"scope": "typescriptreact",
14+
"prefix": "qcomponent$ + props",
15+
"description": "Qwik component w/ props",
16+
"body": [
17+
"export interface ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}}Props {",
18+
" $2",
19+
"}",
20+
"",
21+
"export const $1 = component$<$1Props>((props) => {",
22+
" const ${2:count} = useSignal(0);",
23+
" return (",
24+
" <${3:div} on${4:Click}$={(ev) => {$5}}>",
25+
" $6",
26+
" </${3}>",
27+
" );",
28+
"});",
29+
],
30+
},
31+
"Qwik signal": {
32+
"scope": "javascriptreact,typescriptreact",
33+
"prefix": "quseSignal",
34+
"description": "useSignal() declaration",
35+
"body": ["const ${1:foo} = useSignal($2);", "$0"],
36+
},
37+
"Qwik store": {
38+
"scope": "javascriptreact,typescriptreact",
39+
"prefix": "quseStore",
40+
"description": "useStore() declaration",
41+
"body": ["const ${1:state} = useStore({", " $2", "});", "$0"],
42+
},
43+
"$ hook": {
44+
"scope": "javascriptreact,typescriptreact",
45+
"prefix": "q$",
46+
"description": "$() function hook",
47+
"body": ["$(() => {", " $0", "});", ""],
48+
},
49+
"useVisibleTask": {
50+
"scope": "javascriptreact,typescriptreact",
51+
"prefix": "quseVisibleTask",
52+
"description": "useVisibleTask$() function hook",
53+
"body": ["useVisibleTask$(({ track }) => {", " $0", "});", ""],
54+
},
55+
"useTask": {
56+
"scope": "javascriptreact,typescriptreact",
57+
"prefix": "quseTask$",
58+
"description": "useTask$() function hook",
59+
"body": [
60+
"useTask$(({ track }) => {",
61+
" track(() => $1);",
62+
" $0",
63+
"});",
64+
"",
65+
],
66+
},
67+
"useResource": {
68+
"scope": "javascriptreact,typescriptreact",
69+
"prefix": "quseResource$",
70+
"description": "useResource$() declaration",
71+
"body": [
72+
"const $1 = useResource$(({ track, cleanup }) => {",
73+
" $0",
74+
"});",
75+
"",
76+
],
77+
},
78+
}

‎README.md

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Qwik City App ⚡️
2+
3+
- [Qwik Docs](https://qwik.dev/)
4+
- [Discord](https://qwik.dev/chat)
5+
- [Qwik GitHub](https://github.com/QwikDev/qwik)
6+
- [@QwikDev](https://twitter.com/QwikDev)
7+
- [Vite](https://vitejs.dev/)
8+
9+
---
10+
11+
## Project Structure
12+
13+
This project is using Qwik with [QwikCity](https://qwik.dev/qwikcity/overview/). QwikCity is just an extra set of tools on top of Qwik to make it easier to build a full site, including directory-based routing, layouts, and more.
14+
15+
Inside your project, you'll see the following directory structure:
16+
17+
```
18+
├── public/
19+
│ └── ...
20+
└── src/
21+
├── components/
22+
│ └── ...
23+
└── routes/
24+
└── ...
25+
```
26+
27+
- `src/routes`: Provides the directory-based routing, which can include a hierarchy of `layout.tsx` layout files, and an `index.tsx` file as the page. Additionally, `index.ts` files are endpoints. Please see the [routing docs](https://qwik.dev/qwikcity/routing/overview/) for more info.
28+
29+
- `src/components`: Recommended directory for components.
30+
31+
- `public`: Any static assets, like images, can be placed in the public directory. Please see the [Vite public directory](https://vitejs.dev/guide/assets.html#the-public-directory) for more info.
32+
33+
## Add Integrations and deployment
34+
35+
Use the `npm run qwik add` command to add additional integrations. Some examples of integrations includes: Cloudflare, Netlify or Express Server, and the [Static Site Generator (SSG)](https://qwik.dev/qwikcity/guides/static-site-generation/).
36+
37+
```shell
38+
npm run qwik add # or `yarn qwik add`
39+
```
40+
41+
## Development
42+
43+
Development mode uses [Vite's development server](https://vitejs.dev/). The `dev` command will server-side render (SSR) the output during development.
44+
45+
```shell
46+
npm start # or `yarn start`
47+
```
48+
49+
> Note: during dev mode, Vite may request a significant number of `.js` files. This does not represent a Qwik production build.
50+
51+
## Preview
52+
53+
The preview command will create a production build of the client modules, a production build of `src/entry.preview.tsx`, and run a local server. The preview server is only for convenience to preview a production build locally and should not be used as a production server.
54+
55+
```shell
56+
npm run preview # or `yarn preview`
57+
```
58+
59+
## Production
60+
61+
The production build will generate client and server modules by running both client and server build commands. The build command will use Typescript to run a type check on the source code.
62+
63+
```shell
64+
npm run build # or `yarn build`
65+
```

‎package.json

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"name": "my-qwik-empty-starter",
3+
"description": "Blank project with routing included",
4+
"engines": {
5+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
6+
},
7+
"engines-annotation": "Mostly required by sharp which needs a Node-API v9 compatible runtime",
8+
"private": true,
9+
"trustedDependencies": [
10+
"sharp"
11+
],
12+
"trustedDependencies-annotation": "Needed for bun to allow running install scripts",
13+
"type": "module",
14+
"scripts": {
15+
"build": "qwik build",
16+
"build.client": "vite build",
17+
"build.preview": "vite build --ssr src/entry.preview.tsx",
18+
"build.types": "tsc --incremental --noEmit",
19+
"deploy": "echo 'Run \"npm run qwik add\" to install a server adapter'",
20+
"dev": "vite --mode ssr",
21+
"dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force",
22+
"fmt": "prettier --write .",
23+
"fmt.check": "prettier --check .",
24+
"lint": "eslint \"src/**/*.ts*\"",
25+
"preview": "qwik build preview && vite preview --open",
26+
"start": "vite --open --mode ssr",
27+
"qwik": "qwik"
28+
},
29+
"devDependencies": {
30+
"@builder.io/qwik": "^1.9.0",
31+
"@builder.io/qwik-city": "^1.9.0",
32+
"@types/eslint": "8.56.10",
33+
"@types/node": "20.14.11",
34+
"@typescript-eslint/eslint-plugin": "7.16.1",
35+
"@typescript-eslint/parser": "7.16.1",
36+
"eslint": "8.57.0",
37+
"eslint-plugin-qwik": "^1.9.0",
38+
"prettier": "3.3.3",
39+
"typescript": "5.4.5",
40+
"undici": "*",
41+
"vite": "5.3.5",
42+
"vite-tsconfig-paths": "^4.2.1"
43+
}
44+
}

‎public/favicon.svg

+1
Loading

‎public/manifest.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"$schema": "https://json.schemastore.org/web-manifest-combined.json",
3+
"name": "qwik-project-name",
4+
"short_name": "Welcome to Qwik",
5+
"start_url": ".",
6+
"display": "standalone",
7+
"background_color": "#fff",
8+
"description": "A Qwik project app."
9+
}

‎public/robots.txt

Whitespace-only changes.

‎qwik.env.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// This file can be used to add references for global types like `vite/client`.
2+
3+
// Add global `vite/client` types. For more info, see: https://vitejs.dev/guide/features#client-types
4+
/// <reference types="vite/client" />
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { component$ } from "@builder.io/qwik";
2+
import { useDocumentHead, useLocation } from "@builder.io/qwik-city";
3+
4+
/**
5+
* The RouterHead component is placed inside of the document `<head>` element.
6+
*/
7+
export const RouterHead = component$(() => {
8+
const head = useDocumentHead();
9+
const loc = useLocation();
10+
11+
return (
12+
<>
13+
<title>{head.title}</title>
14+
15+
<link rel="canonical" href={loc.url.href} />
16+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
17+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
18+
19+
{head.meta.map((m) => (
20+
<meta key={m.key} {...m} />
21+
))}
22+
23+
{head.links.map((l) => (
24+
<link key={l.key} {...l} />
25+
))}
26+
27+
{head.styles.map((s) => (
28+
<style
29+
key={s.key}
30+
{...s.props}
31+
{...(s.props?.dangerouslySetInnerHTML
32+
? {}
33+
: { dangerouslySetInnerHTML: s.style })}
34+
/>
35+
))}
36+
37+
{head.scripts.map((s) => (
38+
<script
39+
key={s.key}
40+
{...s.props}
41+
{...(s.props?.dangerouslySetInnerHTML
42+
? {}
43+
: { dangerouslySetInnerHTML: s.script })}
44+
/>
45+
))}
46+
</>
47+
);
48+
});

‎src/entry.dev.tsx

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* WHAT IS THIS FILE?
3+
*
4+
* Development entry point using only client-side modules:
5+
* - Do not use this mode in production!
6+
* - No SSR
7+
* - No portion of the application is pre-rendered on the server.
8+
* - All of the application is running eagerly in the browser.
9+
* - More code is transferred to the browser than in SSR mode.
10+
* - Optimizer/Serialization/Deserialization code is not exercised!
11+
*/
12+
import { render, type RenderOptions } from "@builder.io/qwik";
13+
import Root from "./root";
14+
15+
export default function (opts: RenderOptions) {
16+
return render(document, <Root />, opts);
17+
}

‎src/entry.preview.tsx

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* WHAT IS THIS FILE?
3+
*
4+
* It's the bundle entry point for `npm run preview`.
5+
* That is, serving your app built in production mode.
6+
*
7+
* Feel free to modify this file, but don't remove it!
8+
*
9+
* Learn more about Vite's preview command:
10+
* - https://vitejs.dev/config/preview-options.html#preview-options
11+
*
12+
*/
13+
import { createQwikCity } from "@builder.io/qwik-city/middleware/node";
14+
import qwikCityPlan from "@qwik-city-plan";
15+
// make sure qwikCityPlan is imported before entry
16+
import render from "./entry.ssr";
17+
18+
/**
19+
* The default export is the QwikCity adapter used by Vite preview.
20+
*/
21+
export default createQwikCity({ render, qwikCityPlan });

‎src/entry.ssr.tsx

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* WHAT IS THIS FILE?
3+
*
4+
* SSR entry point, in all cases the application is rendered outside the browser, this
5+
* entry point will be the common one.
6+
*
7+
* - Server (express, cloudflare...)
8+
* - npm run start
9+
* - npm run preview
10+
* - npm run build
11+
*
12+
*/
13+
import {
14+
renderToStream,
15+
type RenderToStreamOptions,
16+
} from "@builder.io/qwik/server";
17+
import { manifest } from "@qwik-client-manifest";
18+
import Root from "./root";
19+
20+
export default function (opts: RenderToStreamOptions) {
21+
return renderToStream(<Root />, {
22+
manifest,
23+
...opts,
24+
// Use container attributes to set attributes on the html tag.
25+
containerAttributes: {
26+
lang: "en-us",
27+
...opts.containerAttributes,
28+
},
29+
serverData: {
30+
...opts.serverData,
31+
},
32+
});
33+
}

‎src/global.css

Whitespace-only changes.

‎src/root.tsx

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { component$ } from "@builder.io/qwik";
2+
import {
3+
QwikCityProvider,
4+
RouterOutlet,
5+
ServiceWorkerRegister,
6+
} from "@builder.io/qwik-city";
7+
import { RouterHead } from "./components/router-head/router-head";
8+
import { isDev } from "@builder.io/qwik/build";
9+
10+
import "./global.css";
11+
12+
export default component$(() => {
13+
/**
14+
* The root of a QwikCity site always start with the <QwikCityProvider> component,
15+
* immediately followed by the document's <head> and <body>.
16+
*
17+
* Don't remove the `<head>` and `<body>` elements.
18+
*/
19+
20+
return (
21+
<QwikCityProvider>
22+
<head>
23+
<meta charset="utf-8" />
24+
{!isDev && (
25+
<link
26+
rel="manifest"
27+
href={`${import.meta.env.BASE_URL}manifest.json`}
28+
/>
29+
)}
30+
<RouterHead />
31+
</head>
32+
<body lang="en">
33+
<RouterOutlet />
34+
{!isDev && <ServiceWorkerRegister />}
35+
</body>
36+
</QwikCityProvider>
37+
);
38+
});

‎src/routes/index.tsx

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { component$ } from "@builder.io/qwik";
2+
import type { DocumentHead } from "@builder.io/qwik-city";
3+
4+
export default component$(() => {
5+
return (
6+
<>
7+
<h1>Hi 👋</h1>
8+
<div>
9+
Can't wait to see what you build with qwik!
10+
<br />
11+
Happy coding.
12+
</div>
13+
</>
14+
);
15+
});
16+
17+
export const head: DocumentHead = {
18+
title: "Welcome to Qwik",
19+
meta: [
20+
{
21+
name: "description",
22+
content: "Qwik site description",
23+
},
24+
],
25+
};

‎src/routes/layout.tsx

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { component$, Slot } from "@builder.io/qwik";
2+
import type { RequestHandler } from "@builder.io/qwik-city";
3+
4+
export const onGet: RequestHandler = async ({ cacheControl }) => {
5+
// Control caching for this request for best performance and to reduce hosting costs:
6+
// https://qwik.dev/docs/caching/
7+
cacheControl({
8+
// Always serve a cached response by default, up to a week stale
9+
staleWhileRevalidate: 60 * 60 * 24 * 7,
10+
// Max once every 5 seconds, revalidate on the server to get a fresh version of this page
11+
maxAge: 5,
12+
});
13+
};
14+
15+
export default component$(() => {
16+
return <Slot />;
17+
});

‎src/routes/service-worker.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* WHAT IS THIS FILE?
3+
*
4+
* The service-worker.ts file is used to have state of the art prefetching.
5+
* https://qwik.dev/qwikcity/prefetching/overview/
6+
*
7+
* Qwik uses a service worker to speed up your site and reduce latency, ie, not used in the traditional way of offline.
8+
* You can also use this file to add more functionality that runs in the service worker.
9+
*/
10+
import { setupServiceWorker } from "@builder.io/qwik-city/service-worker";
11+
12+
setupServiceWorker();
13+
14+
addEventListener("install", () => self.skipWaiting());
15+
16+
addEventListener("activate", () => self.clients.claim());
17+
18+
declare const self: ServiceWorkerGlobalScope;

‎tsconfig.json

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"compilerOptions": {
3+
"allowJs": true,
4+
"target": "ES2017",
5+
"module": "ES2022",
6+
"lib": ["es2022", "DOM", "WebWorker", "DOM.Iterable"],
7+
"jsx": "react-jsx",
8+
"jsxImportSource": "@builder.io/qwik",
9+
"strict": true,
10+
"forceConsistentCasingInFileNames": true,
11+
"resolveJsonModule": true,
12+
"moduleResolution": "Bundler",
13+
"esModuleInterop": true,
14+
"skipLibCheck": true,
15+
"incremental": true,
16+
"isolatedModules": true,
17+
"outDir": "tmp",
18+
"noEmit": true,
19+
"paths": {
20+
"~/*": ["./src/*"]
21+
}
22+
},
23+
"files": ["./.eslintrc.cjs"],
24+
"include": ["src", "./*.d.ts", "./*.config.ts"]
25+
}

‎vite.config.ts

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* This is the base config for vite.
3+
* When building, the adapter config is used which loads this file and extends it.
4+
*/
5+
import { defineConfig, type UserConfig } from "vite";
6+
import { qwikVite } from "@builder.io/qwik/optimizer";
7+
import { qwikCity } from "@builder.io/qwik-city/vite";
8+
import tsconfigPaths from "vite-tsconfig-paths";
9+
import pkg from "./package.json";
10+
11+
type PkgDep = Record<string, string>;
12+
const { dependencies = {}, devDependencies = {} } = pkg as any as {
13+
dependencies: PkgDep;
14+
devDependencies: PkgDep;
15+
[key: string]: unknown;
16+
};
17+
errorOnDuplicatesPkgDeps(devDependencies, dependencies);
18+
19+
/**
20+
* Note that Vite normally starts from `index.html` but the qwikCity plugin makes start at `src/entry.ssr.tsx` instead.
21+
*/
22+
export default defineConfig(({ command, mode }): UserConfig => {
23+
return {
24+
plugins: [qwikCity(), qwikVite(), tsconfigPaths()],
25+
// This tells Vite which dependencies to pre-build in dev mode.
26+
optimizeDeps: {
27+
// Put problematic deps that break bundling here, mostly those with binaries.
28+
// For example ['better-sqlite3'] if you use that in server functions.
29+
exclude: [],
30+
},
31+
32+
/**
33+
* This is an advanced setting. It improves the bundling of your server code. To use it, make sure you understand when your consumed packages are dependencies or dev dependencies. (otherwise things will break in production)
34+
*/
35+
// ssr:
36+
// command === "build" && mode === "production"
37+
// ? {
38+
// // All dev dependencies should be bundled in the server build
39+
// noExternal: Object.keys(devDependencies),
40+
// // Anything marked as a dependency will not be bundled
41+
// // These should only be production binary deps (including deps of deps), CLI deps, and their module graph
42+
// // If a dep-of-dep needs to be external, add it here
43+
// // For example, if something uses `bcrypt` but you don't have it as a dep, you can write
44+
// // external: [...Object.keys(dependencies), 'bcrypt']
45+
// external: Object.keys(dependencies),
46+
// }
47+
// : undefined,
48+
49+
server: {
50+
headers: {
51+
// Don't cache the server response in dev mode
52+
"Cache-Control": "public, max-age=0",
53+
},
54+
},
55+
preview: {
56+
headers: {
57+
// Do cache the server response in preview (non-adapter production build)
58+
"Cache-Control": "public, max-age=600",
59+
},
60+
},
61+
};
62+
});
63+
64+
// *** utils ***
65+
66+
/**
67+
* Function to identify duplicate dependencies and throw an error
68+
* @param {Object} devDependencies - List of development dependencies
69+
* @param {Object} dependencies - List of production dependencies
70+
*/
71+
function errorOnDuplicatesPkgDeps(
72+
devDependencies: PkgDep,
73+
dependencies: PkgDep,
74+
) {
75+
let msg = "";
76+
// Create an array 'duplicateDeps' by filtering devDependencies.
77+
// If a dependency also exists in dependencies, it is considered a duplicate.
78+
const duplicateDeps = Object.keys(devDependencies).filter(
79+
(dep) => dependencies[dep],
80+
);
81+
82+
// include any known qwik packages
83+
const qwikPkg = Object.keys(dependencies).filter((value) =>
84+
/qwik/i.test(value),
85+
);
86+
87+
// any errors for missing "qwik-city-plan"
88+
// [PLUGIN_ERROR]: Invalid module "@qwik-city-plan" is not a valid package
89+
msg = `Move qwik packages ${qwikPkg.join(", ")} to devDependencies`;
90+
91+
if (qwikPkg.length > 0) {
92+
throw new Error(msg);
93+
}
94+
95+
// Format the error message with the duplicates list.
96+
// The `join` function is used to represent the elements of the 'duplicateDeps' array as a comma-separated string.
97+
msg = `
98+
Warning: The dependency "${duplicateDeps.join(", ")}" is listed in both "devDependencies" and "dependencies".
99+
Please move the duplicated dependencies to "devDependencies" only and remove it from "dependencies"
100+
`;
101+
102+
// Throw an error with the constructed message.
103+
if (duplicateDeps.length > 0) {
104+
throw new Error(msg);
105+
}
106+
}

0 commit comments

Comments
 (0)
Please sign in to comment.