常见问题

@QwikDev 是一个有意识的 AI 吗?

是的,而且我还非常有趣!关注我

为什么叫 Qwik?

最初它被称为 qoot,但我们认为这个名字很难搜索。我们的一位朋友 @patrickjs__ 提出了 Qwik 这个名字,经过 builder.io 的内部投票,我们决定采用这个名字!

Qwik 与其他框架有什么不同?

Qwik 是第一个在组件编写方面与 ReactVueSvelte 具有相似 DX(开发者体验)的框架,同时提供即时交互的 实时 HTML。Qwik 通过完全消除水合作用来实现这一特性。相反,Qwik 应用程序会在用户交互时立即执行事件处理程序,而无需引导所有应用程序状态。这种技术被称为可恢复性

结果是,开发人员无需担心,即使不做任何额外的工作,他们编写的应用程序也会自动具有极高的性能。使用 Qwik 构建的应用程序无论组件数量或复杂性如何,都具有出色的性能,它们在 JS 负载方面是 O(1)(常数时间)的。

为什么需要另一个框架?

简短的答案是,Qwik 解决了其他框架无法解决的问题。无论应用程序有多复杂,Qwik 都具有即时启动性能。Qwik 应用程序的初始 JS 量不受组件数量的影响。Qwik 是第一个开源的 O(1) 框架

Qwik City 是什么?

Qwik City 只是 Qwik 之上的一组额外的 API。可以将其视为 Qwik 是核心,City 是额外的 API(路由、数据加载、端点等)。我们将其称为 Qwik 的元框架。Qwik City 对于 Qwik 来说就像 Next.js 对于 React、Nuxt 对于 Vue、SvelteKit 对于 Svelte 一样。

Qwik 难学吗?

Qwik 是以 React(和其他基于 JSX 的框架)为设计目标的,确保学习起来轻松无压力,并提高开发效率。开发组件与 React 几乎相同,而路由则受到 Next.js 和其他框架的启发。

然而,还有一些新概念需要学习,例如可恢复性和细粒度的响应性,但我们认为学习曲线并不陡峭。

我们还有一个互动的教程,可以帮助你入门。

那些 $ 符号是什么意思?

你可能已经注意到在 Qwik 应用程序中有比平常更多的 $ 符号,例如:component$()useTask$()<div onClick$={() => console.log('click')} />。它们用作懒加载边界的标记。Qwik 将应用程序分解为小块;这些块比组件本身更小。对于事件处理程序、钩子等,$ 同时向优化器和开发人员发出信号。

示例:

import { component$ } from '@builder.io/qwik';
 
export default component$(() => {
  console.log('render');
  return <button onClick$={() => console.log('hello')}>Hello Qwik</button>;
});

由于 $ 语法,上面的组件被拆分为:

app.js
import { componentQrl, qrl } from '@builder.io/qwik';
 
const App = /*#__PURE__*/ componentQrl(
  qrl(() => import('./app_component_akbu84a8zes.js'), 'App_component_AkbU84a8zes')
);
 
export { App };
app_component_akbu84a8zes.js
import { jsx as _jsx } from '@builder.io/qwik/jsx-runtime';
import { qrl } from '@builder.io/qwik';
export const App_component_AkbU84a8zes = () => {
  console.log('render');
  return /*#__PURE__*/ _jsx('p', {
    onClick$: qrl(
      () => import('./app_component_p_onclick_01pegc10cpw'),
      'App_component_p_onClick_01pEgC10cpw'
    ),
    children: 'Hello Qwik',
  });
};
app_component_p_onclick_01pegc10cpw.js
export const App_component_p_onClick_01pEgC10cpw = () => console.log('hello');

注意:$jQuery、Svelte 或任何其他框架无关。

Qwik 在用户交互时会下载 JS 吗?

不会。在生产环境中,Qwik 使用 SSR(服务器端渲染)期间生成的大量信息,尽快地开始预填充缓存,仅将当前页面上的交互部分作为可用部分预先加载到缓存中。这样,当用户点击或交互时,JS 已经在缓存中了。

如果 Qwik 仍然请求 JS,那有什么区别?

预填充缓存与解析和执行 JS 不同,Qwik 在用户交互之前不执行 JS。

此外,预取模块使得 Qwik 可以优先处理重要的交互部分,然后再处理不太重要的部分。

例如,“立即购买”按钮比“添加到购物车”按钮更重要,因此 Qwik 会首先预取“立即购买”按钮,然后再预取“添加到购物车”按钮。

Qwik 不需要预取所有内容才能开始运行,而其他框架需要在开始运行之前下载整个关键路径,因为水合作用的原因。

Qwik 应用在网络较慢的情况下会变慢吗?

完全不会!由于 预取模块,Qwik 应用在网络较慢的情况下不会比其他框架受到更大的影响。事实上,由于细粒度的打包和可恢复性,Qwik 应用在较少的 JS 下就可以实现交互,从而在网络较慢的情况下更快。

Qwik 会生成太多小文件吗?

在开发模式下,Qwik 会生成很多小文件,因为它使用 Dev Vite.js 服务器,但在生产模式下,Qwik 会以更高效的方式打包文件。

为什么 Qwik 使用 JSX?它是 React 底层实现吗?

不是的,Qwik 根本不使用 React。Qwik 使用 JSX 作为模板语法。

请注意,JSX 不是 React。实际上,JSX 只是语法,没有语义。我们选择 JSX 有几个原因:

  • 熟悉的语法: 它不是重复造轮子,而是利用现有的 JS 循环、条件等。JSX 规范非常简短
  • 生态系统: 得到 IDE、代码检查工具、安全审计工具、调试工具和高亮显示器的良好支持。
  • 类似于 HTML: JSX 在视觉上和概念上与 HTML 类似,都是树形结构。而其他模板系统(如 html templates(lit-html))不是树形结构,而是令人难以构建和转换的令牌数组。
  • 流行: 无论如何,JSX 都是世界上使用最广泛的模板语法。

Qwik 使用虚拟 DOM(vDOM)吗?

答案介于两者之间:

你可以将其视为一个光谱:

  • 一个极端是 React,它始终使用 vDOM。(可以说 vDOM 是慢的。)
  • 另一个极端是 SolidJS,它根本不使用 vDOM。(导致非常出色的性能。)

Qwik 有时使用 vDOM,其他时候则像 SolidJS 那样(直接更新 DOM)。

思考方式如下:

如果状态的更改没有结构性变化,那么 Qwik 很可能不会使用 vDOM。例如:

没有 DOM 结构变化,只是更新值
export const NoStructuralChange = component$(() => {
  const count = useSignal(0);
 
  return (
    <>
    {/* 这不会触发 vDOM。(没有 DOM 结构变化,只是更新文本值) */}
     <div>Count: {count.value}</div>
     <button onClick$={() => count.value++}>+1</button>
    </>
  );
});

当发生结构性变化时,Qwik 会使用 vDOM。在下面的示例中,DOM 结构需要更新(将 <h1> 替换为 <button>),因此将使用 vDOM 进行渲染:

DOM 结构变化
export const StructuralChange = component$(() => {
  const isLoggedIn = useSignal(false);
  return (
    <div>
      {isLoggedIn.value ? <h1>you are logged in!</h1> : <button>Log in</button>}
    </div>
  )
});
 

需要理解的重要事情(以及 vDOM 在 Qwik 中不会成为性能问题的原因)是,在 React 中,当你使根组件无效时,整个树的 vDOM 都会被创建。在 Qwik 中,决策是基于每个组件的基础上进行的。只有具有结构性变化且实际上正在更改其结构的组件才会使用 vDOM。如果组件是结构性的(vDOM),但没有检测到结构性变化,那么 Qwik 将跳过该组件。你可以将其视为所有组件的自动记忆化,这意味着只有在视图发生结构性变化时才会使用 vDOM。这种情况很少见,因为在大多数情况下,视图只会更改其值。

