Show HN:我用 TypeScript 重写了 PHP(演示)
Show HN: I reinvented PHP in TypeScript (demo)

原始链接: https://github.com/vseplet/morph

Morph是一个可嵌入的全栈库,用于构建无需构建步骤的超媒体驱动应用程序,专为Deno、Bun和Node.js环境设计。它利用HTMX进行服务器端渲染,融合了SSR、SPA和岛屿架构的优点,同时遵循纯HTML、CSS和JS。它最初是为了优化Telegram Web App的开发而创建的,因为传统的前端技术栈对于小型项目来说过于复杂。 其关键特性包括:无需构建步骤、客户端JavaScript代码极少、组件的服务器端渲染,以及组件能够调用自身返回超文本的API的能力。组件可以嵌套并独立重新渲染,形成一个层次结构。当无需分离前端和后端时,Morph尤其出色,使其成为Telegram机器人、桌面应用程序或需要动态UI而无需完整前端技术栈的内部工具的理想选择。它目前运行在Hono之上,未来可能会支持其他后端。

The "Show HN" post introduces Morph, a TypeScript library aiming to simplify full-stack web development by rendering HTML directly from the server. The author pitches it as a "PHP reinvented in TypeScript" alternative, avoiding complex front-end frameworks, build steps, and preprocessors. It targets use cases like internal tools, dashboards, and Telegram web apps where single-page applications feel like overkill. The comments highlight differing opinions. Some appreciate the simplicity and potential for rapid development, echoing the ease of old-school PHP. Others argue that modern PHP practices emphasize separation of concerns and templating. Some suggest it resembles templating approaches in Node.js with tagged template literals. Concerns are raised about performance compared to PHP's shared-nothing architecture and deployment considerations, with some mentioning serverless environments like Deno Deploy. Overall, the project sparks a discussion about balancing simplicity and modern development practices in web development.

原文

JSR GitHub commit activity GitHub last commit

This package is under development and will be frequently updated. The author would appreciate any help, advice, and pull requests! Thank you for your understanding 😊


Morph is an embeddable fullstack library for building Hypermedia-Driven Applications without a build step, based on HTMX.

Morph combines the best of SSR, SPA, and islands architecture, while sticking to plain HTML, CSS, and JS.

I created Morph while optimizing the development of Telegram Web Apps using Deno and Deno Deploy. Traditional stacks that separate frontend and backend with complex APIs and use React or Vue felt overly heavy, complex, and expensive for small projects.

Currently, Morph runs on Hono, but support for other backends may be added in the future.

  • Each component can call its own API that returns hypertext (other components)\
  • All components are rendered on the server and have access to server-side context\
  • Components can be rendered and re-rendered independently\
  • Components form a hierarchy, can be nested in one another, and returned from APIs\
  • Minimal or no client-side JavaScript\
  • No build step\
  • No need to design API data structures upfront\
  • The library can be embedded into any Deno/Node/Bun project\

Morph is ideal when there’s no need to split frontend and backend into separate services. It works especially well for small Telegram bots, desktop apps, or internal tools that don’t justify a full frontend stack but still need a clean and dynamic UI.

Deno
deno add jsr:@vseplet/morph jsr:@hono/hono

Bun
bunx jsr add @vseplet/morph
bun add hono

Node
npx jsr add @vseplet/morph
npm i --save hono @hono/node-server

Make main.ts and add imports

Deno

import { Hono } from "@hono/hono";
import { component, fn, html, meta, morph, styled } from "@vseplet/morph";

Bun

import { Hono } from "hono";
import { component, fn, html, meta, morph, styled } from "@vseplet/morph";

Node

import { serve } from '@hono/node-server'
import { Hono } from "hono";
import { component, fn, html, meta, morph, styled } from "@vseplet/morph";

Create simple page (for all runtimes)

const app = new Hono()
  .all("/*", async (c) =>
    await morph
      .page("/", component(async () => html`
          ${meta({ title: "Hello, World!" })}

          <h1>Hello, World!</h1>

          <pre class="${styled`color:red;`}">${
            (await (await fetch("https://icanhazdadjoke.com/", {
              headers: {
                Accept: "application/json",
                "User-Agent": "My Fun App (https://example.com)",
              },
            })).json()).joke
          }</pre>

          ${fn(() => alert("Hello!"))}
        `),
      )
    .fetch(c.req.raw));

Deno

Bun

Node

Deno
deno -A main.ts

Bun
bun main.ts

Node
node --experimental-strip-types main.ts

MIT

联系我们 contact @ memedata.com