Primero pasos en Qwik

· 22 min de lectura
Primero pasos en Qwik

Los sitios web envían JavaScript al navegador para proporcionar interactividad. La cantidad de JavaScript que se descarga en el navegador aumenta cada año, a medida que aumenta la complejidad de los sitios web. La mayoría de los frameworks de JavaScript descargan y ejecutan todo el código a la vez. Esto hace que el tiempo de carga sea cada vez más lento, ya que el tiempo de carga es O(n).

Qwik es un framework de JavaScript que descarga perezosamente el código a medida que el usuario interactúa. Su objetivo es tener aplicaciones instantáneas, incluso en dispositivos móviles. Logra el objetivo a través de dos estrategias principales:

  • Retrasa la ejecución y la descarga de JavaScript (excepto el código de inicio, alrededor de 1KB) durante el mayor tiempo posible.
  • Serializar el estado de ejecución de la aplicación y del framework en el servidor y reanudarlo en el cliente.

Qwik no es React, aunque se parece a React, y utiliza JSX. Ofrece el tiempo de carga de página más rápido posible, independientemente de la complejidad de un sitio web. Su tiempo de carga es O(1).

Instalar y ejecutar Qwik


Ejecute el siguiente comando para instalar Qwik:

% npm create qwik@latest

La instalación es un asistente interactivo, y pasamos por las opciones seleccionando todos los valores predeterminados.

El proyecto se instala en la carpeta, qwik-app. package.json se encuentra en el directorio raíz. Dentro de package.json, hay una serie de guiones.

"scripts": {
  "build": "qwik build",
  "build.client": "vite build",
  "build.preview": "vite build --ssr src/entry.preview.tsx",
  "build.types": "tsc --incremental --noEmit",
  "dev": "vite --mode ssr",
  "dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force",
  "fmt": "prettier --write .",
  "fmt.check": "prettier --check .",
  "lint": "eslint \"src/**/*.ts*\"",
  "preview": "qwik build preview && vite preview --open",
  "start": "vite --open --mode ssr",
  "qwik": "qwik"
}
  • En la línea 2, el script, build, ejecuta build.client (línea 3) , build.preview (línea 4), y build.types (línea 5).
  • En la línea 3, el script, build.client, genera el módulo cliente.
% npm run build.client
> build.client
> vite build
vite v3.1.1 building for production...
✓ 47 modules transformed.
dist/q-manifest.json        11.45 KiB
dist/build/q-8ba14edf.js    0.06 KiB / gzip: 0.07 KiB
dist/build/q-53555967.js    4.57 KiB / gzip: 2.23 KiB
dist/build/q-d7f3d226.js    0.26 KiB / gzip: 0.22 KiB
dist/build/q-bceff05d.js    0.61 KiB / gzip: 0.27 KiB
dist/build/q-8d91e16b.js    1.49 KiB / gzip: 0.84 KiB
dist/build/q-026a668e.js    0.83 KiB / gzip: 0.49 KiB
dist/build/q-b10147d6.js    0.20 KiB / gzip: 0.16 KiB
dist/build/q-f13b34ad.js    1.00 KiB / gzip: 0.51 KiB
dist/build/q-cff735f7.js    0.26 KiB / gzip: 0.20 KiB
dist/build/q-8d0c32f0.js    0.26 KiB / gzip: 0.20 KiB
dist/build/q-07a60165.js    0.43 KiB / gzip: 0.29 KiB
dist/build/q-9abdde7c.js    0.11 KiB / gzip: 0.11 KiB
dist/build/q-eab02654.js    2.42 KiB / gzip: 1.12 KiB
dist/build/q-b5e190d0.js    2.82 KiB / gzip: 0.88 KiB
dist/service-worker.js      2.13 KiB / gzip: 1.01 KiB
dist/build/q-0ea8883c.css   1.58 KiB / gzip: 0.79 KiB
dist/build/q-9d71bc2f.js    39.14 KiB / gzip: 15.82 KiB
dist/build/q-9a4a797f.js    3.99 KiB / gzip: 1.99 KiB

En la línea 4, el sript, build.preview, construye el paquete SSR para la producción.

% npm run build.preview
> build.preview
> vite build --ssr src/entry.preview.tsx
vite v3.1.1 building SSR bundle for production...
✓ 17 modules transformed.
server/entry.preview.mjs   32.50 KiB

En la línea 5, el sript, build.types, ejecuta una comprobación de tipo en el código fuente.

% npm run build.types
> build.types
> tsc --incremental --noEmit

En la línea 6, el sript, dev, comienza con el modo de desarrollo, utilizando el servidor de desarrollo de Vite.

