返回资讯中心
外部精选
软件工程
#开发者实时流

ohne 发布零依赖免构建 TypeScript Web 框架

来源标题:Show HN: Nobuild TypeScript web framework with zero dependencies

ohne 是一个零依赖、无需构建的 TypeScript Web 框架,开发者声明字段后框架自动生成管理后台,字符串、选项和关联均可按语言本地化。它借助 Node 直接剥离类型运行 .ts 文件,没有打包器和 dist 目录,并支持多层叠加、就近覆盖。

Hacker News 最新murisceman2026/11/7 · 今天13 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

声明你的字段。ohne 围绕这些字段生成管理后台——每个字符串、下拉选项和关联都可按语言翻译,无需任何同步维护。

当你运行代码、叠加一个层、声明一个集合,或请求另一种语言时,会发生什么。

Node 会剥离你 .ts 文件中的类型并直接运行它们。仪表盘拿到的是同样的文件,按需进行类型剥离。无需打包器,没有 dist 文件夹。

你写什么,就运行什么 常规做法会先把 app.ts 构建到 dist/ 再运行。使用 ohne 时,Node 剥离 app.ts 的类型后直接运行。常规做法app.tsbuilddist/runohneapp.tstitle: string = 'Hi'runrunNode 剥离类型 02叠加层,覆盖任何内容 一个层就是一组集合、路由和消息的打包。把你的层叠加在应用之下。越近的层优先,而你的应用优先级最高。

叠加层 三个层像纸片一样叠放:ohnejs/base 提供 Users 和 /login,@acme/blog 提供 Posts 和 /feed,而你的应用提供自己的 /login。运行时每个位置取自最近一个填充它的层,因此你的 /login 会替换掉 ohnejs/base 中的那个。你的应用@acme/blogohnejs/base/loginPosts/feedUsers/login运行时Users/loginPosts/feed越近的层优先 03集合变成表 每个集合就是一张表,而关联列表会拥有自己的链接表。无论读取两行还是两百行,开销都是同样几次查询。

集合变成表 一个带有 title 和 tags 的 Posts 集合会变成一张带有 title 列的 Posts 表,通过 Posts_tags 表关联到 Tags 表。读取帖子及其标签需要 3 次查询,每张表一次,无论 2 行还是 200 行。Posts.tstitle:field('text'),tags:field('records', {collection:'Tags',}),PoststitlePosts_tagsTagsquery('Posts').populate('tags').findMany()2 行20 行200 行3 次查询 04一条记录,所有语言 翻译字段位于记录旁边,每种语言一行。读取时会连接你请求的语言。缺失的语言读到 null,绝不猜测。

一条记录,所有语言 Posts 行把翻译保存在 Posts__translations 中,每种语言一行:en 为 Welcome,de 为 Willkommen。请求 de 读到 title 为 Willkommen。请求 bs(没有对应行)读到 title 为 null,不会静默回退。PostsslugwelcomePosts__translationsenWelcomedeWillkommen.locale('de').locale('bs') title: 'Willkommen' title: null不静默回退 你写什么,就运行什么 常规做法会先把 app.ts 构建到 dist/ 再运行。使用 ohne 时,Node 剥离 app.ts 的类型后直接运行。常规做法app.tsbuilddist/runohneapp.tstitle: string = 'Hi'runrunNode 剥离类型叠加层 三个层像纸片一样叠放:ohnejs/base 提供 Users 和 /login,@acme/blog 提供 Posts 和 /feed,而你的应用提供自己的 /login。运行时每个位置取自最近一个填充它的层,因此你的 /login 会替换掉 ohnejs/base 中的那个。你的应用@acme/blogohnejs/base/loginPosts/feedUsers/login运行时Users/loginPosts/feed越近的层优先集合变成表 一个带有 title 和 tags 的 Posts 集合会变成一张带有 title 列的 Posts 表,通过 Posts_tags 表关联到 Tags 表。读取帖子及其标签需要 3 次查询,每张表一次,无论 2 行还是 200 行。Posts.tstitle:field('text'),tags:field('records', {collection:'Tags',}),PoststitlePosts_tagsTagsquery('Posts').populate('tags').findMany()2 行20 行200 行3 次查询一条记录,所有语言 Posts 行把翻译保存在 Posts__translations 中,每种语言一行:en 为 Welcome,de 为 Willkommen。请求 de 读到 title 为 Willkommen。请求 bs(没有对应行)读到 title 为 null,不会静默回退。PostsslugwelcomePosts__translationsenWelcomedeWillkommen.locale('de').locale('bs') title: 'Willkommen' title: null不静默回退 实践 一个集合、两条路由、一个 hook 和一个仪表盘页面。每个都是约定目录中的普通 TypeScript 文件,ohne dev 会监视它们全部。 import { defineCollection, field } from 'ohnejs'; export default defineCollection({ api: true, fields: { title: field('text', { translatable: true, max: 120 }), status: field('select', { choices: ['draft', 'published'], default: 'draft' }), author: field('record', { collection: 'Users' }), body: field('text', { multiline: true }), }); 保存文件后,API 会重新加载,表也一并就位。无需迁移文件,无需 SQL,且同步会拒绝任何可能导致数据丢失的更改。api: true 会在角色检查之后,将其挂载到 /collections/posts 下提供服务。 以下所有内容都随 ohnejs 提供。叠加 ohnejs/uploads 以获得文件功能,或叠加 ohnejs/ai 以获得助手功能,也可以编写你自己的层。 集合与字段 字段类型 查询 翻译 模式同步 路由 集合 API Hooks 认证 消息 仪表盘 CLI 层 上传 助手 部署 开始使用 回答几个提示。你会得到一个已安装其唯一依赖的新项目。 启动 API 和仪表盘。打开 localhost:9000 查看。类型会重新生成,每次保存时 API 都会重新加载。 创建 collections/Posts.ts 并列出其字段。保存时,ohne 会创建表,你的查询会知道其字段,仪表盘会列出 Posts。构建你的第一个应用 ohne 的每个部分都有指南:项目、数据库、HTTP API、认证、国际化、仪表盘和生产环境。

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →