Deno Fresh&Platform的开始
#css #网络开发人员 #typescript #deno

ð为什么要新鲜使用Deno?

  • deno Fresh 构建快速站点因此您获得头等舱用户体验(ux)
  • 使用平台因此,如果您已经知道 javascript apis ,那么新鲜开始就可以很快开始,将它们与混音,Astro或Sveltekit一起使用),
  • 令人惊叹的开发人员体验(DX) 无服务器没有构建步骤,部署是 live 几乎立即强>。

ð¶½什么是新鲜的?

deno Fresh是下一个代网站构建器。 它构建了服务器端渲染(SSR)站点并支持部分水合。在DENO JavaScript运行时进行新鲜运行,该运行时间优先考虑安全性和性能。在Deno,JavaScript API是一流的公民 - 它使用该平台。这使DeNo更快,更易于学习。 Deno在服务器上呈现您的网站,默认情况下将零javaScript归为浏览器。这使得内容网站的新鲜选择。通过内容网站,我们的意思是那些主要是文档,博客等,通常不是很互动。

当您需要在新鲜站点上进行交互性时,可以使用Fresh's 部分水合功能集。这仅意味着页面的部分是交互式的部分,也称为互动岛,得到水合。水合只是浏览器中页面加载中的一步,允许交互性的代码加载,并且这些组件的状态变得一致。

ð - 您如何旋转一个新鲜的应用程序?

要走,您将在开发环境中需要Deno。如果您尚未安装它,它很快就可以从MacOS上使用自制的终端设置或Linux上的Shell脚本:

# macOS
brew install deno

# Linux
curl -fsSL https://deno.land/install.sh | sh

# Test installation worked
deno --version

与node.js基于运行时的工具相比,通常您可以通过URL运行应用程序和访问软件包。这正是我们可以采取的措施来旋转新的Deno Fresh应用程序。安装了Deno后,在终端中键入这些命令以进行操作:

deno run -A -r https://fresh.deno.dev my-fresh-app && cd $_
deno task start

ð§deno Fresh开始:里面有什么?

.
├── components
│   └── Button.tsx
├── deno.json
├── deno.lock
├── dev.ts
├── fresh.gen.ts
├── import_map.json
├── islands
│   └── Counter.tsx
├── main.ts
├── routes
│   ├── [name].tsx
│   ├── api
│   │   └── joke.ts
│   └── index.tsx
└── static
    ├── favicon.ico
    └── logo.svg
  • 使用Deno Fresh,您可以在 preacct 中写下您的组件(如果您第一次提前做出反应)。您的提前组件文件会根据是否具有互动性,将其放置在componentsislands目录中。因此,更改状态的按钮可以在islands中进行,但是使用平台和WebApis的表单可以进入components
  • deno.json 此松散地图映射到node.js中的package.json文件。随附的start任务是您运行的要启动应用程序,并告诉DeNo运行dev.ts文件(也列出了上面),
  • import_map.json 以及列出包装的别名,我们将看到如何在此文件中添加项目源文件的导入别名,
  • main.ts :这是我们从中运行内置的Web服务器的地方。您可以为TLS添加其他配置,而不是这里的内容,
  • routes :此文件夹包含将其映射到网站上实际页面的文件。如果您已经使用 Astro remix next.js 基于文件的路由系统将非常熟悉。 routes/index.tsx将在您的最终站点上映射到https://example.com/,而routes/about.tsx将映射到https://example.com/aboutroutes/[name].tsx是动态页面模板。这提供了例如,从单个文件中创建/offices/london/offices/berlin/offices/mumbai,而无需重复内容并访问模板中的城市名称参数(/offices/[office-name].tsx)。
  • static 适用于不需要诸如Favicons,pwas或 logos manifest.webmanifest文件。

故意缺少什么?