Vite es una herramienta de construcción que tiene como objetivo proporcionar una experiencia de desarrollo más rápida y más delgada para los proyectos web modernos. Este comando genera la salida SSR.

% npm run dev
> dev
> vite --mode ssr
VITE v3.1.1  ready in 654 ms
➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
(node:30981) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)

En la línea 7, el script, dev.debug, comienza con el modo de desarrollo con depuración (debug) . --inspect-brk es la opción de Node.js para habilitar el agente inspector y escucha en la dirección y puerto por defecto (127.0.0.1:9229). Añade un punto de interrupción antes de que comience el código del usuario.

% npm run dev.debug
> dev.debug
> node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force
Debugger listening on ws://127.0.0.1:9229/9f1b7a85-5155-4e06-a510-67188fbe690a
For help, see: https://nodejs.org/en/docs/inspector

En la línea 8, el script, fmt, formatea todo el código.

% npm run fmt
> fmt
> prettier --write .
.eslintrc.cjs 52ms
.vscode/extensions.json 4ms
.vscode/qwik-city.code-snippets 3ms
.vscode/qwik.code-snippets 8ms
package-lock.json 63ms
package.json 10ms
README.md 56ms
server/entry.preview.mjs 259ms
src/components/header/header.css 47ms
src/components/header/header.tsx 300ms
src/components/icons/qwik.tsx 8ms
src/components/router-head/router-head.tsx 26ms
src/entry.dev.tsx 14ms
src/entry.preview.tsx 3ms
src/entry.ssr.tsx 5ms
src/global.css 20ms
src/root.tsx 5ms
src/routes/flower/flower.css 12ms
src/routes/flower/index.tsx 18ms
src/routes/index.tsx 21ms
src/routes/layout.tsx 4ms
src/routes/service-worker.ts 4ms
tsconfig.json 3ms
vite.config.ts 3ms

En la línea 9, el script, fmt.check, comprueba si algún archivo necesita ser formateado.

% npm run fmt.check
> fmt.check
> prettier --check .
Checking formatting...
All matched files use Prettier code style!

En la línea 10, the script, lint, utiliza eslint para realizar un análisis estático del código.

% npm run lint
> lint
> eslint "src/**/*.ts*"

En la línea 11, el script, preview, crea una compilación de producción de los módulos del cliente y ejecuta un servidor local. El servidor de vista previa es sólo para la conveniencia de la vista previa local de una construcción de producción, y no debe ser utilizado como un servidor de producción.

% npm run preview
> preview
> qwik build preview && vite preview --open
vite build
vite build --ssr src/entry.preview.tsx
vite v3.1.1 building for production...
✓ 47 modules transformed.
dist/q-manifest.json        11.45 KiB
dist/build/q-8ba14edf.js    0.06 KiB / gzip: 0.07 KiB
dist/build/q-d7f3d226.js    0.26 KiB / gzip: 0.22 KiB
dist/build/q-53555967.js    4.57 KiB / gzip: 2.23 KiB
dist/build/q-bceff05d.js    0.61 KiB / gzip: 0.27 KiB
dist/build/q-8d91e16b.js    1.49 KiB / gzip: 0.84 KiB
dist/build/q-026a668e.js    0.83 KiB / gzip: 0.49 KiB
dist/build/q-f13b34ad.js    1.00 KiB / gzip: 0.51 KiB
dist/build/q-b10147d6.js    0.20 KiB / gzip: 0.16 KiB
dist/build/q-cff735f7.js    0.26 KiB / gzip: 0.20 KiB
dist/build/q-8d0c32f0.js    0.26 KiB / gzip: 0.20 KiB
dist/build/q-9abdde7c.js    0.11 KiB / gzip: 0.11 KiB
dist/build/q-07a60165.js    0.43 KiB / gzip: 0.29 KiB
dist/build/q-b5e190d0.js    2.82 KiB / gzip: 0.88 KiB
dist/build/q-eab02654.js    2.42 KiB / gzip: 1.12 KiB
dist/service-worker.js      2.13 KiB / gzip: 1.01 KiB
dist/build/q-9d71bc2f.js    39.14 KiB / gzip: 15.82 KiB
dist/build/q-0ea8883c.css   1.58 KiB / gzip: 0.79 KiB
dist/build/q-9a4a797f.js    3.99 KiB / gzip: 1.99 KiB
✓ Built client modules
✓ Built preview (ssr) modules
➜  Local:   http://localhost:4173/
  ➜  Network: use --host to expose
(node:31183) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)

En la línea 12, script, start, inicia el servidor de desarrollo.

