Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >微服务(十)——GateWay新一代网关

微服务(十)——GateWay新一代网关

作者头像
不愿意做鱼的小鲸鱼
发布于 2022-09-26 10:28:26
发布于 2022-09-26 10:28:26
69300
代码可运行
举报
文章被收录于专栏:web全栈web全栈
运行总次数:0
代码可运行

GateWay和Zuul说明

Zuul开发人员窝里斗,实属明日黄花

重点关注GateWay

GateWay是什么

上一代zuul 1.x官网

Gateway官网

概述

Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;

但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关替代Zuul,那就是SpringCloud Gateway—句话:gateway是原zuul1.x版的替代

Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和Project Reactor等技术。

Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等。

SpringCloud Gateway是Spring Cloud的一个全新项目,基于Spring 5.0+Spring Boot 2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供—种简单有效的统一的API路由管理方式。

SpringCloud Gateway作为Spring Cloud 生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty

Spring Cloud Gateway的目标提供统一的路由方式且基于 Filter链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

作用

  • 方向代理
  • 鉴权
  • 流量控制
  • 熔断
  • 日志监控

微服务架构中网关的位置

GateWay非阻塞异步模型

有Zuull了怎么又出来Gateway?我们为什么选择Gateway?

  1. netflix不太靠谱,zuul2.0一直跳票,迟迟不发布。
    1. 一方面因为Zuul1.0已经进入了维护阶段,而且Gateway是SpringCloud团队研发的,是亲儿子产品,值得信赖。而且很多功能Zuul都没有用起来也非常的简单便捷。
    2. Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。虽然Netflix早就发布了最新的Zuul 2.x,但Spring Cloud貌似没有整合计划。而且Netflix相关组件都宣布进入维护期;不知前景如何?
    3. 多方面综合考虑Gateway是很理想的网关选择。
  2. SpringCloud Gateway具有如下特性
    1. 基于Spring Framework 5,Project Reactor和Spring Boot 2.0进行构建;
    2. 动态路由:能够匹配任何请求属性;
    3. 可以对路由指定Predicate (断言)和Filter(过滤器);
    4. 集成Hystrix的断路器功能;
    5. 集成Spring Cloud 服务发现功能;
    6. 易于编写的Predicate (断言)和Filter (过滤器);
    7. 请求限流功能;
    8. 支持路径重写。
  3. SpringCloud Gateway与Zuul的区别
    1. 在SpringCloud Finchley正式版之前,Spring Cloud推荐的网关是Netflix提供的Zuul。
    2. Zuul 1.x,是一个基于阻塞I/O的API Gateway。
    3. Zuul 1.x基于Servlet 2.5使用阻塞架构它不支持任何长连接(如WebSocket)Zuul的设计模式和Nginx较像,每次I/О操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx用C++实现,Zuul用Java实现,而JVM本身会有第-次加载较慢的情况,使得Zuul的性能相对较差。
    4. Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。Zuul .x的性能较Zuul 1.x有较大提升。在性能方面,根据官方提供的基准测试,Spring Cloud Gateway的RPS(每秒请求数)是Zuul的1.6倍。
    5. Spring Cloud Gateway建立在Spring Framework 5、Project Reactor和Spring Boot2之上,使用非阻塞API
    6. Spring Cloud Gateway还支持WebSocket,并且与Spring紧密集成拥有更好的开发体验

Zuul1.x模型

Springcloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是传统的Serviet IO处理模型。

Servlet的生命周期?servlet由servlet container进行生命周期管理。

  • container启动时构造servlet对象并调用servlet init()进行初始化;
  • container运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service);
  • container关闭时调用servlet destory()销毁servlet。

上述模式的缺点

Servlet是一个简单的网络IO模型,当请求进入Servlet container时,Servlet container就会为其绑定一个线程,在并发不高的场景下这种模型是适用的。但是一旦高并发(如抽风用Jmeter压),线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。在一些简单业务场景下,不希望为每个request分配一个线程,只需要1个或几个线程就能应对极大并发的请求,这种业务场景下servlet模型没有优势。

所以Zuul 1.X是基于servlet之上的一个阻塞式处理模型,即Spring实现了处理所有request请求的一个servlet (DispatcherServlet)并由该servlet阻塞式处理处理。所以SpringCloud Zuul无法摆脱servlet模型的弊端。

Gateway模型

WebFlux是什么?官方文档

传统的Web框架,比如说: Struts2,SpringMVC等都是基于Servlet APl与Servlet容器基础之上运行的。

但是在Servlet3.1之后有了异步非阻塞的支持。而WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上。非阻塞式+函数式编程(Spring 5必须让你使用Java 8)。