注意没有

  • package.json:使用Deno Fresh,您可以使用 import_map.json 用于依赖项和deno.json中的tasks字段用于脚本,
  • tsconfig.json:Deno Fresh带有内置的打字稿支持,并选择明智的默认值在引擎盖下,可以帮助您更快地进行新项目,
  • eslint.jseslint.config.js:只需使用deno lint命令 - 不需要配置这个,
  • .prettierrc.prettierignore:类似于Rust,格式也已集成到工具中。当您想整理代码时,运行deno fmt
  • vitest.config.ts:您猜到了deNo在工具中内置了

ð«9 deno入门的快速提示

  1. 权限:DENO优先确定安全性,并使您对应用程序的访问权限有了更多的控制。
{
  "tasks": {
    "start": "deno run -A --watch=static/,routes/ dev.ts"
  }, // ...TRUNCATED
}

start脚本中的-A标志授予我们的应用程序访问所有权限,包括文件系统(读取和写入),环境变量和网络。如果您希望更细的粒度控件将其删除并重新启动您的应用程序。现在,您将看到提示在终端中要求各种权限。

  1. 环境变量 在云中,您可以在DENO部署控制台(或您的主机等效)中定义秘密。在本地,与其他工具一样,您可以使用.env文件。请记住将其添加到您的.gitignore文件中,以免秘密投入您的git reco。
.env
.DS_Store
DATABASE_PASSWORD="open-sesame"

对于您的项目访问.env文件,您可以添加https://deno.land/std@0.171.0/dotenv软件包。 DENO的新方法是用$std/别名更新导入地图:

{
  "imports": {
    "$fresh/": "https://deno.land/x/fresh@1.1.2/",
    "preact": "https://esm.sh/preact@10.11.0",
    "preact/": "https://esm.sh/preact@10.11.0/",
    "preact-render-to-string": "https://esm.sh/*preact-render-to-string@5.2.4",
    "@preact/signals": "https://esm.sh/*@preact/signals@1.0.3",
    "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.0.1",
    "$std/": "https://deno.land/std@0.167.0/"
  }
}

作为最佳实践,包括URL中的软件包版本(以使您的应用程序在较新的包装版本中引入破坏变化时,请按预期工作)。接下来,从dev.ts文件中的dotenv导入加载脚本:

#!/usr/bin/env -S deno run -A --watch=static/,routes/

import dev from "$fresh/dev.ts";
import "$std/dotenv/load.ts";

await dev(import.meta.url, "./main.ts");

请注意两件事:您将.ts扩展包含在路径中,您可以使用刚创建的新别名。如果需要,您可以在导入语句中写出整个URL,而不是使用别名:

// EXAMPLE ONLY PREFER USING ALIASES AS ABOVE
import "https://deno.land/std@0.167.0/std/dotenv/load.ts";

这里的缺点是,您可能会在其他源文件中使用std,当您想升级到0.168.0时,您需要更新您包含完整路径的每个文件。使用别名方法,您只需要更新该文件导入地图。

最后,在您的源代码中,您可以使用Deno.env.get()访问秘密变量:

const DATABASE_PASSWORD = Deno.env.get("DATABASE_PASSWORD");
if (typeof DATABASE_PASSWORD !== 'string') {
  throw new Error("env `DATABASE_PASSWORD` must be set");
}
  1. vscode设置:您可能已经在项目中有一个.vscode/extensions.json文件(取决于您回答设置提示的方式)。
{
  "recommendations": [
    "denoland.vscode-deno"
  ]
}

这将导致VSCODE在打开项目时提示您安装DENO扩展程序。我注意到,即使在非DENO项目中,扩展也正在连接到网络。因此,现在我将其按正常安装,然后在Vscode扩展程序中找到DENO,然后单击 disable 按钮。最后,我单击下拉列表以选择 enable(workspace)
扩展名增加了刺激提示和格式化功能。要使用保存格式,请更新.vscode/settings.json

{
  "deno.enable": true,
  "deno.lint": true,
  "editor.defaultFormatter": "denoland.vscode-deno",
  "editor.formatOnSave": true,
}