% npm run start
> start
> vite --open --mode ssr
VITE v3.1.1  ready in 900 ms
➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
(node:31325) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)

En la línea 13, el script, qwik, puede utilizarse para añadir integraciones adicionales.

% npm run qwik add
🦋  Add Integration
? What feature would you like to add? › (use ↓↑ arrows, hit enter)
❯   Server Adaptors (SSR)
    Static Generator (SSG)
    Partytown
    Qwik React
    Tailwind

Qwik requiere Node.js 16 o superior. Ejecuta npm run dev, y el sitio web por defecto está disponible en  http://localhost:5173/.

Carpeta Qwik Source


Después de la instalación, la carpeta, qwik-app, se ve así:

qwik-app
├── README.md
├── public
│   └── favicon.svg
├── src
│   ├── components
│   ├── routes
│   ├── entry.dev.tsx
│   ├── entry.preview.tsx
│   ├── entry.ssr.tsx
│   ├── global.css
│   └── root.tsx
├── vite.config.ts
├── tsconfig.json
├── node_modules
├── package.json
├── package-lock.json
├── .eslintignore
├── .eslintrc.cjs
├── .gitignore
└── .prettierignore
  • qwik-app: Es el directorio que contiene el código de la aplicación Qwik.
  • README.md: Describe la estructura y los script del proyecto.
  • public: Es el directorio para los activos estáticos, incluyendo favicon.svg.
  • src/components: Es el directorio recomendado para los componentes.
  • src/routes: Proporciona el enrutamiento basado en el directorio.
  • src/entry.dev.tsx: Es el punto de entrada al desarrollo utilizando sólo módulos del lado del cliente, sin SSR.
import { render, RenderOptions } from "@builder.io/qwik";
import Root from "./root";

export default function (opts: RenderOptions) {
  return render(document, <Root />, opts);
}
  • src/entry.preview.tsx: Es el punto de entrada del paquete para el script, preview, que sirve el paquete SSR en modo de producción.
import { qwikCity } from "@builder.io/qwik-city/middleware/node";
import render from "./entry.ssr";

/**
 * The default export is the QwikCity adaptor used by Vite preview.
 */
export default qwikCity(render);

QwikCity se importa en la línea 1, y se utiliza para adaptar render para qwikCity en la línea 7. Qwik City está construido sobre Qwik, trayendo enrutamiento opinado (opinionated routing)  y otras cosas que construyen sitios web a escala de una manera opinada y performante.

  • src/entry.ssr.tsx: Es el punto de entrada del SSR. Se utiliza en todos los casos en los que la aplicación se renderiza fuera del navegador, para servidores, como por ejemplo express, cloudflare, y para scripts, start, preview, and build.
import { renderToStream, RenderToStreamOptions } from "@builder.io/qwik/server";
import { manifest } from "@qwik-client-manifest";
import Root from "./root";

export default function (opts: RenderToStreamOptions) {
  return renderToStream(<Root />, {
    manifest,
    ...opts,
    prefetchStrategy: {
      implementation: {
        linkInsert: null,
        workerFetchInsert: null,
        prefetchEvent: "always",
      },
    },
  });
}

renderToStream (línea 6) genera HTML en el servidor. Es similar a React ReactDOMServer’s renderToString and renderToPipeableStream.

  • src/global.css: Se trata de estilos aplicados globalmente.
  • src/root.tsx: Es el archivo raíz para definir la página web de QwikCity
import { component$ } from "@builder.io/qwik";
import {
  QwikCity,
  RouterOutlet,
  ServiceWorkerRegister,
} from "@builder.io/qwik-city";
import { RouterHead } from "./components/router-head/router-head";

import "./global.css";

export default component$(() => {
  /**
   * The root of a QwikCity site always start with the <QwikCity> component,
   * immediately followed by the document's <head> and <body>.
   *
   * Dont remove the `<head>` and `<body>` elements.
   */
  return (
    <QwikCity>
      <head>
        <meta charSet="utf-8" />
        <RouterHead />
      </head>
      <body lang="en">
        <RouterOutlet />
        <ServiceWorkerRegister />
      </body>
    </QwikCity>
  );
});

En las líneas 19-28, el QwikCity del sitio web se define con head (líneas 20–23) y body (líneas 24–27).  En la línea 25, <RouterOutlet> se utiliza para renderizar los elementos de ruta hijos.

  • vite.config.js: Es el archivo de configuración de Vite paraqwikCity y qwikVite.
  • tsconfig.js: Es el archivo de configuración de TypeScript.

Componentes Qwik