Spring WebFlux是Spring 5.0 引入的新的响应式框架,区别于Spring MVC,它不需要依赖Servlet APl,它是完全异步非阻塞的,并且基于Reactor来实现响应式流规范。

Spring Cloud Gateway requires the Netty runtime provided by Spring Boot and Spring Webflux. It does not work in a traditional Servlet Container or when built as a WAR.link

Gateway工作流程

三大核心概念

  1. Route(路由) - 路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如断言为true则匹配该路由;
  2. Predicate(断言) - 参考的是Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由;
  3. Filter(过滤) - 指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。

predicate就是我们的匹配条件;而fliter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了

Gateway工作流程

官网总结

Clients make requests to Spring Cloud Gateway. If the Gateway Handler Mapping determines that a request matches a route, it is sent to the Gateway Web Handler. This handler runs the request through a filter chain that is specific to the request. The reason the filters are divided by the dotted line is that filters can run logic both before and after the proxy request is sent. All “pre” filter logic is executed. Then the proxy request is made. After the proxy request is made, the “post” filter logic is run. link

客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到GatewayWeb Handler。

Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。

过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post")执行业务逻辑。

Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

核心逻辑:路由转发 + 执行过滤器链。

Gateway9527搭建

1.新建Module - cloud-gateway-gateway9527

2.POM

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>cn.kt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-gateway-gateway9527</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包 -->
        <dependency>
            <groupId>cn.kt</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--一般基础配置类-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

3.YML

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
server:
  port: 9527

spring:
  application:
    name: cloud-gateway

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

4.业务类

5.主启动类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package cn.kt.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * Created by tao.
 * Date: 2022/8/1 23:47
 * 描述:
 */

@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
    public static void main(String[] args) {
        SpringApplication.run(GateWayMain9527.class, args);
    }
}

6.9527网关如何做路由映射?

cloud-provider-payment8001看看controller的访问地址

  • get
  • lb

我们目前不想暴露8001端口,希望在8001外面套一层9527

7.YML新增网关配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
#############################新增网关配置###########################
  cloud:
    gateway:
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          #uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          #uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
####################################################################

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

8.测试

Gateway配置路由的两种方式

在配置文件yml中配置,见上一章节

代码中注入RouteLocator的Bean

官方案例 - link

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
    .maxTrustedIndex(1);

...

.route("direct-route",
    r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")
        .uri("https://downstream1")
.route("proxied-route",
    r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")
        .uri("https://downstream2")
)

百度国内新闻网址,需要外网 - http://news.baidu.com/guonei

自己写一个

业务需求 - 通过9527网关访问到外网的百度新闻网址

编码

cloud-gateway-gateway9527业务实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package cn.kt.springcloud.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by tao.
 * Date: 2022/8/2 00:08
 * 描述:
 */

@Configuration
public class GateWayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        routes.route("path_route_atguigu",
                r -> r.path("/guonei")
                        .uri("http://news.baidu.com/guonei")).build();

        return routes.build();
    }
}

测试

浏览器输入http://localhost:9527/guonei,返回http://news.baidu.com/guonei相同的页面。

GateWay配置动态路由

默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能(不写死一个地址)。

启动

  • eureka7001
  • payment8001/8002

POM

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!--eureka-client-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

YML

需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能。

lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
#############################新增网关配置###########################
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
####################################################################

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

测试

浏览器输入 - http://localhost:9527/payment/lb

结果

不停刷新页面,8001/8002两个端口切换。

GateWay常用的Predicate

官方文档

Route Predicate Factories这个是什么

Spring Cloud Gateway matches routes as part of the Spring WebFlux HandlerMapping infrastructure. Spring Cloud Gateway includes many built-in route predicate factories. All of these predicates match on different attributes of the HTTP request. You can combine multiple route predicate factories with logical and statements. link

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。

Spring Cloud Gateway包括许多内置的Route Predicate工厂。所有这些Predicate都与HTTP请求的不同属性匹配。多个RoutePredicate工厂可以进行组合。

Spring Cloud Gateway创建Route 对象时,使用RoutePredicateFactory 创建 Predicate对象,Predicate 对象可以赋值给Route。Spring Cloud Gateway包含许多内置的Route Predicate Factories。 所有这些谓词都匹配HTTP请求的不同属性。多种谓词工厂可以组合,并通过逻辑and。

predicate 美: ['predɪkeɪt] 英: ['predɪkət] v. 断言;使基于;使以…为依据;表明 adj. 述语的;谓项的 n. 谓语(句子成分,对主语加以陈述,如 John went home 中的 went home)

常用的Route Predicate Factory

  1. The After Route Predicate Factory
  2. The Before Route Predicate Factory
  3. The Between Route Predicate Factory
  4. The Cookie Route Predicate Factory
  5. The Header Route Predicate Factory
  6. The Host Route Predicate Factory
  7. The Method Route Predicate Factory
  8. The Path Route Predicate Factory
  9. The Query Route Predicate Factory
  10. The RemoteAddr Route Predicate Factory
  11. The weight Route Predicate Factory

