@qwik.dev/core 2.0.0-beta.18 → 2.0.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/backpatch/package.json +1 -1
  2. package/dist/build/package.json +1 -1
  3. package/dist/cli.mjs +2 -2
  4. package/dist/core-internal.d.ts +10 -3
  5. package/dist/core.min.mjs +1 -1
  6. package/dist/core.mjs +107 -91
  7. package/dist/core.mjs.map +1 -1
  8. package/dist/core.prod.mjs +64 -61
  9. package/dist/loader/package.json +1 -1
  10. package/dist/optimizer.mjs +889 -884
  11. package/dist/server.mjs +4 -3
  12. package/dist/starters/adapters/cloudflare-workers/README.md +52 -0
  13. package/dist/starters/adapters/cloudflare-workers/adapters/cloudflare-workers/vite.config.ts +15 -0
  14. package/dist/starters/adapters/cloudflare-workers/gitignore +3 -0
  15. package/dist/starters/adapters/cloudflare-workers/package.json +31 -0
  16. package/dist/starters/adapters/cloudflare-workers/public/.assetsignore +4 -0
  17. package/dist/starters/adapters/cloudflare-workers/public/_headers +11 -0
  18. package/dist/starters/adapters/cloudflare-workers/public/_redirects +1 -0
  19. package/dist/starters/adapters/cloudflare-workers/src/entry.cloudflare-pages.tsx +23 -0
  20. package/dist/starters/adapters/cloudflare-workers/worker-configuration.d.ts +5 -0
  21. package/dist/starters/adapters/cloudflare-workers/wrangler.jsonc +41 -0
  22. package/dist/starters/adapters/express/package.json +1 -1
  23. package/dist/starters/features/compiled-i18n/package.json +37 -0
  24. package/dist/starters/features/compiled-i18n/src/components/locale-selector/locale-selector.tsx +30 -0
  25. package/dist/starters/features/{localize → compiled-i18n}/src/entry.ssr.tsx +7 -2
  26. package/dist/starters/features/compiled-i18n/src/routes/plugin@compiled-i18n.ts +28 -0
  27. package/dist/starters/features/cypress/src/actions/example.action.ts +5 -0
  28. package/dist/starters/features/cypress/src/components/example/example.cy.tsx +50 -8
  29. package/dist/starters/features/cypress/src/components/example/example.tsx +13 -3
  30. package/dist/starters/features/cypress/src/loaders/example.loader.ts +5 -0
  31. package/dist/testing/index.mjs +71 -44
  32. package/dist/testing/package.json +1 -1
  33. package/package.json +2 -2
  34. package/dist/starters/features/localize/package.json +0 -37
  35. package/dist/starters/features/localize/src/locales/message.en.json +0 -8
  36. package/dist/starters/features/localize/src/locales/message.it.json +0 -8
  37. package/dist/starters/features/localize/src/routes/[locale]/i18n-utils.ts +0 -94
  38. package/dist/starters/features/localize/src/routes/[locale]/index.tsx +0 -52
  39. package/dist/starters/features/localize/src/routes/[locale]/layout.tsx +0 -12
package/dist/server.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * @qwik.dev/core/server 2.0.0-beta.18-dev+a8081d4
3
+ * @qwik.dev/core/server 2.0.0-beta.19-dev+0d046fb
4
4
  * Copyright QwikDev. All Rights Reserved.
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://github.com/QwikDev/qwik/blob/main/LICENSE
@@ -1174,7 +1174,7 @@ function getBuildBase(opts) {
1174
1174
  return `${import.meta.env.BASE_URL || "/"}build/`;
1175
1175
  }
1176
1176
  var versions = {
1177
- qwik: "2.0.0-beta.18-dev+a8081d4",
1177
+ qwik: "2.0.0-beta.19-dev+0d046fb",
1178
1178
  qwikDom: "2.1.19"
1179
1179
  };
1180
1180
 