La carpeta, src/components, es el directorio recomendado para los componentes. fuera de la caja, hay 3 subdirectorios para los componentes, icons, header, y router-head.

components
├── icons
│   └── qwik.tsx
├── header
│   ├── header.tsx
│   └── header.css
└── router-head
    └── router-head.tsx

El componente QwikLogo se encuentra dentro de src/components/icons. Actualmente, incluye el logotipo SVG file, qwik.tsx.

Aquí src/components/icons/qwik.tsx:

export const QwikLogo = () => (
  <svg
    width="100"
    height="35"
    viewBox="0 0 167 53"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      d="M81.9545 46.5859H75.5513V35.4045C73.4363 36.8579 71.0496 37.5749 68.4884 37.5749C65.0151 37.5749 62.4344 36.6253 60.8239 34.6487C59.2134 32.6915 58.3984 29.2034 58.3984 24.2231C58.3984 19.1266 59.3492 15.5997 61.2702 13.5456C63.23 11.4721 66.3734 10.4644 70.7004 10.4644C74.7946 10.4644 78.5201 11.0264 81.9545 12.131V46.5859ZM75.5513 16.278C74.096 15.8323 72.4661 15.6191 70.7004 15.6191C68.5272 15.6191 66.9749 16.1811 66.1017 17.3244C65.2479 18.4871 64.7823 20.6962 64.7823 23.9712C64.7823 27.0524 65.1897 29.1065 66.0435 30.2304C66.8973 31.335 68.3719 31.897 70.5452 31.897C73.3781 31.897 75.5513 30.7343 75.5513 29.2809V16.278Z"
      fill="black"
    />
    <path
      d="M91.133 11.1426C93.4033 17.4406 95.3242 23.7386 96.993 30.0948C99.205 23.5836 101.087 17.2856 102.542 11.1426H108.15C110.265 17.4406 112.031 23.7386 113.447 30.0948C115.97 23.196 117.949 16.8787 119.404 11.1426H125.71C123.033 20.173 120.064 28.777 116.785 36.8966H109.256C108.402 32.3039 107.044 26.7617 105.22 20.1536C104.056 25.2889 102.445 30.8893 100.33 36.8966H92.8018C90.2793 27.5174 87.5434 18.9522 84.6328 11.1426H91.133Z"
      fill="black"
    />
    <path
      d="M132.832 7.55758C129.999 7.55758 129.203 6.85996 129.203 3.97257C129.203 1.39523 130.018 0.794495 132.832 0.794495C135.665 0.794495 136.46 1.39523 136.46 3.97257C136.46 6.85996 135.665 7.55758 132.832 7.55758ZM129.649 11.1426H136.053V36.8966H129.649V11.1426Z"
      fill="black"
    />
    <path
      d="M166.303 11.1426C161.763 17.5956 158.581 21.5295 156.815 22.9441C158.27 23.8937 162.17 28.8933 167.002 36.916H159.628C153.613 27.7887 150.742 23.8549 149.325 23.2542V36.916H142.922V0H149.325V23.2348C150.78 22.169 153.963 18.1382 158.872 11.1426H166.303Z"
      fill="black"
    />
    <path
      d="M40.973 52.5351L32.0861 43.6985L31.9503 43.7179V43.621L13.0511 24.9595L17.708 20.4637L14.9721 4.76715L1.99103 20.8513C-0.220992 23.0798 -0.628467 26.7036 0.962635 29.3778L9.07337 42.8265C10.3152 44.9 12.566 46.1402 14.9915 46.1208L19.0081 46.082L40.973 52.5351Z"
      fill="#18B6F6"
    />
    <path
      d="M45.8232 20.5411L44.038 17.2468L43.1066 15.5609L42.738 14.902L42.6992 14.9408L37.8094 6.47238C36.587 4.34075 34.2974 3.02301 31.8137 3.04239L27.5255 3.15865L14.7384 3.19741C12.313 3.21679 10.101 4.49577 8.87853 6.56927L1.09766 21.9945L15.0101 4.72831L33.2496 24.7656L30.0091 28.0406L31.9495 43.7178L31.9689 43.679V43.7178H31.9301L31.9689 43.7565L33.4824 45.2293L40.8364 52.4187C41.1469 52.7094 41.6514 52.3606 41.4379 51.9924L36.8975 43.0589L44.8142 28.4282L45.0664 28.1375C45.1634 28.0212 45.2604 27.905 45.3381 27.7887C46.8904 25.6764 47.1038 22.8472 45.8232 20.5411Z"
      fill="#AC7EF4"
    />
    <path
      d="M33.3076 24.6882L15.0099 4.74774L17.61 20.3668L12.9531 24.882L31.9105 43.6985L30.203 28.0794L33.3076 24.6882Z"
      fill="white"
    />
  </svg>
);