简而言之,Qwik 使用 vDOM,但在可比较的情况下远远少于 React。

为什么在具有负面声誉的情况下使用 vDOM?

  1. 因为 vDOM 具有吸引人的 DX 特性,特别是当你需要动态组件时。
  2. 因为非 vDOM 解决方案需要在启动时至少执行一次代码,以了解组件结构。这是 Qwik 明确避免的事情。

例如:

动态组件
const DynamicList = [ CompA, CompB, ...];
export const DynamicExample = component$(() => {
  const idx = Math.floor(Math.random() * DynamicList.length);
  const Component = DynamicList[idx];
  {/* 动态选择要渲染的组件 */}
  return <Component/>; 
})

上面的代码 <Component/> 非常容易理解。我们动态选择要放置的组件。但在 SolidSvelteVueAngular 中,这变得复杂(请参阅链接)。

通过谨慎使用 vDOM,我们拥有了最佳的两个世界。在创建过程中,我们使用 SSR,大多数客户端更新都是非结构性的。当需要结构性更新时,它们仅限于特定组件,而不会影响其子组件,从而限制了 vDOM 可能引起的任何潜在的减速。

Qwik 有路由器吗?

有!Qwik City 包括一个基于目录的路由器,受 Next.js 和其他框架的启发。

部署 Qwik 应用程序需要服务器吗?

你可以在任何无服务器环境中轻松部署 Qwik 应用程序。我们还支持原生 Node 适配器,用于基于 Node.js 的服务器,如 Express。

如果不需要 SSR,你可以将 Qwik 应用程序部署为静态站点,感谢我们的SSG(静态站点生成)适配器

哪个更快:SPA(单页应用)还是 MPA(多页应用)?

这取决于情况。对于 SPA,大部分成本都是在会话开始时下载所有内容。因此,当用户与应用程序交互时,成本很小。

MPA 的加载速度非常快,因为它们不需要下载与 SPA 相同数量的 JS。但是,当用户导航时,通常需要完整的页面重新加载。完整的页面重新加载通常非常快,因为浏览器非常快地下载和解析 HTML,但是 MPA 的方法并不适用于每个项目,因为有时最好在导航之间保持状态,而 SPA 可以很好地实现这一点。

Qwik 是一种独特的框架,同时是 MPA 和 SPA。

Qwik 能做 SPA 吗?

当然可以!Qwik City 包括 <Link> 组件,它触发 SPA 导航。 使用 Qwik,开发人员不需要在 SPA 和 MPA 之间进行选择,每个应用程序同时具备这两个功能。

MPA 和 SPA 不再是项目开始时的架构决策,而是每个链接的决策。

Qwik 能做静态站点生成(SSG)吗?

可以!这是所有 Qwik City 起始模板的一部分。了解如何进行静态站点生成

但是... 使用其他框架,我也可以创建 MPA 或 SPA 吗?

不完全是这样,其他框架建议删除根部的所有 <Scripts> 以生成 MPA,从而连同 SPA 导航一起删除所有交互性。

如果不删除脚本,则每次完整页面重新加载都会非常昂贵,因为每次页面重新加载都意味着框架需要对整个页面进行水合。然而,Qwik 对于每个页面加载都没有水合成本

迁移到 Qwik 需要付出很大的努力吗?

这取决于情况。如果你来自 React,将你的组件迁移到 Qwik 应该是直接的。此外,由于 Qwik React,你可以使用 React 生态系统的所有功能,因此可以在 Qwik 应用程序中使用任何 React 组件和任何 React 库。

我可以享受丰富的 React 生态系统吗?

可以!Qwik 可以原生运行 React 组件,查看文档

