deno使用rust_使用graphql和deno构建ssr react应用程序

2023-10-14 13:59

本文主要是介绍deno使用rust_使用graphql和deno构建ssr react应用程序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

deno使用rust

介绍(Introduction)

Unless you have been living under a rock, I am sure you have been hearing all the hype on Deno and/or GraphQL in the past few years. If you are intrigued by these technologies and enjoy learning new technologies by building with them, then you're in the right place!

除非您一直生活在一块石头下,否则我相信您会在过去几年中听到有关Deno和/或GraphQL的所有炒作。 如果您对这些技术感兴趣,并且喜欢通过与它们一起构建来学习新技术,那么您来对地方了!

迪诺背景 (Background on Deno)

On May 13, 2018, Ryan Dahl, the creator of Node.js announced Deno, a new secure runtime for JavaScript and Typescript, during his “10 Things I Regret About Node.js” talk. In this talk, he mentioned some of the improvements that Deno aims to implement, such as abstracting the need for dependency solutions like NPM modules and package.json, supporting TypeScript out of the box by implementing a snapshotted TypeScript compiler, and breaking the sandboxed environment of the V8 engine.

2018年5月13日,Node.js的创建者Ryan Dahl在“我对Node.js的十件事感到遗憾”演讲中宣布了Deno,这是一个用于JavaScript和Typescript的新安全运行时。 在本次演讲中,他提到了Deno旨在实现的一些改进,例如抽象出对依赖解决方案(如NPM模块和package.json)的需求,通过实现快照TypeScript编译器开箱即用地支持TypeScript,以及打破沙盒环境。 V8引擎。

After two years, on May 13, 2020, it was announced that Deno was ready for production, and has been backed my major cloud providers such as AWS Lambda, Azure Functions, and Google Cloud Run.

两年后,即2020年5月13日,宣布Deno可以投入生产,并得到了我的主要云提供商的支持,例如AWS Lambda,Azure Functions和Google Cloud Run。

总览 (Overview)

Throughout this article, we will be building a simple application to show Rick and Morty character information utilizing React, GraphQL, and Deno. During the process, we will be implementing server-side rendering with Deno’s Oak framework, as well as executing and caching GraphQL queries with Deno’s Obsidian library.

在整个本文中,我们将构建一个简单的应用程序,以利用React,GraphQL和Deno显示Rick和Morty的角色信息。 在此过程中,我们将使用Deno的Oak框架实现服务器端渲染,并使用Deno的Obsidian库执行和缓存GraphQL查询。