Importa este archivo a un visor de SVG, y podemos ver el logotipo de Qwik.

El componente de la cabecera

El componente Header se encuentra dentro de src/components/header.  Define la cabecera del sitio web por defecto que se muestra a continuación, donde el logotipo de Qwik se encuentra en la zona superior izquierda.

Hay 2 archivos en la carpeta, src/components/header:

  • header.tsx
  • header.css

Aquí src/components/header/header.tsx:

import { component$, useStylesScoped$ } from "@builder.io/qwik";
import { QwikLogo } from "../icons/qwik";
import styles from "./header.css?inline";

export default component$(() => {
  useStylesScoped$(styles);

  return (
    <header>
      <div class="logo">
        <a href="https://qwik.builder.io/" target="_blank">
          <QwikLogo />
        </a>
      </div>
      <ul>
        <li>
          <a
            href="https://qwik.builder.io/docs/components/overview/"
            target="_blank"
          >
            Docs
          </a>
        </li>
        <li>
          <a
            href="https://qwik.builder.io/examples/introduction/hello-world/"
            target="_blank"
          >
            Examples
          </a>
        </li>
        <li>
          <a
            href="https://qwik.builder.io/tutorial/welcome/overview/"
            target="_blank"
          >
            Tutorials
          </a>
        </li>
      </ul>
    </header>
  );
});

El código anterior es muy similar al de React.

component$() (línea 5) es la definición del componente en Qwik, y (líneas 5-43) define una pieza de código reutilizable que puede ser usada para construir una UI, similar al componente funcional en React.

useStylesScoped$() (línea 6) crea un estilo de alcance.

src/components/header/header.css:

header {
  display: flex;
  background: white;
  border-bottom: 10px solid var(--qwik-dark-purple);
}

header .logo a {
  display: inline-block;
  padding: 10px 10px 7px 20px;
}

header ul {
  margin: 0;
  padding: 3px 10px 0 0;
  list-style: none;
  flex: 1;
  text-align: right;
}

header li {
  display: inline-block;
  margin: 0;
  padding: 0;
}

header li a {
  display: inline-block;
  padding: 15px 10px;
  text-decoration: none;
}

header li a:hover {
  text-decoration: underline;
}

Es un archivo CSS que define los selectores de etiquetas y clases para el componente header

El componente RouterHead

El componente RouterHead se encuentra dentro de src/components/router-head. Define el contenido colocado dentro del documento <head>

src/components/router-head/router-head.tsx:

import { component$ } from "@builder.io/qwik";
import { useDocumentHead, useLocation } from "@builder.io/qwik-city";

/**
 * The RouterHead component is placed inside of the document `<head>` element.
 */
export const RouterHead = component$(() => {
  const head = useDocumentHead();
  const loc = useLocation();

  return (
    <>
      <title>{head.title}</title>

      <link rel="canonical" href={loc.href} />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <link rel="icon" type="image/svg+xml" href="/favicon.svg" />

      <link rel="preconnect" href="https://fonts.googleapis.com" />
      <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
      <link
        href="https://fonts.googleapis.com/css2?family=Poppins&amp;display=swap"
        rel="stylesheet"
      />

      <meta property="og:site_name" content="Qwik" />
      <meta name="twitter:site" content="@QwikDev" />
      <meta name="twitter:title" content="Qwik" />

      {head.meta.map((m) => (
        <meta {...m} />
      ))}

      {head.links.map((l) => (
        <link {...l} />
      ))}

      {head.styles.map((s) => (
        <style {...s.props} dangerouslySetInnerHTML={s.style} />
      ))}
    </>
  );
});

Se coloca dentro del elemento head para root.tsx:

<head>
  <meta charSet="utf-8" />
  <RouterHead />
</head>

En el navegador, View Page Source, muestra el contenido del cabezal convertido.


<head q:head>
  <meta charSet="utf-8" q:head>
  <!--qv q:id=2 q:key=zrbrqoaqXSY:-->
  <title q:head>Welcome to Qwik</title>
  <link rel="canonical" href="http://localhost:5173/" q:id="3" q:head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" q:head>
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" q:head>
  <link rel="preconnect" href="https://fonts.googleapis.com" q:head>
  <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin q:head>
  <link href="https://fonts.googleapis.com/css2?family=Poppins&amp;display=swap" rel="stylesheet" q:head>
  <meta property="og:site_name" content="Qwik" q:head>
  <meta name="twitter:site" content="@QwikDev" q:head>
  <meta name="twitter:title" content="Qwik" q:head>
  <!--/qv-->
  <link rel="stylesheet" href="/src/global.css">
