Vite 官方 Qwik + TypeScript 启动模板(CSR 模式)深度解析
本文围绕 Vite 官方 create-vite 脚手架内置的 template-qwik-ts(Qwik + TypeScript)启动模板展开。该模板展示了如何用 Vite 驱动一个纯 CSR(Client-Side Rendering)模式的 Qwik 应用:从 qwikVite({ csr: true }) 插件配置、create-vite 中的模板注册逻辑,到入口引导链(qwikloader.js → render)、Qwik 信号与事件指令(useSignal、onClick$),以及模板的 TypeScript 工程配置。读完本文,你将理解该模板每个文件的职责、各 npm 脚本的构建行为,以及 CSR 模式与 Qwik 全栈 SSR/QwikCity 方案的适用边界。
模板定位:它是 create-vite 中的哪个脚手架
template-qwik-ts 位于仓库的 packages/create-vite/template-qwik-ts/ 目录,是 create-vite(即 npm create vite@latest)可选模板之一。在脚手架入口 packages/create-vite/src/index.ts 中,Qwik 以 name: 'qwik' 的形式注册了一组变体:
qwik-ts:TypeScript 版,即本文分析的这个模板;qwik:JavaScript 版(对应 template-qwik 目录);custom-qwik-city(显示为 "QwikCity ↗"):不走本地模板,而是直接执行npm create qwik@latest empty TARGET_DIR,引导用户使用 Qwik 官方的服务端元框架 QwikCity 创建完整的生产级应用。
因此,通过 CLI 创建该模板项目的标准方式是:
npm create vite@latest my-qwik-app -- --template qwik-ts
cd my-qwik-app
npm install # 或使用 pnpm / yarn
模板自身的 README 也明确提示:如果目标是"完整、生产就绪、使用 SSR 和 QwikCity 的 Qwik 应用",应使用 npm create qwik@latest,而不是本模板。本模板的定位是纯 CSR 的快速起步——应用完全在浏览器中引导(bootstrap),不依赖服务端渲染。README 中同时指出:Qwik 的许多核心创新(如 resumability 等)通常是在 SSR 模式下发挥作用的,CSR 模式属于 Qwik 运行形态中的一个子集。
构建配置:qwikVite 插件与 CSR 开关
模板的 Vite 配置极其精简,见 vite.config.ts:
import { qwikVite } from '@builder.io/qwik/optimizer'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
qwikVite({
csr: true,
}),
],
})
要点说明:
- 插件来源:
qwikVite从@builder.io/qwik/optimizer子路径导出,而非主包。这与 Qwik 包的组织方式有关——其 Vite 集成(负责 JSX/TSX 转换、component$编译、事件指令处理等)被拆分在 optimizer 子包中。 csr: true:这是本模板与 Qwik SSR 项目的关键配置差异。该选项告知插件以纯客户端渲染方式处理构建产物:不需要为 Node.js 环境生成服务端 bundle,也就不需要额外的 SSR 入口文件与打包步骤。从模板文件结构看,整个src/下只有main.tsx、app.tsx与若干静态资源,没有任何 server entry,印证了 CSR 单入口的形态。- 除此之外没有配置任何 alias、resolve 或自定义 build 选项——Qwik 模板把复杂度都收敛到了插件内部,用户侧的 Vite 配置保持最小化。
依赖与 npm 脚本
package.json 定义了三个脚本和一组最小依赖:
{
"name": "vite-qwik",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "serve dist"
},
"devDependencies": {
"@types/node": "^24.13.3",
"serve": "^14.2.6",
"typescript": "~6.0.2",
"vite": "^8.2.2"
},
"dependencies": {
"@builder.io/qwik": "^1.20.0"
}
}
按 README 中的 "Available Scripts" 一节,各脚本行为如下:
npm run dev:启动 Vite 开发服务器,默认在 http://localhost:5173 访问。开发模式下享受原生 ESM 快速冷启动与 HMR(README 中提示修改src/app.tsx保存即可验证 HMR 生效)。npm run build:执行tsc -b && vite build,即先用 TypeScript 项目引用模式做类型检查(见下文 tsconfig 一节),再调用vite build产出生产构建到dist目录。注意这里tsc -b只校验不输出(各子 tsconfig 均为noEmit: true),产物完全由 Vite 生成。npm run preview:使用serve dist静态托管构建产物,用于本地验证生产构建效果。serve因此被放在 devDependencies 中。
依赖层面,运行时依赖仅有 @builder.io/qwik(^1.20.0);开发期依赖包括 Vite 8.x、TypeScript 6.x 及 @types/node、serve,整体保持"框架只有一个包"的轻量结构。
入口引导链:index.html → main.tsx → qwikloader.js
CSR 应用的启动流程可以从三个文件串起来:
1. index.html —— 标准 Vite HTML 入口,<body> 内只有一处挂载点和一个模块脚本:
<div id="app"></div>
<script type="module" src="/src/main.tsx"></script>
<head> 中引用了 public/ 下的 favicon.svg 作为站点图标。
2. src/main.tsx —— 客户端引导入口:
import '@builder.io/qwik/qwikloader.js'
import { render } from '@builder.io/qwik'
import './index.css'
import { App } from './app.tsx'
render(document.getElementById('app') as HTMLElement, <App />)
两行关键导入体现了 Qwik 的启动约定:
@builder.io/qwik/qwikloader.js:Qwik 的运行时加载器,负责在运行时管理组件代码的懒加载(resumability 相关机制依赖它在浏览器侧的工作)。CSR 模式下它同样会被引入,保证与 SSR 产物的运行时行为一致;render(element, <App />):Qwik 提供的客户端渲染 API,将根组件挂载到index.html中id="app"的占位 DOM 上。
3. src/app.tsx —— 根组件,也是模板附带的示例代码,集中演示了 Qwik 的三个核心 API:
export const App = component$(() => {
const count = useSignal(0)
// ...
<button type="button" class="counter" onClick$={() => count.value++}>
Count is {count.value}
</button>
})
component$:Qwik 的组件声明函数(注意$后缀是 Qwik 组件/函数命名惯例的一部分);useSignal(0):响应式信号,count.value的变化会驱动 DOM 更新;onClick$:Qwik 的事件指令。它以 JSX 属性形式声明事件处理,事件函数在首次序列化后以"可恢复(resumable)"的形态保存在标记化输出中,点击时才需要求值——这正是 README 中所说"多数创新在 SSR 下更充分"的机制在 CSR 场景中的降级表现:CSR 下组件在浏览器内挂载,事件绑定同样可用,但序列化-恢复链路不会跨越服务端。
组件中还通过 import heroImg from './assets/hero.png' 等方式引入了 assets 下的图片(hero.png、qwik.svg、vite.svg),由 Vite 的静态资源管线处理;index.css 与 app.css 分别承载全局样式与组件区块样式。页面中的 SVG 图标通过 public/ 下的 icons.svg 以 <use href="/icons.svg#documentation-icon"> 形式引用,走 Vite 的静态资源直出。
TypeScript 工程配置:双引用结构
模板沿用 Vite 生态通用的"项目引用"式 TS 组织,tsconfig.json 本身不编译任何文件,仅声明两个引用:
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}
-
tsconfig.app.json:覆盖
src/,moduleResolution: "bundler"、verbatimModuleSyntax、jsx: "react-jsx"。其中最值得注意的是:"jsxImportSource": "@builder.io/qwik"Qwik 的 JSX 运行时(
jsx/jsxs/Fragment)来自 Qwik 包自身而非 React,这个配置让tsc按 Qwik 的 JSX 类型签名校验模板代码——这是 Qwik 能"借用 React 风格 JSX 语法但拥有独立运行时"的关键接线。 -
tsconfig.node.json:仅包含
vite.config.ts,module: "nodenext"、types: ["node"],为配置文件提供独立的 Node 环境类型。
build 脚本中的 tsc -b 即按这两个引用顺序做增量类型检查(tsBuildInfoFile 指向 node_modules/.tmp/),检查通过后才执行 vite build。
适用边界与升级路径
综合模板 README 与 create-vite 源码,可以归纳出该模板的适用边界:
| 维度 | 本模板(template-qwik-ts) | Qwik 官方脚手架 |
|---|---|---|
| 渲染模式 | 纯 CSR,浏览器引导 | SSR 为主 |
| 路由/元框架 | 无,单页 #app 挂载 |
QwikCity(文件路由、meta 等) |
| 构建配置 | qwikVite({ csr: true }) 单插件 |
更完整的服务端 + 客户端双端配置 |
| 创建命令 | npm create vite@latest my-app -- --template qwik-ts |
npm create qwik@latest |
如果你的项目目标只是快速体验 Qwik 的组件/信号/事件指令 API 与 Vite 开发体验(例如学习 useSignal、component$、onClick$),本模板足够;一旦需要服务端渲染、文件路由或生产级部署形态,应切换到 create-vite 中注册的 QwikCity 入口(对应命令 npm create qwik@latest empty TARGET_DIR)。
关键文件索引
| 文件 | 作用 |
|---|---|
| packages/create-vite/template-qwik-ts/README.md | 模板说明:CSR 模式、用法与脚本 |
| packages/create-vite/template-qwik-ts/vite.config.ts | qwikVite({ csr: true }) 构建配置 |
| packages/create-vite/template-qwik-ts/package.json | dev / build / preview 脚本与依赖 |
| packages/create-vite/template-qwik-ts/index.html | HTML 入口与 #app 挂载点 |
| packages/create-vite/template-qwik-ts/src/main.tsx | qwikloader 引入与 render 引导 |
| packages/create-vite/template-qwik-ts/src/app.tsx | 根组件示例:component$ / useSignal / onClick$ |
| packages/create-vite/template-qwik-ts/tsconfig.app.json | 应用侧 TS 配置与 Qwik JSX 运行时接线 |
| packages/create-vite/src/index.ts | create-vite 中 Qwik 模板变体的注册逻辑 |
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00