为何多数Jaspr组件需添加@client注解?(Dart)
Jaspr中无客户端逻辑的页面组件为何必须添加@client注解?
错误原因:Jaspr的代码拆分与水合机制
你遇到的AssetNotFoundException本质是Jaspr的构建逻辑约束导致的:所有路由页面组件必须标记为@client,不管组件有没有客户端交互逻辑。核心原因在于:
- Jaspr采用服务端渲染(SSR)+客户端水合(Hydration)的混合模式,客户端需要匹配服务端渲染的DOM结构,这就要求页面组件的代码必须存在于客户端包中。
@client注解的核心作用不是标记"有客户端逻辑",而是告诉构建工具:该组件需要被打包到客户端代码中,用于完成水合过程和路由匹配。- 当你移除
@client后,构建工具不会生成该组件的客户端资产文件(比如.client.dart、.ddc.dill),但路由系统仍然尝试在客户端加载这些组件,从而抛出资产找不到的错误。
关于服务端路由提取的疑问
你的猜测有误,context.binding.currentUri在服务端和客户端都能正常访问:
- 服务端渲染时,Jaspr会将当前HTTP请求的URI注入到
BindingContext中,所以你在build方法里可以直接获取路由参数。 - 客户端水合时,
currentUri会对应浏览器的当前URL,保证前后端路由一致。
你可以通过kIsServer常量区分前后端环境,验证这一点:
import 'package:jaspr/jaspr.dart'; import 'package:jaspr/server.dart'; // 引入kIsServer @client class EmptyPage extends StatelessComponent { const EmptyPage({super.key}); @override Iterable<Component> build(BuildContext context) sync* { final uri = context.binding.currentUri; if (kIsServer) { print('[Server] 当前请求URI: $uri'); // 服务端打印请求URL } else { print('[Client] 当前浏览器URI: $uri'); // 客户端打印浏览器URL } final page = uri.pathSegments.last; yield h1([text('Empty: $page')]); } }
例外情况:纯服务端静态组件
如果某个组件是完全静态的、不需要参与客户端水合(比如页面底部的版权信息),可以使用@server注解标记,这样构建工具不会将其打包到客户端代码中。但注意:@server组件不能作为路由页面使用,只能作为页面内的子组件,因为路由页面必须参与客户端的路由匹配和水合流程。
内容的提问来源于stack exchange,提问作者cdemy Leitung
相关产品推荐
相关产品推荐