</head>

Rutas Qwik

La carpeta, src/routes, se basa en Qwik City, que admite las siguientes características:

  • Enrutamiento basado en directorios.
  • Diseños anidados.
  • Menús basados en archivos.
  • Apoyo a la creación de contenidos con .tsx o .mdx
  • Data endpoints

Fuera de la caja, las rutas incluyen los siguientes files/directories:

routes
├── layout.tsx
├── index.tsx
├── service-worker.ts
└── flower
    ├── flower.css
    └── index.tsx

El componente de diseño


En una aplicación, las diferentes rutas suelen compartir algo común, como el head y el body. Estas partes comunes se implementan mediante un componente de diseño que se reutiliza para cada página.

src/routes/layout.tsx:

import { component$, Slot } from "@builder.io/qwik";
import Header from "../components/header/header";

export default component$(() => {
  return (
    <>
      <main>
        <Header />
        <section>
          <Slot />
        </section>
      </main>
      <footer>
        <a href="https://www.builder.io/" target="_blank">
          Made with ♡ by Builder.io
        </a>
      </footer>
    </>
  );
});

En la línea 8 el comando Header se coloca en la parte superior de la página.

En la línea 10 un Slot se utiliza para colocar el componente hijo en el centro de la página.

En la línea 13 - 17  un elemento footer se coloca en la parte inferior de la página.

La ruta index

El archivo de la hoja en cada ruta se llama index, donde el tipo de archivo puede ser .ts, .tsx, .js, .jsx, .md, o .mdx.

El index.tsx define la interfaz de usuario que se coloca en la ranura (en el cuadro rojo de abajo), cuando la URL es /.

Lo siguiente src/routes/index.tsx implementa la anterior interfaz de usuario de caja roja de manera directa.

import { component$ } from "@builder.io/qwik";
import type { DocumentHead } from "@builder.io/qwik-city";
import { Link } from "@builder.io/qwik-city";

export default component$(() => {
  return (
    <div>
      <h1>
        Welcome to Qwik <span class="lightning">⚡️</span>
      </h1>

      <ul>
        <li>
          Check out the <code>src/routes</code> directory to get started.
        </li>
        <li>
          Add integrations with <code>npm run qwik add</code>.
        </li>
        <li>
          More info about development in <code>README.md</code>
        </li>
      </ul>

      <h2>Commands</h2>

      <table class="commands">
        <tr>
          <td>
            <code>npm run dev</code>
          </td>
          <td>Start the dev server and watch for changes.</td>
        </tr>
        <tr>
          <td>
            <code>npm run preview</code>
          </td>
          <td>Production build and start preview server.</td>
        </tr>
        <tr>
          <td>
            <code>npm run build</code>
          </td>
          <td>Production build.</td>
        </tr>
        <tr>
          <td>
            <code>npm run qwik add</code>
          </td>
          <td>Select an integration to add.</td>
        </tr>
      </table>

      <h2>Add Integrations</h2>

      <table class="commands">
        <tr>
          <td>
            <code>npm run qwik add cloudflare-pages</code>
          </td>
          <td>
            <a href="https://developers.cloudflare.com/pages" target="_blank">
              Cloudflare Pages Server
            </a>
          </td>
        </tr>
        <tr>
          <td>
            <code>npm run qwik add express</code>
          </td>
          <td>
            <a href="https://expressjs.com/" target="_blank">
              Nodejs Express Server
            </a>
          </td>
        </tr>
        <tr>
          <td>
            <code>npm run qwik add netlify-edge</code>
          </td>
          <td>
            <a href="https://docs.netlify.com/" target="_blank">
              Netlify Edge Functions
            </a>
          </td>
        </tr>
        <tr>
          <td>
            <code>npm run qwik add static-node</code>
          </td>
          <td>
            <a
              href="https://qwik.builder.io/qwikcity/static-site-generation/overview/"
              target="_blank"
            >
              Static Site Generation (SSG)
            </a>
          </td>
        </tr>
      </table>

      <h2>Community</h2>

      <ul>
        <li>
          <span>Questions or just want to say hi? </span>
          <a href="https://qwik.builder.io/chat" target="_blank">
            Chat on discord!
          </a>
        </li>
        <li>
          <span>Follow </span>
          <a href="https://twitter.com/QwikDev" target="_blank">
            @QwikDev
          </a>
          <span> on Twitter</span>
        </li>
        <li>
          <span>Open issues and contribute on </span>
          <a href="https://github.com/BuilderIO/qwik" target="_blank">
            Github
          </a>
        </li>
        <li>
          <span>Watch </span>
          <a href="https://qwik.builder.io/media/" target="_blank">
            Presentations, Podcasts, Videos, etc.
          </a>
        </li>
      </ul>
      <Link class="mindblow" href="/flower">
        Blow my mind 🤯
      </Link>
    </div>
  );
});

