Представляем Qwik — JavaScript Framework со временем загрузки O(1)
Веб-сайты отправляют JavaScript в браузер для обеспечения интерактивности. Количество JavaScript, загружаемых в браузер, увеличивается в каждым годом по мере увеличения сложности веб-сайтов. Большинство фреймворков JavaScript загружают и выполняют весь код сразу. В итоге время загрузки становится медленнее, потому что время загрузки равно O(n).
Qwik — это среда JavaScript, которая лениво загружает код по мере взаимодействия пользователя. Он нацелен на мгновенное включение приложений даже на мобильных устройствах. Он достигает цели с помощью двух основных стратегий:
- Отложите выполнение и загрузку JavaScript (кроме стартового кода, около 1 КБ) как можно дольше.
- Сериализировать состояние выполнения приложения и фреймворка на сервере и возобновить его на клиенте.
Qwik - это не React, хотя он похож на React и использует JSX. Он предлагает максимально быстрое время загрузки страницы независимо от сложности веб-сайта. Время его загрузки O(1).
Установите и запустите Qwik
Выполните следующую команду, чтобы установить Qwik:
% npm create qwik@latest
Установка представляет собой интерактивный мастер, и мы проходим через варианты, выбирая все значения по умолчанию.
Проект устанавливается в папку qwik-app
. package.json
находится в корнпевом каталоге. Внутри package.json
есть несколько скриптов.
"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"
}
build
в строке 2 выполняется сценарийbuild.client
(строка 3),build.preview
(строка 4) иbuild.types
(строка 5).- В строке 3 скрипт
build.client
генерирует клиентский модуль.
% 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
- В строке 4 скрипт
build.preview
строит пакет SSR для производства
% 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
- В строке 5 скрипт
build.types
выполняет проверку типа исходного кода.
% npm run build.types
> build.types
> tsc --incremental --noEmit
- В строке 6 сценарий
dev
запускается в режиме разработки с использованием сервера разработки Vite. Vite - это инструмент для сборки, целью которого является обеспечение более быстрой и удобной разработки современных веб-проектов. Это команда генерирует выходные данные 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)
- В 7 строке скрипт
dev.debug
запускается в режиме разработки с отладкой.--inspect-brk
является параметром Node.Js для включения агента инспектора и прослушивания адреса и порта по умолчанию (127.0.0.1:9229
). Он добавляет точку останова перед запуском пользовательского кода.
% 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
- В 8 строке скрипт
fmt
форматирует весь код.
% 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
- В строке 9 скрипт
fmt.check
проверяет, нужно ли форматировать какой-либо файл.
% npm run fmt.check
> fmt.check
> prettier --check .
Checking formatting...
All matched files use Prettier code style!
- В строке 10 скрипт
lint
использует eslint для выполнения статического анализа кода.
% npm run lint
> lint
> eslint "src/**/*.ts*"
- В 11 строке сценарий
preview
создает производственную сборку клиентских модулей и запускает локальный сервер. Сервер предварительного просмотра предназначен только для удобства локального предварительного просмотра рабочей сборки, и ео не следует использовать в качестве рабочего сервера.
% 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)
- В строке 12 сценарий
start
запускает сервер разработки.
% 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)
- В 13 строке можно использовать скрипт
qwik
для добавления дополнительных интеграций.
% 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 требует Node.Js 16 или выше. Выполните npm run dev
, и веб-сайт по умолчанию будет доступен по адресу http://localhost:5173/
.
Исходная папка Qwik
После установки папка qwik-app
выглядит так:
qwik-app
├── README.md
├── public
│ └── favicon.svg
├── src
│ ├── компоненты
│ ├── маршруты
│ ├── entry.dev.tsx
│ ─ ├ entry├ ,
_ _
_
_
_
_
_
_
_ ── package-lock.json
├── .eslintignore
├── .eslintrc.cjs
├── .gitignore
└── .prettierignore
qwik-app
: это каталог, содержащий код приложения Qwik.README.md
: описывает структуру проекта и скрипты.public
: каталог для статических ресурсов, включая файлыfavicon.svg
.src/components
: рекомендуемый каталог для компонетов.src/routes
: обеспечивает маршрутизацию на основе каталогов.src/entry.dev.tsx
: это точка входа в разработку, использующая только клиентские модули без 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
: точка пакета входа для скриптаpreview
, который обслуживает пакет SSR в производственном режиме
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
импортируется в строке 1 и используется для адаптации render
в qwikCity
строке 7. QwikCity построен на основе Qwik, обеспечивая самостоятельную маршрутизацию и другие функции, которые позволяют создавать веб-сайты в масштабе самоуверенным и эффективным способом. QwikCity для Qwik - это то, что Next.js для React.
- src/entry.ssr.tsx: это точка входа SSR. Он используется во всех случаях, когда приложение отображается вне браузера, для серверов, таких как express, cloudflare, а также для скриптов
start
,preview
и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
(строка 6) генерирует HTML на сервере. Он похож на React ReactDOMServer
, renderToString
и renderToPipeableStream
.
src/global.css
: это глобально применяемые стили.src/root.tsx
: корневой файл для опреленения веб-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>
);
});
В строках 19–28 веб-QwikCity
сайт определяется с помощью head
(строки 20–23) и body
(строки 24–27). В строке 25 <RouterOutlet>
используется для рендеринга дочерних элементов маршрута.
vite.config.js
: файл конфигурации Vite дляqwikCity
иqwikVite
.tsconfig.js
: это файл конфигурации TypeScript.
Компоненты Qwik
Папка, src/components
является рекомендуемым каталогом для компонентов. Из коробки есть три каталога для компонентов icons
, header
и router-head
.
components
├── icons
│ └── qwik.tsx
├── header
│ ├── header.tsx
│ └── header.css
└── router-head
└── router-head.tsx
Компонент QwikLogo
Компонент QwikLogo
находится внутри src/components/icons
. В настоящее время он включает файл логотипа SVG, qwik.tsx
.
Вот 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>
);
Импортируйте этот файл в программу просмотра SVG, и мы увидим логотип Qwik.
Компонент заголовка
Компонент Header
находится внутри src/components/header
. Он определяет заголовок веб-сайта по умолчанию, отображаемый ниже, где логотип Qwik расположен в верхней левой области.
В папке два файла src/components/header
:
header.tsx
header.css
Вот 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>
);
});
Приведенный выше код очень похож на React.
component$()
(строка 5) — это определение компонента в Qwik, и оно (строки 5–43) определяет повторно используемый фрагмент кода, который можно использовать для создания пользовательского интерфейса, аналогичного функциональному компоненту в React.
useStylesScoped$()
(строка 6) создает стиль с заданной областью.
Что такое $?
Это символ для оптимизатора и разработчика, чтобы знать, что оптимизатор применит преобразование для извлечения выражения, следующего за $
, и превратит его в лениво загружаемый и импортируемый символ.
Вот 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;
}
Это файл CSS, который определяет селекторы тегов и классов для header
компонента.
Компонент RouterHead
Компонент RouterHead
находится внутри src/components/router-head
. Он определяет содержимое, размещенное внутри <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&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} />
))}
</>
);
});
Он помещается внутри head
элемента root.tsx
:
<head>
<meta charSet="utf-8" />
<RouterHead />
</head>
В браузере View Page Source
показывает преобразованное содержимое заголовка.
<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&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>
Маршруты Qwik
Папка src/routes
основана на QwikCity, который поддерживает следующие функции:
- Маршрутизация на основе каталогов
- Вложенные макеты
- Файловые меню
- Панировочные сухари
- Поддержка авторского контента с форматами файлов
.tsx
или.mdx
- Конечные точки данных
По умолчанию маршруты включают следующие файлы/каталоги:
маршруты
├── layout.tsx
├── index.tsx
├── service-worker.ts
└── flower
├── flower.css
└── index.tsx
Компонент макета
В приложении разные маршруты обычно имеют что-то общее, например верхний и нижний колонтитулы. Эти общие части реализуются компонентом макета, который повторно используется для каждой страницы.
Вот 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>
</>
);
});
В строке 8 общее Header
помещается вверху страницы.
В строке 10 Slot
используется для размещения дочернего компонента в середине страницы.
В строках 13–17 footer
элемент размещается внизу страницы.
Индексный маршрут
Листовой файл на каждом маршруте имеет имя index
, где тип файла может быть .ts
, .tsx
, .js
, .jsx
, .md
или .mdx
.
Определяет index.tsx
пользовательский интерфейс, который размещается в слоте (в красном поле ниже), когда URL-адрес равен /
.
Следующее src/routes/index.tsx
реализует описанный выше пользовательский интерфейс с красной рамкой простым способом.
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",
};
Работник службы
Традиционный сервис-воркер обеспечивает предварительную выборку и кэширование. Qwik City использует сервис-воркер для динамической предварительной выборки того, что можно выполнить. Отсутствие предварительной загрузки всего приложения освобождает ресурсы для запроса только небольших частей, которые пользователь может использовать для отображаемого пользовательского интерфейса.
Вот 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;
Этот файл может включать или отключать сервисного работника. Если приложение вообще не хочет использовать сервис-воркер, просто удалите setupServiceWorker()
(строку 3) из файла.
Цветочный маршрут
На маршруте /flower
показана демонстрация цветка, построенная из массива преобразованных квадратов.
Переходим к http://localhost:5173/flower
, и видим вращающийся цветок.
В папке 2 файла src/routes/flower
:
index.tsx
flower.css
Определяет index.tsx
пользовательский интерфейс, который размещается в слоте, когда URL-адрес равен /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",
};
- В строках 10–59 определяется цветочный компонент.
useStylesScoped$()
(строка 11) создает стиль с ограниченной областью действия.useLocation
(строка 12) извлекает расположение URL.- В строках 14–17 создаются два состояния
count
иnumber
.count
обновляет переменную css--state
(строка 39), которая используется для вычисления квадратного преобразования вflower.css
.number
используется для управления количеством квадратов (строка 46) в цветке. - В строках 19–25 задается
useClientEffect$
интервал обновления квадратов. - В строках 29–36 он определяет ползунок диапазона для изменения
number
. - В строках 37–45 он определяет расположение цветка.
- В строках 46–55 создается массив
div
с классомsquare
. Он также добавляет класс,odd
если индексi
нечетный. Эти классы используются для стилизации массиваdiv
. - В строках 61–63 определяется
head
компонент, и он будет помещен внутри<head>
элемента документа.
Интересно, что параметр запроса URL-адреса проверяется в строке 43 на предмет того, является ли он /flower?pride=true
. Когда это правда, он добавляет класс pride
.
Давайте посмотрим на 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;
}
- В строках 1–18 настраивается макет хоста.
- В строках 20–22 ползунок диапазона определяется с помощью
100%
width
. - В строках 24–45 стилизованы квадраты.
- В строках 47–54 нечетные индексированные квадраты имеют разные цвета фона.
- В строках 56–73 для div с классами
pride
иsquare
некоторые из них определены с разными цветами фона.
Переходим к http://localhost:5173/flower?pride=true
, и видим вращающийся красочный цветок.
Почему Qwik быстрый?
Qwik работает быстро, так как утверждает, что время загрузки составляет O(1). Его быстрое время загрузки обусловлено возможностью повторного использования, прогрессивностью и реактивностью.
Вот кнопка со слушателем:
<button on:click="./chunk.js#handler_symbol">click me</button>
HTML-код должен загрузить функцию JavaScript для выполнения, а эта функция вызывает загрузку большего количества вещей для всей логики приложения.
Qwik отличается тем, что не требует гидратации для возобновления работы приложения на клиенте. Его возобновляемость заключается в приостановке выполнения на сервере и возобновлении выполнения на клиенте без повторного воспроизведения и загрузки всей логики приложения.
Qwik сериализует прослушиватель событий в DOM в следующем формате:
<button on:click="./chunk.js#handler_symbol">click me</button>
Атрибут on:click
содержит имя пакета и символ функции. Он может возобновить работу приложения на стороне клиента только тогда, когда пользователь нажмет кнопку. Это делает Qwik быстрее других фреймворков.
Прогессивность
Прогрессивность заключается в загрузке кода по мере необходимости, без необходимости жадно загружать всю кодовую базу. В Qwik все загружается лениво:
- Компонент при рендеринге (блок инициализации и блок рендеринга)
- Компонент на часах (побочные эффекты, загружаются только при изменении входных данных)
- Слушатели (загружаются только при взаимодействии)
- Стили (загружаются только в том случае, если сервер их еще не предоставил)
Реактивность
Qwik отслеживает, какие компоненты на какое состояние подписаны. Эта информация позволяет Qwik аннулировать только соответствующий компонент при изменении состояния, что сводит к минимуму количество компонентов, которые необходимо повторно отобразить.
Вывод
Qwik — это среда JavaScript, которая лениво загружает код по мере взаимодействия пользователя. Он предлагает максимально быстрое время загрузки страницы независимо от сложности веб-сайта. Время его загрузки O(1).
Мы объяснили установленное приложение Qwik. Его синтаксис похож на React. Qwik является ядром, а Qwik City построен на основе Qwik с организованными компонентами и маршрутами.
Приложение Qwik легко создать, и оно обеспечивает максимально быстрое время загрузки страницы независимо от сложности веб-сайта.