让我们开始吧! (Let's get right into it!)

First things first, we need to set up our file structure.

首先,我们需要设置文件结构。

my-app
├── client
│ ├── Components
| ├── static
│ ├── app.tsx
│ └── client.tsx
├── server.tsx
├── deps.ts
├── serverDeps.tsx
├── staticFileMiddleware.ts
├── tsconfig.json
└── README.md
  • client is where we will store all our React components, static files, and theapp.tsx andclient.tsx files.

    client是我们存储所有React组件,静态文件以及app.tsxclient.tsx文件的地方。

  • deps.ts and serverDeps.ts serve to import all of the Deno modules used throughout the application in one place.

    deps.tsserverDeps.ts用于将整个应用程序中使用的所有serverDeps.ts模块集中到一个位置。

  • staticFileMiddleware.ts will contain the logic to handle requests for static files.

    staticFileMiddleware.ts将包含处理静态文件请求的逻辑。

  • tsconfig.json specifies the root files and the compiler options required to compile the TypeScript project.

    tsconfig.json指定根文件和编译TypeScript项目所需的编译器选项。

导入Deno模块 (Importing Deno Modules)

Since we have determined all of the libraries that we will be importing on our client-side and server-side, we will begin by creating deps.ts files to import them into our application.

由于我们已经确定了要在客户端和服务器端导入的所有库,因此我们将首先创建deps.ts文件以将其导入到我们的应用程序中。

import React from 'https://dev.jspm.io/react@16.13.1';
import ReactDom from 'https://dev.jspm.io/react-dom@16.13.1';
import {ObsidianWrapper,useObsidian,
} from 'https://deno.land/x/obsidian@v0.1.6/ObsidianWrapper/ObsidianWrapper.jsx';export { React, ReactDom, ObsidianWrapper, useObsidian };
  • deps.ts is where we will be importing all the Deno modules that will be utilized in the client-side of the application.

    deps.ts是我们将导入将在应用程序客户端使用的所有Deno模块的地方。

import {Application,Router,Context,send,
} from 'https://deno.land/x/oak@v6.0.1/mod.ts';
import ReactDomServer from 'https://dev.jspm.io/react-dom@16.13.1/server';export { Application, Router, ReactDomServer, Context, send };
  • serverDeps.ts is where we will be importing all the Deno modules that will be utilized in the server-side of the application.

    serverDeps.ts中,我们将导入将在应用程序服务器端使用的所有Deno模块。

服务器端渲染 (Server-side Rendering)

Now that we have imported all our modules in one central location, we can begin setting up our server. We will be utilizing Deno’s Oak middleware framework, and ReactDOMServer to render components to static markup.

现在,我们已将所有模块导入一个中央位置,我们可以开始设置服务器了。 我们将利用Deno的Oak中间件框架和ReactDOMServer将组件呈现为静态标记。

import { Application, Router, ReactDomServer } from './serverDeps.ts';
import { React } from './deps.ts';
import App from './client/app.tsx';
import { staticFileMiddleware } from './staticFileMiddleware.ts';const PORT = 3000;// Create a new server
const app = new Application();// Router for base path
const router = new Router();router.get('/', handlePage);// Bundle the client-side code
const [_, clientJS] = await Deno.bundle('./client/client.tsx');// Router for bundle
const serverrouter = new Router();
serverrouter.get('/static/client.js', (context) => {context.response.headers.set('Content-Type', 'text/html');context.response.body = clientJS;
});// Implement the routes on the server
app.use(staticFileMiddleware);
app.use(router.routes());
app.use(serverrouter.routes());
app.use(router.allowedMethods());app.addEventListener('listen', () => {console.log(`Listening at http://localhost:${PORT}`);
});
await app.listen({ port: PORT });// Function to render entire application as a string
function handlePage(ctx: any) {try {const body = (ReactDomServer as any).renderToString(<App />);ctx.response.body = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><link rel="stylesheet" href="/static/style.css"><meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Rick and Morty</title></head><body ><div id="root">${body}</div><script  src="/static/client.js" defer></script></body></html>`;} catch (error) {console.error(error);}
}

If you are familiar with Express.js and/or Koa.js the structure for creating routers and endpoints with the Oak framework above should be very familiar. If you skim through the code there are two main things that differ from what you may be used to: the Deno.bundle function on line 17 and the HTML file at the bottom of the code block.

如果您熟悉Express.js和/或Koa.js,那么使用上述Oak框架创建路由器和端点的结构应该非常熟悉。 如果您浏览了代码,则有两个主要的方面与您可能习惯的有所不同:第17行的Deno.bundle函数和代码块底部HTML文件。

The Deno.bundle function is one of the great features that Deno provides. Similar to how you would use a bundler like Webpack to transpile and compile your application in Node.js, Deno has that functionality out of the box. The Deno.bundle function takes an entry point of the client-side code as an argument and transpiles and bundles the client-side file structure into a single javascript file to be sent to the client.

Deno.bundle函数是Deno.bundle提供的重要功能之一。 与您使用像Webpack这样的打包器在Node.js中转译和编译应用程序的方式类似,Deno可以立即使用该功能。 Deno.bundle函数将客户端代码的入口点作为参数,并进行编译并将客户端文件结构捆绑到单个javascript文件中,以发送给客户端。

The second nuance above is the handlePage function, starting on line 38. When this function is invoked, it begins by utilizing the rendertoString function that is provided by the ReactDOMServer package. The React application is passed into this function and converts the entire application into an HTML string. So when a “GET” request for the root endpoint is received by the server, the entire React application is sent to the client as a string.

上面的第二个细微差别是handlePage函数,从第38行开始。调用此函数时,它首先利用ReactDOMServer包提供的rendertoString函数。 React应用程序传递到此函数中,并将整个应用程序转换为HTML字符串。 因此,当服务器收到对根端点的“ GET”请求时,整个React应用程序将作为字符串发送到客户端。

While the page does load faster, it is a marked down version of the page, meaning that it does not have any of the React functionality — this is why a request is made for the bundled javascript file on line 52. With server-side rendering, the React application never uses the render method and instead uses a hydrate method. Since the webpage is already rendered, the browser receives the bundled javascript file and parses through the rendered application, seamlessly reinjecting the React functionality into the application.

尽管该页面确实加载得更快,但这是该页面的标记版本,这意味着它不具有任何React功能-这就是为什么在第52行上请求捆绑的javascript文件的原因。服务器端渲染,React应用程序从不使用render方法,而是使用hydrate方法。 由于已经渲染了网页,因此浏览器会接收捆绑的javascript文件并通过渲染的应用程序进行解析,从而将React功能无缝地重新注入到应用程序中。

客户端代码和GraphQL (Client-side code and GraphQL)

Now that we have covered server-side rendering from the server-side, let's take a look at how we are able to achieve this functionality on the client-side.

现在我们已经从服务器端介绍了服务器端渲染,下面让我们看一下如何在客户端上实现此功能。

import { React, ReactDom } from '../deps.ts';
import App from './app.tsx';// Hydrate the app and reconnect React functionality
(ReactDom as any).hydrate(<App />, document.getElementById('root'));

The code snippet above demonstrates the entry point into the client-side code. Notice how the hydrate method is used instead of render.

上面的代码段演示了客户端代码的入口点。 注意如何使用hydrate方法而不是render

Pretty simple, right? Well, let’s look into how we can incorporate GraphQL fetching and caching functionality into our application.

很简单,对吧? 好吧,让我们研究如何将GraphQL提取和缓存功能整合到我们的应用程序中。

import { React, ObsidianWrapper } from '../deps.ts';import MainComponent from './DemoComponents/MainComponent.tsx';declare global {namespace JSX {interface IntrinsicElements {div: any;}}
}const App = () => {return (<ObsidianWrapper><MainComponent /></ObsidianWrapper>);
};export default App;

In order to cache our GraphQL requests, we will be using the ObsidianWrapper . Similar to how you would wrap your application in a provider when using a React state management library, utilizing this wrapper supplies caching capabilities to our GraphQL requests. This improves the performance of the app, providing consistent data throughout the application and reducing the load on the backend.

为了缓存GraphQL请求,我们将使用ObsidianWrapper 。 与使用React状态管理库时将应用程序包装在提供程序中的方式类似,利用此包装器可以为我们的GraphQL请求提供缓存功能。 这可以提高应用程序的性能,在整个应用程序中提供一致的数据,并减少后端的负载。

提取和缓存GraphQL请求 (Fetching and caching GraphQL requests)

Finally, we will be taking a look at how we will be fetching and caching our GraphQL requests in the following code block.

最后,我们将研究如何在以下代码块中获取和缓存GraphQL请求。

import { React, useObsidian } from '../../deps.ts';
import Sidebar from './Sidebar.tsx';
import Carousel from './Carousel.tsx';declare global {namespace JSX {interface IntrinsicElements {h1: any;div: any;}}
}const GET_CHARACTERS = `query{characters(page:1){results{idnameimage}}}
`;const MainPage = () => {const [info, setInfo] = (React as any).useState({});const [characters, setCharacters] = (React as any).useState([]);const { gather } = useObsidian();(React as any).useEffect(() => {gather(GET_CHARACTERS, {endpoint: 'https://rickandmortyapi.com/graphql',destructure: false,}).then((resp: any) => setCharacters([...resp.data.characters.results]));}, []);return (<div id='main-container'><h1>Rick and Morty Character Guide</h1><div id='app-container'><Sidebar info={info} /><Carousel characters={characters} setInfo={setInfo} /></div></div>);
};export default MainPage;

We will first begin by importing the useObsidian hook which allows us to access the functionality provided by the wrapper. On line 31 we invoke the hook which gives us access to a few different methods. Here we are using the gather method which gives us the ability to fetch and cache GraphQL requests. The first parameter of this method is the GraphQL query and the second is an “options” parameter. For the sake of simplicity, we are using an external API and specifying to not destructure the query and response since this requires us to provide the application with the GraphQL schema. If you are curious about Obsidian’s normalization and destructuring capabilities, check out the article below.

首先,我们将导入useObsidian挂钩,该挂钩允许我们访问包装器提供的功能。 在第31行,我们调用该钩子,该钩子使我们可以访问一些不同的方法。 这里我们使用的gather方法,它为我们提供了获取和缓存GraphQL请求的能力。 此方法的第一个参数是GraphQL查询,第二个参数是“选项”参数。 为简单起见,我们使用外部API并指定不破坏查询和响应,因为这要求我们为应用程序提供GraphQL模式。 如果您对黑曜石的标准化和解构功能感到好奇,请查看下面的文章。

结语 (Wrapping up)

Now that we have built our core structure, we can add some additional functionality to query for more specific query information about each individual character. Finally, we add some minor styling to wrap it all up!

现在我们已经建立了核心结构,我们可以添加一些附加功能来查询有关每个字符的更具体的查询信息。 最后,我们添加一些较小的样式以将其全部包装!

Image for post

If you would like to have a look at the source code you can find the repository at https://github.com/Alonsog66/GraphQL-Deno-Medium-Demo.

如果您想看一下源代码,可以在https://github.com/Alonsog66/GraphQL-Deno-Medium-Demo中找到存储库。

结论 (Conclusion)

And there you have it! As you can see there are some major changes when working with Deno as opposed to Node.js — we do not store external modules locally, TypeScript can be compiled out of the box, and we did not need to configure a webpack.config.js file to specify the compiling as Deno can natively perform all of the transpiling and bundling. If you have any questions about any of this material covered feel free to post a comment below or reach out via LinkedIn.

在那里,您拥有了! 如您所见,与Deno相比,与Node.js相比,使用Deno时有一些重大更改-我们不在本地存储外部模块,TypeScript可以直接编译,并且我们不需要配置webpack.config.js文件指定编译,因为Deno可以本地执行所有转码和捆绑。 如果您对本文涵盖的任何内容有任何疑问,请随时在下面发表评论或通过LinkedIn进行联系。

Cheers!

干杯!

翻译自: https://medium.com/@alonsogarza6/building-an-ssr-react-application-with-graphql-and-deno-832c391bf8f2

deno使用rust


http://www.taodudu.cc/news/show-7958345.html

相关文章:

  • 带你五步学会Vue SSR
  • NGW,前端新技术赛场:Serverless SSR 技术内幕
  • 云原生时代的搜索服务算力管理
  • 阿里巴巴 Noslate 正式开源 - 面向云原生的 JavaScript 容器方案
  • 任正非一语成真,中国的鸡正回中国下蛋!一场巨变即将到来
  • 互联网大厂程序员,挣到1900万是财务自由的标准线?
  • cpython包_cpython 教程
  • Web开发团队常备工具
  • 将一组数据放入一个新数组中
  • 大华 摄像头 rtmp 拉流
  • 内网穿透代理服务器nps使用初探(三)微信小程序内网穿透
  • 微信小程序安装后打开一直提示:当前代理不是安全代理
  • 解决PC小程序抓包问题
  • 微信小程序请求数据出现跨域问题
  • 微信小程序https和wss,nginx代理,
  • burp抓不到微信小程序数据包的问题
  • 小程序如何访问本地后端服务
  • 【转】提升Exadata 计算节点本地IO性能
  • Repair the Wall
  • Exadata X3-2 存储服务器BBU 更换
  • opencv处理图片
  • Unity中全屏播放视频
  • STM32 CortexM4 主控板触摸屏保姆级别总结
  • html单标记语言有哪些,HTML(Hypertext Markup Language,超文本标记语言)是构成Web页面的主要工具,是用来表示网上信息的符号标记语言 。( )...
  • socket [WinError 10048]错误分析及解决方案
  • 虚幻引擎宣布和Quixel的合作了,作为开发者怎么获取Megascans库资源
  • 【Unreal】Unreal引擎学习-笔记二
  • [WinError 10061] 由于目标计算机积极拒绝,无法连接:requests.exceptions.ConnectionError: HTTPConnectionPool...
  • Error invoking remote method ‘fetch-data‘: FetchError: request to https://desktop.docker.com/tips.js
  • ue4屏幕空间反射关不掉问题
  • 这篇关于deno使用rust_使用graphql和deno构建ssr react应用程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



    http://www.chinasem.cn/article/210980

    相关文章

    Python使用FastAPI实现大文件分片上传与断点续传功能

    《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

    Spring Security简介、使用与最佳实践

    《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

    springboot中使用okhttp3的小结

    《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

    Vue和React受控组件的区别小结

    《Vue和React受控组件的区别小结》本文主要介绍了Vue和React受控组件的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录背景React 的实现vue3 的实现写法一:直接修改事件参数写法二:通过ref引用 DOMVu

    Java使用Javassist动态生成HelloWorld类

    《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

    使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

    《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

    Java使用jar命令配置服务器端口的完整指南

    《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

    C#使用Spire.Doc for .NET实现HTML转Word的高效方案

    《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

    Java中的抽象类与abstract 关键字使用详解

    《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

    MyBatis ParameterHandler的具体使用

    《MyBatisParameterHandler的具体使用》本文主要介绍了MyBatisParameterHandler的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、概述二、源码1 关键属性2.setParameters3.TypeHandler1.TypeHa