export const head: DocumentHead = {
  title: "Welcome to Qwik",
};

El servicio worker

Un trabajador de servicio tradicional (traditional service worker) proporciona la precarga y el almacenamiento en caché. Qwik City utiliza el service worker para precargar dinámicamente lo que es posible ejecutar. El hecho de no precargar toda la aplicación libera recursos para solicitar únicamente las pequeñas partes que un usuario podría utilizar para la interfaz de usuario mostrada.

src/routes/service-worker.ts:

import { setupServiceWorker } from "@builder.io/qwik-city/service-worker";

setupServiceWorker();

addEventListener("install", () => self.skipWaiting());

addEventListener("activate", () => self.clients.claim());

declare const self: ServiceWorkerGlobalScope;

Este archivo puede optar por el trabajador de servicios o no. Si la aplicación no quiere utilizar el servicio de trabajo en absoluto, simplemente elimine setupServiceWorker() (línea 3) del archivo.

La ruta de las flores

En la ruta, /flower, muestra una demostración de flores que se construye mediante una matriz de cuadrados transformados.

Ve a  http://localhost:5173/flower, y vemos una flor giratoria.

Hay 2 archivos en la carpeta, src/routes/flower:

  • index.tsx
  • flower.css


index.tsx define la interfaz de usuario que se coloca en la ranura, cuando la URL es /flower.

src/routes/flower/index.tsx:

import {
  component$,
  useClientEffect$,
  useStore,
  useStylesScoped$,
} from "@builder.io/qwik";
import { DocumentHead, useLocation } from "@builder.io/qwik-city";
import styles from "./flower.css?inline";

export default component$(() => {
  useStylesScoped$(styles);
  const loc = useLocation();

  const state = useStore({
    count: 0,
    number: 20,
  });

  useClientEffect$(({ cleanup }) => {
    const timeout = setTimeout(() => (state.count = 1), 500);
    cleanup(() => clearTimeout(timeout));

    const internal = setInterval(() => state.count++, 7000);
    cleanup(() => clearInterval(internal));
  });

  return (
    <>
      <input
        type="range"
        value={state.number}
        max={50}
        onInput$={(ev) => {
          state.number = (ev.target as HTMLInputElement).valueAsNumber;
        }}
      />
      <div
        style={{
          "--state": `${state.count * 0.1}`,
        }}
        class={{
          host: true,
          pride: loc.query["pride"] === "true",
        }}
      >
        {Array.from({ length: state.number }, (_, i) => (
          <div
            key={i}
            class={{
              square: true,
              odd: i % 2 === 0,
            }}
            style={{ "--index": `${i + 1}` }}
          />
        )).reverse()}
      </div>
    </>
  );
});

export const head: DocumentHead = {
  title: "Qwik Flower",
};
  • En las líneas 10-59 se define el componente floral.
  • useStylesScoped$() (línea 11) crea un estilo de alcance. useLocation  (línea 12) recupera la ubicación de la URL.
  • En las líneas 14-17, se crean dos estados, count y number. count actualiza la variable css, --state (línea 39), que se utiliza para calcular la transformación al cuadrado en  flower.css. number se utiliza para controlar cuántos cuadrados (línea 46) hay en la flor.
  • En las líneas 19-25, useClientEffect$  establece el intervalo para actualizar las casillas.
  • En las líneas 29-36, define un deslizador de rango para cambiar number.
  • En las líneas 37-45, se define el diseño que alberga la flor.
  • En las líneas 46-55, un array de div  se crea con clase, square. También añade la clase, odd,si el index, i, es impar. Estas clases se utilizan para dar estilo a la matriz de div.
  • En las líneas 61-63, el componente head se define, y se colocará dentro del documento <head>

Curiosamente, en la línea 43 se comprueba el parámetro de consulta de la ubicación de la URL para ver si es /flower?pride=true. Cuando es verdadero, añade la clase, pride.

Echemos un vistazo a src/routes/flower/flower.css:

.host {
  display: grid;

  align-items: center;
  justify-content: center;
  justify-items: center;
  --rotation: 135deg;
  --rotation: 225deg;
  --size-step: 10px;
  --odd-color-step: 5;
  --even-color-step: 5;
  --center: 12;

  width: 100%;
  height: 500px;

  contain: strict;
}