@@ -1214,7 +1214,7 @@ function flattenPrefetchResources(prefetchResources) {
1214
1214
  // packages/qwik/src/server/preload-strategy.ts
1215
1215
  var getBundles = (qrls) => {
1216
1216
  const platform = getPlatform();
1217
- return qrls?.map((qrl) => {
1217
+ const bundles2 = qrls?.map((qrl) => {
1218
1218
  const symbol = qrl.$symbol$;
1219
1219
  const chunk = qrl.$chunk$;
1220
1220
  const result = platform.chunkForSymbol(symbol, chunk, qrl.dev?.file);
@@ -1223,6 +1223,7 @@ var getBundles = (qrls) => {
1223
1223
  }
1224
1224
  return chunk;
1225
1225
  }).filter(Boolean);
1226
+ return [...new Set(bundles2)];
1226
1227
  };
1227
1228
  function getPreloadPaths(qrls, opts, resolvedManifest) {
1228
1229
  const prefetchStrategy = opts.prefetchStrategy;
@@ -0,0 +1,52 @@
1
+ ## Cloudflare Workers
2
+
3
+ Cloudflare's [wrangler](https://github.com/cloudflare/wrangler) CLI can be used to preview a production build locally. To start a local server, run:
4
+
5
+ ```
6
+ npm run serve
7
+ ```
8
+
9
+ Then visit [http://localhost:8787/](http://localhost:8787/)
10
+
11
+ ### Deployments
12
+
13
+ [Cloudflare Workers](https://workers.cloudflare.com/) can be deployed using the [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/).
14
+
15
+ If you don't already have an account, then [create a Cloudflare account here](https://dash.cloudflare.com/sign-up/workers-and-pages).
16
+
17
+ Once authenticated, you can deploy your Worker:
18
+
19
+ ```
20
+ npm run deploy
21
+ ```
22
+
23
+ ### Configuration
24
+
25
+ The `wrangler.jsonc` file contains your Worker configuration. Key settings include:
26
+
27
+ - **name**: Your Worker's name
28
+ - **main**: Path to your Worker script (default: `./dist/_worker.js`)
29
+ - **compatibility_date**: The date used for compatibility with the Workers runtime
30
+ - **assets**: Configuration for serving static assets
31
+ - **bindings**: Resources your Worker can interact with (KV, R2, D1, etc.)
32
+
33
+ After adding any binding, use this command to regenerate the worker-configuration.d.ts file
34
+
35
+ ```
36
+ npm run cf-typegen
37
+ ```
38
+
39
+ For more details, see the [Wrangler configuration documentation](https://developers.cloudflare.com/workers/wrangler/configuration/).
40
+
41
+ ### Bindings
42
+
43
+ Cloudflare Workers can interact with various Cloudflare resources through bindings:
44
+
45
+ - **KV**: Key-value storage
46
+ - **R2**: Object storage
47
+ - **D1**: SQL database
48
+ - **Durable Objects**: Strongly consistent storage
49
+ - **Queues**: Message queues
50
+ - **AI**: AI inference
51
+
52
+ Configure bindings in your `wrangler.jsonc` file. See the [bindings documentation](https://developers.cloudflare.com/workers/runtime-apis/bindings/) for more information.
@@ -0,0 +1,15 @@
1
+ import { cloudflarePagesAdapter as cloudflareWorkersAdapter } from "@builder.io/qwik-city/adapters/cloudflare-pages/vite";
2
+ import { extendConfig } from "@builder.io/qwik-city/vite";
3
+ import baseConfig from "../../vite.config";
4
+
5
+ export default extendConfig(baseConfig, () => {
6
+ return {
7
+ build: {
8
+ ssr: true,
9
+ rollupOptions: {
10
+ input: ["src/entry.cloudflare-pages.tsx", "@qwik-city-plan"],
11
+ },
12
+ },
13
+ plugins: [cloudflareWorkersAdapter()],
14
+ };
15
+ });
@@ -0,0 +1,3 @@
1
+ # Cloudflare
2
+ functions/**/*.js
3
+ .wrangler/
@@ -0,0 +1,31 @@
1
+ {
2
+ "description": "Cloudflare Workers",
3
+ "scripts": {
4
+ "build.server": "qwik check-client src dist && vite build -c adapters/cloudflare-workers/vite.config.ts",
5
+ "deploy": "wrangler deploy",
6
+ "serve": "wrangler dev",
7
+ "cf-typegen": "wrangler types"
8
+ },
9
+ "devDependencies": {
10
+ "@cloudflare/workers-types": "^4.20251228.0",
11
+ "wrangler": "^3.0.0"
12
+ },
13
+ "__qwik__": {
14
+ "priority": 40,
15
+ "displayName": "Adapter: Cloudflare Workers",
16
+ "docs": [
17
+ "https://qwik.dev/deployments/cloudflare-workers/",
18
+ "https://developers.cloudflare.com/workers"
19
+ ],
20
+ "nextSteps": {
21
+ "title": "Next Steps",
22
+ "lines": [
23
+ "Make sure to follow the instructions in the [Cloudflare Workers documentation](https://qwik.dev/deployments/cloudflare-workers/) to setup your Qwik app.",
24
+ "Now you can build and deploy to Cloudflare Workers with:",
25
+ "",
26
+ "- pnpm run build: production build for Cloudflare",
27
+ "- pnpm run deploy: it will use the Cloudflare CLI to deploy your site"
28
+ ]
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,4 @@
1
+ _worker.js
2
+ _routes.json
3
+ _headers
4
+ _redirects
@@ -0,0 +1,11 @@
1
+ # https://developers.cloudflare.com/pages/platform/headers/
2
+
3
+ /*service-worker.js
4
+ Cache-Control: no-store
5
+ Content-Type: application/javascript
6
+ X-Content-Type-Options: nosniff
7
+
8
+ /build/*
9
+ Cache-Control: public, max-age=31536000, s-maxage=31536000, immutable
10
+ /assets/*
11
+ Cache-Control: public, max-age=31536000, s-maxage=31536000, immutable
@@ -0,0 +1 @@
1
+ # https://developers.cloudflare.com/pages/platform/redirects/
@@ -0,0 +1,23 @@
1
+ /*
2
+ * WHAT IS THIS FILE?
3
+ *
4
+ * It's the entry point for Cloudflare Workers when building for production.
5
+ *
6
+ * Learn more about the Cloudflare Workers integration here:
7
+ * - https://qwik.dev/docs/deployments/cloudflare-workers/
8
+ *
9
+ */
10
+ import {
11
+ createQwikCity,
12
+ type PlatformCloudflarePages as PlatformCloudflareWorkers,
13
+ } from "@builder.io/qwik-city/middleware/cloudflare-pages";
14
+ import qwikCityPlan from "@qwik-city-plan";
15
+ import render from "./entry.ssr";
16
+
17
+ declare global {
18
+ type QwikCityPlatform = PlatformCloudflareWorkers;
19
+ }
20
+
21
+ const fetch = createQwikCity({ render, qwikCityPlan });
22
+
23
+ export { fetch };
@@ -0,0 +1,5 @@
1
+ // Generated by Wrangler
2
+ // After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen`
3
+ interface Env {
4
+ ASSET: Fetcher;
5
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * For more details on how to configure Wrangler, refer to:
3
+ * https://developers.cloudflare.com/workers/wrangler/configuration/
4
+ */
5
+ {
6
+ "$schema": "node_modules/wrangler/config-schema.json",
7
+ "name": "my-qwik-app",
8
+ "main": "./dist/_worker.js",
9
+ "compatibility_date": "2025-12-28",
10
+ "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
11
+ "assets": {
12
+ "binding": "ASSET",
13
+ "directory": "./dist",
14
+ },
15
+ "observability": {
16
+ "enabled": true,
17
+ },
18
+ /**
19
+ * Smart Placement
20
+ * https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
21
+ */
22
+ // "placement": { "mode": "smart" }
23
+ /**
24
+ * Bindings
25
+ * Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including
26
+ * databases, object storage, AI inference, real-time communication and more.
27
+ * https://developers.cloudflare.com/workers/runtime-apis/bindings/
28
+ */
29
+ /**
30
+ * Environment Variables
31
+ * https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
32
+ * Note: Use secrets to store sensitive data.
33
+ * https://developers.cloudflare.com/workers/configuration/secrets/
34
+ */
35
+ // "vars": { "MY_VARIABLE": "production_value" }
36
+ /**
37
+ * Service Bindings (communicate between multiple Workers)
38
+ * https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
39
+ */
40
+ // "services": [ { "binding": "MY_SERVICE", "service": "my-service" } ]
41
+ }
@@ -5,7 +5,7 @@
5
5
  "serve": "node server/entry.express"
6
6
  },
7
7
  "dependencies": {
8
- "express": "4.20.0"
8
+ "express": "4.22.0"
9
9
  },
10
10
  "devDependencies": {
11
11
  "@types/compression": "^1.7.2",
@@ -0,0 +1,37 @@
1
+ {
2
+ "description": "Add compiled-i18n to your Qwik app",
3
+ "__qwik__": {
4
+ "displayName": "Integration: compiled-i18n (compile time translations)",
5
+ "priority": -10,
6
+ "viteConfig": {
7
+ "imports": [
8
+ {
9
+ "namedImports": [
10
+ "i18nPlugin"
11
+ ],
12
+ "importPath": "compiled-i18n/vite"
13
+ }
14
+ ],
15
+ "vitePlugins": [
16
+ "i18nPlugin({ locales: ['en'] })"
17
+ ]
18
+ },
19
+ "docs": [
20
+ "https://qwik.dev/docs/integrations/i18n/#localize",
21
+ "https://github.com/wmertens/compiled-i18n/blob/main/Readme.md"
22
+ ],
23
+ "nextSteps": {
24
+ "title": "Next Steps",
25
+ "lines": [
26
+ " - Change the `locales` array in the vite config to add more languages",
27
+ " - Use the `src/components/locale-selector/locale-selector.tsx` component to switch languages",
28
+ "",
29
+ " Check out the compiled-i18n docs:",
30
+ " - https://github.com/wmertens/compiled-i18n/blob/main/Readme.md"
31
+ ]
32
+ }
33
+ },
34
+ "devDependencies": {
35
+ "compiled-i18n": "latest"
36
+ }
37
+ }
@@ -0,0 +1,30 @@
1
+ import { component$, getLocale } from "@builder.io/qwik";
2
+ import { _, locales } from "compiled-i18n";
3
+
4
+ export const LocaleSelector = component$(() => {
5
+ const currentLocale = getLocale();
6
+ return (
7
+ <>
8
+ {locales.map((locale) => {
9
+ const isCurrent = locale === currentLocale;
10
+ return (
11
+ // Note, you must use `<a>` and not `<Link>` so the page reloads
12
+ <a
13
+ key={locale}
14
+ // When using route-based locale selection, build the URL here
15
+ href={`?locale=${locale}`}
16
+ aria-disabled={isCurrent}
17
+ class={
18
+ "btn btn-ghost btn-sm" +
19
+ (isCurrent
20
+ ? " bg-neutralContent text-neutral pointer-events-none"
21
+ : " bg-base-100 text-base-content")
22
+ }
23
+ >
24
+ {locale}
25
+ </a>
26
+ );
27
+ })}
28
+ </>
29
+ );
30
+ });
@@ -7,15 +7,20 @@
7
7
  * On the client, containers resume and do not call render.
8
8
  */
9
9
  import { createRenderer } from "@qwik.dev/router";
10
+ import { extractBase, setSsrLocaleGetter } from "compiled-i18n/qwik";
10
11
  import Root from "./root";
11
- import { extractBase } from "./routes/[locale]/i18n-utils";
12
+
13
+ setSsrLocaleGetter();
12
14
 
13
15
  export default createRenderer((opts) => {
14
16
  return {
15
17
  jsx: <Root />,
16
18
  options: {
17
19
  ...opts,
18
- base: extractBase, // determine the base URL for the client code
20
+
21
+ // determine the base URL for the client code
22
+ base: extractBase,
23
+
19
24
  // Use container attributes to set attributes on the html tag.
20
25
  containerAttributes: {
21
26
  lang: opts.serverData?.locale ?? "en-us",
@@ -0,0 +1,28 @@
1
+ // ... other imports
2
+ import { guessLocale } from "compiled-i18n";
3
+ import type { RequestHandler } from "@builder.io/qwik-city";
4
+
5
+ /**
6
+ * Handle incoming requests to determine and set the appropriate locale.
7
+ * This function checks for a 'locale' query parameter, then a `locale` cookie,
8
+ * and finally falls back to the 'Accept-Language' header.
9
+ */
10
+ export const onRequest: RequestHandler = async ({
11
+ query,
12
+ cookie,
13
+ headers,
14
+ locale,
15
+ }) => {
16
+ // Allow overriding locale with query param `locale`
17
+ if (query.has("locale")) {
18
+ const newLocale = guessLocale(query.get("locale"));
19
+ cookie.delete("locale");
20
+ cookie.set("locale", newLocale, {});
21
+ locale(newLocale);
22
+ } else {
23
+ // Choose locale based on cookie or accept-language header
24
+ const maybeLocale =
25
+ cookie.get("locale")?.value || headers.get("accept-language");
26
+ locale(guessLocale(maybeLocale));
27
+ }
28
+ };
@@ -0,0 +1,5 @@
1
+ import { routeAction$ } from "@builder.io/qwik-city";
2
+
3
+ export const useExampleAction = routeAction$(() => {
4
+ return "This is example action data.";
5
+ });
@@ -1,18 +1,60 @@
1
+ import { $, component$ } from "@builder.io/qwik";
2
+ import { QwikCityMockProvider } from "@builder.io/qwik-city";
3
+
1
4
  import { ExampleTest } from "./example";
5
+ import { useExampleLoader } from "../../loaders/example.loader";
6
+ import { useExampleAction } from "../../actions/example.action";
7
+
8
+ const Template = component$((props: { flag: boolean }) => {
9
+ const loadersMock = [
10
+ {
11
+ loader: useExampleLoader,
12
+ data: "Loader Data",
13
+ },
14
+ ];
15
+
16
+ const actionStub = $(() => cy.stub().as("actionStub"))();
17
+ const actionsMock = [
18
+ {
19
+ action: useExampleAction,
20
+ handler: $(async () => {
21
+ await actionStub.then((_) => _());
22
+ return { status: 200, result: "Action Data" };
23
+ }),
24
+ },
25
+ ];
26
+
27
+ return (
28
+ <QwikCityMockProvider loaders={loadersMock} actions={actionsMock}>
29
+ <ExampleTest flag={props.flag} />
30
+ </QwikCityMockProvider>
31
+ );
32
+ });
2
33
 
3
34
  it("should render ⭐", () => {
4
- cy.mount(<ExampleTest flag={true} />);
5
- cy.get("div.icon").should("contain.text", "⭐");
35
+ cy.mount(<Template flag={true} />);
36
+ cy.get("#icon").should("contain.text", "⭐");
6
37
  });
7
38
 
8
39
  it("should render 💣", () => {
9
- cy.mount(<ExampleTest flag={false} />);
10
- cy.get("div.icon").should("contain.text", "💣");
40
+ cy.mount(<Template flag={false} />);
41
+ cy.get("#icon").should("contain.text", "💣");
11
42
  });
12
43
 
13
44
  it("should count clicks", () => {
14
- cy.mount(<ExampleTest flag={true} />);
15
- cy.get("span").should("contain.text", "Count:0");
16
- cy.get("button").click();
17
- cy.get("span").should("contain.text", "Count:1");
45
+ cy.mount(<Template flag={true} />);
46
+ cy.get("#count").should("contain.text", "Count:0");
47
+ cy.get("#btn-counter").click();
48
+ cy.get("#count").should("contain.text", "Count:1");
49
+ });
50
+
51
+ it("should render loader data", () => {
52
+ cy.mount(<Template flag={true} />);
53
+ cy.get("#loader-data").should("contain.text", "Loader Data");
54
+ });
55
+
56
+ it("should call action on button click", () => {
57
+ cy.mount(<Template flag={true} />);
58
+ cy.get("#btn-action").click();
59
+ cy.get("@actionStub").should("have.been.called");
18
60
  });
@@ -1,17 +1,27 @@
1
1
  import { component$, useStore } from "@qwik.dev/core";
2
2
 
3
+ import { useExampleLoader } from "../../loaders/example.loader";
4
+ import { useExampleAction } from "../../actions/example.action";
5
+
3
6
  export const ExampleTest = component$((props: { flag: boolean }) => {
4
7
  const state = useStore({
5
8
  counter: 0,
6
9
  });
7
10
 
11
+ const loaderState = useExampleLoader();
12
+ const action = useExampleAction();
13
+
8
14
  return (
9
15
  <>
10
- <span>Count:{state.counter}</span>
11
- <div class="icon">Flag: {props.flag ? "⭐" : "💣"}</div>
12
- <button class="btn-counter" onClick$={() => state.counter++}>
16
+ <span id="count">Count:{state.counter}</span>
17
+ <div id="icon">Flag: {props.flag ? "⭐" : "💣"}</div>
18
+ <button id="btn-counter" onClick$={() => state.counter++}>
13
19
  Increment counter
14
20
  </button>
21
+ <span id="loader-data">{loaderState.value}</span>
22
+ <button id="btn-action" onClick$={() => action.submit()}>
23
+ Call action
24
+ </button>
15
25
  </>
16
26
  );
17
27
  });
@@ -0,0 +1,5 @@
1
+ import { routeLoader$ } from "@builder.io/qwik-city";
2
+
3
+ export const useExampleLoader = routeLoader$(() => {
4
+ return "This is example loader data.";
5
+ });