我注意到当我从终端运行deno fmt时,自动格式保存的文件会稍微更改,但是想象这将很快解决。

  1. 浏览器与服务器在其他框架中,您可能还记得必须进行一些检查以确保仅在客户端中运行一块代码。您可以在components/Button.tsx中看到一个如何实现这一目标的示例:
import { JSX } from "preact";
import { IS_BROWSER } from "$fresh/runtime.ts";

export function Button(props: JSX.HTMLAttributes<HTMLButtonElement>) {
  return (
    <button
      {...props}
      disabled={!IS_BROWSER || props.disabled}
    />
  );
}

如果代码未在浏览器中运行,则在此禁用该按钮,但是如果您使用本地存储(例如),则可以使用此按钮,并且需要通过window.localStorage在客户端上访问它。

9个快速入门的快速技巧继续(5)(9)

  1. deno std 我们以前向import_map.json添加了std软件包以访问dotenv。这是 deno标准库(Deno具有标准库,例如C和Rust)。除了dotenv,您还可以使用std for:
    • $std/crypto :要在服务器端代码中访问webcrypto apis,
    • $std/encoding :用于从Markdown文件中提取前染色或生成BasicAuth HTTP标头的base64,
    • $std/http 用于与HTTP Cookie合作。
    • $std/path 用于您可能在node:path中找到的文件操作,
    • $std/testing/asserts $std/testing/bdd $std/testing/snapshot.ts 用于玩笑风格的asserts以及行为驱动的测试describeit。对于柴风格expect尝试https://cdn.skypack.dev/chai@4.3.4?dts

顺便说一句,从$std/fmt/bytes.ts导入的format将文件大小格式化为易于可读字符串。

  1. 查找软件包:deno与node.js有些不同,因为您不必使用npm作为软件包存储库,也可以从URL导入包装。在引擎盖下,Deno在本地缓存该软件包(有点像PNPM),因此每次启动应用程序时都无需重新下载它们。第三方模块的三个来源是:

    • deno x:https://deno.land/x?在这里找到deno特定模块,
    • skypack:https://cdn.skypack.dev/ NPM软件包的替代方案,
    • esm.sh:https://esm.sh/另一个NPM软件包替代方案。
  2. 更多的别名以及为外部模块添加别名,还可以为项目文件夹定义它们。例如,更新import_map.json

{
  "imports": {
    "@/": "./",
    "$fresh/": "https://deno.land/x/fresh@1.1.2/",
    "preact": "https://esm.sh/preact@10.11.0",
    "preact/": "https://esm.sh/preact@10.11.0/",
    "preact-render-to-string": "https://esm.sh/*preact-render-to-string@5.2.4",
    "@preact/signals": "https://esm.sh/*@preact/signals@1.0.3",
    "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.0.1",
    "$std/": "https://deno.land/std@0.167.0/"
  }
}

现在我们可以整理routes/index.tsx中的导入语句:

import { Head } from "$fresh/runtime.ts";
// import Counter from "../islands/Counter.tsx";
import Counter from "@/islands/Counter.tsx";

这可以使您的代码看起来更加干净,并且还可以更轻松地映射导入的位置。

  1. 404页:创建通过在项目中添加routes/_404.tsx文件来创建未找到的自定义页面:
import { Head } from "$fresh/runtime.ts";
import { UnknownPageProps } from "$fresh/server.ts";

export default function NotFoundPage({ url }: UnknownPageProps) {
  const title = "Page not found 😢";
  const description = "I don’t think you are supposed to be here!";

  return (
    <>
      <Head>
        <title>{title}</title>
      </Head>
      <main>
        <h1>{title}</h1>
        <p>
          Not sure: <code>{url.pathname}</code> exists mate!
        </p>
      </main>
    </>
  );
}