input {
  width: 100%;
}

.square {
  --size: calc(40px + var(--index) * var(--size-step));

  display: block;
  width: var(--size);
  height: var(--size);
  transform: rotateZ(
    calc(var(--rotation) * var(--state) * (var(--center) - var(--index)))
  );
  transition-property: transform, border-color;
  transition-duration: 5s;
  transition-timing-function: ease-in-out;
  grid-area: 1 / 1;
  background: white;
  border-width: 2px;
  border-style: solid;
  border-color: black;
  box-sizing: border-box;
  will-change: transform, border-color;

  contain: strict;
}

.square.odd {
  --luminance: calc(1 - calc(calc(var(--index) * var(--odd-color-step)) / 256));
  background: rgb(
    calc(172 * var(--luminance)),
    calc(127 * var(--luminance)),
    calc(244 * var(--luminance))
  );
}

.pride .square:nth-child(12n + 1) {
  background: #e70000;
}
.pride .square:nth-child(12n + 3) {
  background: #ff8c00;
}
.pride .square:nth-child(12n + 5) {
  background: #ffef00;
}
.pride .square:nth-child(12n + 7) {
  background: #00811f;
}
.pride .square:nth-child(12n + 9) {
  background: #0044ff;
}
.pride .square:nth-child(12n + 11) {
  background: #760089;
}
view raw
  • En las líneas 1-18, el diseño del host es estilizado.
  • En las líneas 20-22, se define el deslizador de rango con 100% width.
  • En las líneas 24-45, se estilan los cuadrados.
  • En las líneas 47-54, las casillas impares indexadas se establecen con diferentes colores de fondo.
  • En las líneas 56-73, para el div con clases, pride y square, algunos de ellos están definidos con diferentes colores de fondo.

http://localhost:5173/flower?pride=true, y vemos una flor colorida que gira.

¿Por qué es Qwik Fast?

Qwik es rápido, ya que afirma que el tiempo de carga es O(1). Su rápido tiempo de carga proviene de la reutilización, la progresividad y la reactividad.

Resumibilidad

La hidratación es una técnica similar al renderizado, pero tiene el DOM completo incorporado en el código HTML en el lado del servidor. La hidratación consume mucho tiempo ya que tiene que descargar todo el código de los componentes asociados a la página actual. También necesita ejecutar las plantillas asociadas a los componentes de la página para reconstruir la ubicación de los oyentes y el árbol interno de componentes.

Aquí hay un botón con el oyente:

<button onclick="handlerFunction()">Click me</button>

El código HTML necesita descargar la función JavaScript para ser ejecutada, y la función hace que se descarguen más cosas para toda la lógica de la aplicación.

Qwik es diferente porque no requiere hidratación para reanudar una aplicación en el cliente. Su reanudación consiste en pausar la ejecución en el servidor y reanudar la ejecución en el cliente sin tener que reproducir y descargar toda la lógica de la aplicación.

Qwik serializa el oyente de eventos en DOM en el siguiente formato:

<button on:click="./chunk.js#handler_symbol">click me</button>

on:click contiene el nombre del paquete y el símbolo de la función. Puede reanudar la aplicación en el lado del cliente sólo cuando un usuario hace clic en el botón. Esto hace que Qwik sea más rápido que otros frameworks.

Progresividad

La progresividad consiste en descargar el código a medida que la aplicación lo necesita, sin tener que descargar toda la base de código de forma ansiosa. En Qwik, todo es descargable de forma perezosa:

  • Componente on-render (bloque de inicialización y bloque de renderización)
  • Componente on-watch (efectos secundarios, sólo se descargan si las entradas cambian)
  • Escuchadores (sólo se descargan en la interacción)
  • Estilos (sólo se descargan si el servidor no los ha proporcionado ya)

Reactividad

Qwik rastrea qué componentes están suscritos a qué estado. Esta información permite a Qwik invalidar sólo el componente relevante en el cambio de estado, lo que minimiza el número de componentes que necesitan ser re-renderizados.

Conclusión

Qwik es un marco de trabajo de JavaScript que descarga perezosamente el código a medida que el usuario interactúa. Ofrece el tiempo de carga de página más rápido posible, independientemente de la complejidad de un sitio web. Su tiempo de carga es O(1).

Hemos explicado la aplicación Qwik instalada. Su sintaxis es similar a la de React. Qwik es el núcleo, y Qwik City está construido sobre Qwik, con componentes y rutas organizadas.

Fuente

Plataforma de cursos gratis sobre programación