你会感到惊讶!

Qwik 是否支持部分水合?

不支持。部分水合(或岛屿架构)是由 Astro 推广的一种将应用程序分解为交互性岛屿的方法,以避免完整页面水合,其中需要下载和执行页面中的所有现有组件。

为了使其工作,开发人员需要手动定义岛屿,然后手动描述何时应该进行水合。岛屿之间也无法相互通信。

相反,Qwik 组件根本不进行水合。Qwik 通过一个强大的序列化系统实现了这一点,该系统仅序列化响应性图中所需的状态。这样,应用程序可以在不急切运行任何 JS 的情况下恢复。

我们认为可恢复性在没有部分水合的负面交换的情况下可以扩展。

Qwik 使用哪些语言编写?

Qwik 的大部分是使用 TypeScript 编写的,TypeScript 是一种添加了可选静态类型和其他功能的 JavaScript 超集。然而,Qwik 编译器(或优化器)是用 Rust 编写的,Rust 是一种非常快速和内存高效的语言。

Qwik 有社区吗?

有!在 DiscordGitHub 上有一个不断壮大的 Qwik 开发者社区。他们为框架做出了很多贡献,构建了大规模的网站,并相互帮助。加入我们

Qwik 是 "Alex Russell 批准" 的框架吗?

是的!Alex Russell(@slightlylate)是众所周知的 PWA、W3C TAG、WC、TC39 和 ES6、Chrome Frame、Dojo 等的贡献者,他经常对 JavaScript 框架持高度批评态度。尽管如此,他批准了 Qwik

Qwik 已经准备好用于生产了吗?

是的!Qwik 已经达到了 1.1 版本。Qwik 已经开发了 3 年了。我们相信 Qwik 已经准备好用于生产,并且不会有预期的重大变化。

Builder.io 和许多团队已经在生产中使用 Qwik,所以你不会孤单。

Qwik 在 HTML 中序列化了太多的数据,是真的吗?

不是的。Qwik 仅序列化当前页面所需的数据。如果一个页面有 1000 个组件,但只有一个是交互式的,那么序列化的数据量与交互性的数量成比例,而不是组件的数量。

谁构建了 Qwik?

一个由全球各地的贡献者组成的令人惊奇的团队,他们在 Discord 上生活,并且还有一些全职开发人员在 Builder.ioMiskoAdamManu Almeida

Qwik 是开源的吗?

是的,MIT 许可证,且无依赖,安装 Qwik 不会使你的 node_modules 或律师臃肿。

Qwik 有什么缺点吗?

是的。每个框架都有自己的优点和缺点,都涉及权衡。

  1. 作为一个相对较新的 JS 框架,Qwik 的社区和生态系统仍在发展中,尽管发展迅速,但你可能还没有找到你从更受欢迎的框架中习惯的所有可能的社区项目、模式和最佳实践。
  2. Qwik 可以加载任何规模的 JS 应用程序 - 瞬间加载,因此它相对于当前技术的主要优势在于初始页面加载和交互时间。如果你的用例是单页面应用程序,并且不介意应用程序加载所需的时间,那么在这个阶段采用 Qwik 可能不会立即给你带来好处。

我们不断努力改进开发者体验和功能,使 Qwik 对于任何用例都更加令人愉快,因此请继续关注。

Contributors

Thanks to all the contributors who have helped make this documentation better!

  • tidiview
  • adamdbradley
  • manucorporat
  • hamatoyogi
  • fabien0102
  • the-r3aper7
  • ryankshaw
  • McMillanThomas
  • ahhshm
  • jangerhofer
  • mrcaidev
  • literalpie
  • zanettin
  • forresst
  • dzearing
  • fum4
  • colynyu
  • eltociear
  • tihuan
  • ptu14
  • reemardelarosa
  • ETN-Tech
  • spicyzboss
  • mhevery
  • wtlin1228
  • ilteoood
  • PatrickJS