注意,我们在此处使用Head组件将<title>元素添加到我们的页面的html <head>中。

  1. Favicons去哪儿了?这也是添加您的自托管字体甚至CSS的好地方。如果您使用的是PostCSS,则可能需要将输入CSS放在项目根部的单独的styles文件夹中,然后将PostCSS输出输出,将CSS转移到static/styles。我们将进一步了解如何自动将哈希相附加到服务的文件名上,以便在更新时缓存。

DENO路线文件的解剖结构

作为第一步,请查看Deno Fresh Skeleton内容中包含的routes/index.tsx文件。它导出一个默认函数,该功能是一个preact组件。如果您熟悉反应或预先反应,那么这里没有什么有趣的。

即使在一个相当基本的网站上,您也可能需要在项目中使用数据库甚至Markdown文件中的内容。这是Deno Fresh的工作,让您在服务器上进行操作并使用Deno 处理程序功能来源。处理程序函数可以与渲染内容(例如,routes/index.tsx中的导出的React组件)放在同一文件中。我喜欢与渲染内容相同的文件中采购数据的模式。对于较小的网站,它可以帮助您更快地调试,甚至可以帮助您记住几个月前写的页面的工作方式。

DENO新路线请求处理程序

我从一个小的DeNo应用程序中修剪了一个源文件,以安排推文,这是一种可怜的Hootsuite或Buffer的表亲。这将有助于我们说明一些更真实的DENO新鲜功能。让我们首先查看数据处理部分:

import { Handlers, PageProps } from "$fresh/server.ts";
import type {
  ScheduledTweet,
} from "@/utils/twitter.ts";
import { Temporal } from "js-temporal/polyfill/?dts";
import { Fragment } from "preact";

interface HappyPathData {
  scheduledTweets: ScheduledTweet[];
  error?: never;
}
interface ErrorData {
  scheduledTweets?: never;
  error: string;
}
type Data = HappyPathData | ErrorData;

export const handler: Handlers<Data> = {
  GET(request, context) {

    // my own function to get list of already scheduled tweets
    const scheduledTweets = getScheduledTweets() ?? [];

    return context.render({
      scheduledTweets,
    });
  },
  POST(request, context) {
    const form = await request.formData();
    const action = form.get("action");
    const id = form.get("id");

    if (action === "retweet" && typeof id === "string") {
      const text = form.get("text");
      const date = form.get("date");
      const time = form.get("time");

      if (typeof date === "string" && typeof time === "string") {
          // my own function to schedule a tweet
          scheduleRetweet({
            id,
            scheduleTime,
            text,
          });
      } 

    }
    const { scheduledTweets } = getScheduledTweets() ?? [];

    return context.render({
      scheduledTweets,
    });
  },
};

Typescript支持不断出现,我们什么也没添加以使其正常工作。您可以看到handler有两个组件:一个GET处理程序,而当页面加载和一个PUT处理程序时,我们将通过提交表单(即将出现的前端代码)调用。请注意,GETPUT是如何以HTTP请求方法命名的。DENO喜欢该平台!这些功能以requestcontext参数为输入。 request是标准的WebAPI请求,我们可以应用formData()json()text()方法来操纵请求主体。我们还可以破坏headersmethodurl等。