讨论几个Route Predicate Factory

The After Route Predicate Factory

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        # 这个时间后才能起效
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

可以通过下述方法获得上述格式的时间戳字符串

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package cn.kt.springcloud;

import java.time.ZonedDateTime;

/**
 * Created by tao.
 * Date: 2022/8/2 00:42
 * 描述:
 */
public class T1 {
    public static void main(String[] args) {
        ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
        System.out.println(zbj);

        //2022-08-02T00:42:44.120+08:00[Asia/Shanghai]
    }
}

The Between Route Predicate Factory

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring:
  cloud:
    gateway:
      routes:
      - id: between_route
        uri: https://example.org
        # 两个时间点之间
        predicates:
        - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

The Cookie Route Predicate Factory

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=username,kt

The cookie route predicate factory takes two parameters, the cookie name and a regular expression.

This predicate matches cookies that have the given name and whose values match the regular expression.

测试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 该命令相当于发get请求,且没带cookie
curl http://localhost:9527/payment/lb

# 带cookie的
curl http://localhost:9527/payment/lb --cookie "username=kt"

The Header Route Predicate Factory

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+

The header route predicate factory takes two parameters, the header name and a regular expression.

This predicate matches with a header that has the given name whose value matches the regular expression.

测试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 带指定请求头的参数的CURL命令
curl http://localhost:9527/payment/lb -H "X-Request-Id:123"

其它的,举一反三。

小结

说白了,Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。

GateWay的Filter

官方文档

Route filters allow the modification of the incoming HTTP request or outgoing HTTP response in some manner. Route filters are scoped to a particular route. Spring Cloud Gateway includes many built-in GatewayFilter Factories.

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Spring Cloud Gateway内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生。

Spring Cloud Gateway的Filter:

  • 生命周期:
    • pre
    • post
  • 种类(具体看官方文档):
    • GatewayFilter - 有31种
    • GlobalFilter - 有10种

常用的GatewayFilter:AddRequestParameter GatewayFilter

自定义全局GlobalFilter:

两个主要接口介绍:

  1. GlobalFilter
  2. Ordered

能干什么:

  1. 全局日志记录
  2. 统一网关鉴权

代码案例:

GateWay9527项目添加MyLogGateWayFilter类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package cn.kt.springcloud.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Date;

/**
 * Created by tao.
 * Date: 2022/8/2 00:54
 * 描述:
 */