同时,context包含一个params对象。对于模板路线(还记得londonmumbai等中的办公室)吗?那里的模板文件名是routes/offices/[office-name].tsx。好吧,例如,如果我们想在访问者访问https://example.com/offices/mumbai时从数据库中取出正确的办公室的电话号码,我们可以使用上下文访问mumbai部分:

  GET(request, context) {
        const {
      params: { 'office-name': officeName },
    } = context;
    const phoneNumber = getPhoneNumber(officeName);
    // ...TRUNCATED

context.render()

以及让我们访问路径参数,上下文对象还定义了render方法。这就是为我们提供服务器端渲染的原因。通过返回它,我们可以将数据传递到客户端模板中。让我看看接下来。

客户端反应代码

请记住,我们可以保持简单,将此代码放在与处理程序同一文件中。我们没有在处理程序中处理上面的操作(以使事情变得简单),但是如果我们从数据库中提取一些问题的推文,我们可能会返回错误。检查客户端代码中的错误,我们可以让用户知道某些内容不正确。这里的<Fragment></Fragment>在句法上等同于使用<></>。如果您是不熟悉的反应或预先反应,您可能不知道,我们的渲染元素必须具有一个顶级元素(这就是为什么要包装Fragment中的其他元素,否则HTMLHeadHeader,等等都是最高级别的元素。

export default function TweetQueue(ctx: PageProps<Data>) {
  const {
    data: { error, scheduledTweets, tweets },
  } = ctx;

  if (error) {
    return (
      <Fragment>
        <HTMLHead
          title="Isolinear 🖥 | Twitter | Tweet Queue"
          description="Isolinear tweet queue."
        />
        <Header />
        <h1>Something went wrong!</h1>
        <p>{error}</p>
      </Fragment>
    );
  }

  const { url } = ctx;
  const { searchParams } = url;
  const retweet = searchParams.get("retweet");
  const id = searchParams.get("id");
  const minDate = Temporal.Now.plainDateTimeISO().toPlainDate().toString();

  return (
    <Fragment>
      <h1>Twitter</h1>
      <h2>Retweet</h2>
      {retweet === "true" && typeof id === "string"
        ? (
          <Fragment>
            <h3 id="retweet">Retweet</h3>
            <form action="/twitter/tweet-queue" method="post">
              <input type="text" name="id" value={id} />
              <input
                type="text"
                name="text"
                placeholder="Tweet text"
                maxLength={280}
              />
              <input type="date" name="date" min={minDate} />
              <input type="time" list="tweet-schedule" name="time" />
              <input type="hidden" name="action" value="retweet" />
              <button type="submit">[ retweet ]</button>
            </form>
          </Fragment>
        )
        : null}
    </Fragment>
  );
}

如果我们需要访问页面URL,则可以使用ctx Prop进行。最后,请注意,我们有一个表格来处理提交新推文。这可以使用该平台工作,而无需其他JavaScript。如果您是新手,请检查MDN文档。一次学习一次,然后在sveltekit的DeNo Fresh中使用它,在Remix,Astro,甚至是普通的HTML/CSS网站!当用户单击按钮时,表单元素上的action="/twitter/tweet-queue" method="post"表示浏览器将向POST http请求发送到/twitter/tweet-queue(此精确路由)。然后,上面处理程序中的POST功能将照顾好它。你没有娱乐ð

DeNo Fresh:总结

我们才刚刚开始!但是,帖子不会变得太长,在后续行动中,我们会看到:

  • deno Fresh Islands 工作,
  • deno的内置测试框架
  • 创建 API路由和更多!

到目前为止的旅程是,我们已经快速看了Deno Fresh的开始。特别是,我们看到了:

  • 如何创建一个新的Deno Fresh App
  • 一些有用的 deno标准库函数
  • 如何将数据传递到客户端React页面。

查看新鲜文档以获取更多详细信息。如果您想了解更多关于Deno和Fresh的内容,请与我们联系。我希望您发现内容有用,并热衷于了解可能的改进。

Deno Fresh:反馈

您发现该帖子有用吗?您想看另一个主题的帖子吗?与新帖子的想法联系。另外,如果您喜欢我的写作风格,请与您联系,如果我可以在咨询中为您的公司网站编写一些帖子。请继续阅读以找到与之联系的方法,以下更远。如果您想支持与此类似的帖子,并且可以浪费几美元,欧元或英镑,请访问consider supporting me through Buy me a Coffee

最后,请随时在社交媒体帐户上分享所有发现有用的关注者的帖子。除了在下面留下评论外,您还可以通过@askRodney在Twitter上与Mastodon上的@rodney@toot.community#rodney元素矩阵室取得联系。另外,请参见further ways to get in touch with Rodney Lab。我定期发布在AstroDeno上。还有subscribe to the newsletter to keep up-to-date与我们的最新项目。