@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("***********come in MyLogGateWayFilter:  " + new Date());

        String uname = exchange.getRequest().getQueryParams().getFirst("uname");

        if (uname == null) {
            log.info("*******用户名为null,非法用户,o(╥﹏╥)o");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

测试:

启动:

  • EurekaMain7001
  • PaymentMain8001
  • GateWayMain9527
  • PaymentMain8002

浏览器输入:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
react 学习:React属性 数组遍历、css引入
一:index.js 里直接引入css。 import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; // import Welcome from './Welcome'; import * as serviceWorker from './serviceWorker'; import 'bootstrap/dist/css/bootstrap.
爱明依
2019/04/22
1.1K0
react 学习:React属性 数组遍历、css引入
[Next] 初见next.js
  Next.js 可与 Windows,Mac 和 Linux 一起使用.您只需要在系统上安装 Node.js 即可开始构建 Next.js 应用程序.如果有个编辑器就更好了
不会飞的小鸟
2019/10/01
5.3K0
[Next] 初见next.js
Next.js入门教程 原
参考代码:https://github.com/chkui/nextjs-getting-started 。
随风溜达的向日葵
2018/12/07
6K0
react新手教程
github仓库 https://github.com/Rynxiao/react-newer JSX语法 const element = <h1>Hello, world!</h1>; This funny tag syntax is neither a string nor HTML. It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to describe w
糊糊糊糊糊了
2018/05/09
2.1K0
Next.js 入门
当使用 React 开发系统的时候,常常需要配置很多繁琐的参数,如 Webpack 配置、Router 配置和服务器配置等。如果需要做 SEO,要考虑的事情就更多了,怎么让服务端渲染和客户端渲染保持一致是一件很麻烦的事情,需要引入很多第三方库。针对这些问题,Next.js提供了一个很好的解决方案,使开发人员可以将精力放在业务上,从繁琐的配置中解放出来。下面我们一起来看看它的一些特性。
Dickensl
2022/06/14
6.7K0
Next.js 入门
js汇率计算器系统
css逻辑: 第一步:先清除掉系统默认的元素的padding与margin值. 第二步;定义css变量
贵哥的编程之路
2020/10/28
5.8K0
js汇率计算器系统
【尚筹网】四、管理员登录
用户11332765
2024/11/26
930
【尚筹网】四、管理员登录
分享 7 个你可能不知道的 Next.js 14 小技巧
今天,我将向大家介绍一些关于NextJS的概念,这些可能是许多开发者所不知道的。你可以利用这些概念来优化你的应用,并改善开发者体验。
前端达人
2024/02/01
9470
分享 7 个你可能不知道的 Next.js 14 小技巧
万字长文助你搞懂现代网页开发中常见的10种渲染模式
近年来,网络开发的迅速演变,尤其是在前端开发领域。这种转变主要归功于无数涌现的框架和技术,它们旨在简化和增强构建引人入胜的用户界面的过程。然而,由于现有框架的丰富多样以及不断涌现的新框架,跟上前端趋势已成为一项艰巨的任务。对于新手来说,很容易感到不知所措,仿佛迷失在广阔的选择海洋中。
前端达人
2023/10/25
5310
万字长文助你搞懂现代网页开发中常见的10种渲染模式
Next.js的创建与使用
NextJs是React的服务器渲染框架,区别于官方SSRNext最大的特点是可以渲染出Ajax异步请求渲染出来的结果,本网站目前使用的前端框架就是NextJs
用户6256742
2022/07/06
4.2K0
Next.js的创建与使用
动手练一练,使用 React 和 Next.js 做一个简单的博客网站(中)
大家好,在《动手练一练,使用 React 和 Next.js 做一个简单的博客网站(上)》一篇文章里,我们一起了解了什么是 Next.js,并手工创建了一个简单的 Next.js 项目,学会了如何基于模板创建简单的页面,本篇文章,我们继续完善这个案例。
前端达人
2021/04/11
1.8K0
动手练一练,使用 React 和 Next.js 做一个简单的博客网站(中)
构建通用的 React 和 Node 应用
原文:Build a universal React and Node App 演示:https://judo-heroes.herokuapp.com/ 译者:nzbin 译者的话:这是一篇非常优秀的 React 教程,该文对 React 组件、React Router 以及 Node 做了很好的梳理。我是 9 月份读的该文章,当时跟着教程做了一遍,收获很大。但是由于时间原因,直到现在才与大家分享,幸好赶在年底之前完成了译文,否则一定会成为 2016 年的小遗憾。翻译仓促,其中还有个别不通顺的地方,望见谅
叙帝利
2018/01/17
9K0
构建通用的 React 和 Node 应用
React学习笔记(二)—— JSX、组件与生命周期
JSX = JavaScript XML,这是React官方发明的一种JS语法(糖)
张果
2023/03/01
6.1K0
React学习笔记(二)—— JSX、组件与生命周期
Vue3 Typescript + Axios 全栈开发教程:手把手教你写「待办清单」APP
本文完整版:《Vue3 Typescript + Axios 全栈开发教程:手把手教你写「待办清单」APP》
蒋川@卡拉云
2022/05/30
1.7K0
Vue3 Typescript + Axios 全栈开发教程:手把手教你写「待办清单」APP
SSR服务器端渲染(Next.js总结和豆瓣电影项目)「建议收藏」
先解释一下Nuxt.js和Next.js虽然只有一个字母之差,但它们是不同的两个服务端渲染框架.
全栈程序员站长
2022/11/15
2.3K0
bootstrap教程,SQL
DDL数据定义语言 TPL事务处理语言 DCL数据控制语言 DML数据操作语言
达达前端
2019/07/03
9630
bootstrap教程,SQL
react进阶用法完全指南
React调用回调函数,正确设置this指向的三种方法 通过bind this.increment = this.increment.bind(this); 通过箭头函数 <button onClick={this.multi}>点我*10</button> multi = () => { this.setState({ count: this.state.count * 10 }) } 箭头函数包裹 <button onClick={() => {this.muti2(
xiaofeng123aa
2022/09/26
6.1K0
React 路由详解(超详细详解)
使用 Link 是会有一些问题的, 他不会显示按钮的高亮显示, 所以我使用 NavLink 来替代它
全栈程序员站长
2022/08/10
6K0
React 路由详解(超详细详解)
forex-python,一个强大的 Python 库!
大家好,今天为大家分享一个强大的 Python 库 - forex-python。
sergiojune
2024/05/30
5851
forex-python,一个强大的 Python 库!
react hook+ts+rouerV6 dev notes
 组件“/machine”为已经定义好的路由,state负责传值state:{参数:值}
biaoblog.cn 个人博客
2022/08/11
2.5K0
react hook+ts+rouerV6 dev notes
推荐阅读
相关推荐
react 学习:React属性 数组遍历、css引入
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验