화제가 소란스럽다!JavaxTypeScript의 웹 프레임워크 "Hilla"에 대한 설명이 전혀 없습니다.

개시하다


https://hilla.dev/
별로 화제가 되지 않는 웹 프레임워크'힐라'[1]를 소개하고 싶다.
자바로 BFF를 만들고 싶거나 어쩔 수 없이 만들어야 하는 사람을 대상으로 하기 때문에 맞지 않는 사람이 여기에 있다exit.Hilla에는 SSR이 없기 때문에 SEO가 필요 없는 시스템이 대상이 될 것이라고 생각한다.
Hilla의 가장 큰 특징은 Type Script 고객의 코드를 통해 자동으로 생성되고 BFF(Java)와 프런트엔드(Type Script)의 유형 보안 통신을 실현하는 것이라고 생각합니다.
개요를 잡기 위해서는 처음에 아래의 기사를 읽는 것이 좋을 것 같습니다.
https://www.infoq.com/jp/news/2022/04/vaadin-introduces-hilla/

프레임 구조


프레임의 구성은 다음과 같습니다.
  • BFF
  • Spring Boot
  • Frontend
  • Lit
  • Vaadin Web UI Components
  • 상당히 완전한 구성입니다.프레임워크, 프로그램 라이브러리 구성에 대해 고민하는 경우는 드물죠.개발할 때의 구축, 발행할 때의 구축도 단숨에 고려되어 그곳에서도 고민이 드물죠.

    Spring Boot


    https://spring.io/projects/spring-boot
    Spring Boot은 Java 서버 측면의 웹 프레임워크입니다.
    너무 고전적이어서 말을 많이 안 해요.

    Lit


    https://lit.dev/
    Lit은 웹 Component를 처리하는 라이브러리입니다.
    HTML 템플릿에는 다음과 같은 Tagged Template Literals가 사용됩니다.
    const header = (title: string) => html`<h1>${title}</h1>`;
    
    React 등 JSX에 비해 유형 안전성이 없다고 생각합니다. 이 점에 대해 뒤에서 서술하고 싶습니다.

    Vaadin Web UI Components


    https://vaadin.com/components
    다양한 Vaadin UI 구성 요소를 사용할 수 있습니다.

    Quickstart


    해설을 하고 싶습니다Quickstart.최종 완성품은여기.입니다.
    우선 아래 명령으로 프로젝트를 제작한다.
    $ npx @vaadin/cli init --preset hilla-quickstart-tutorial hilla-grocery-app
    $ cd hilla-grocery-app
    

    BFF 모델 클래스


    BFF 요청 및 응답을 위한 모델 클래스src/main/java/com/example/application/GroceryItem.java를 생성합니다.
    package com.example.application;
    
    import javax.validation.constraints.Min;
    import javax.validation.constraints.NotBlank;
    import javax.validation.constraints.NotNull;
    
    public class GroceryItem {
    
        @NotBlank 
        private String name;
    
        @NotNull
        @Min(value = 1) 
        private Integer quantity;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getQuantity() {
            return quantity;
        }
    
        public void setQuantity(int quantity) {
            this.quantity = quantity;
        }
    }
    
    Java16에서 가져온 record의 사용이 검증되지 않았습니다.

    BFF Endpoint 클래스


    처리 요청에 대한 Endpoint 클래스src/main/java/com/example/application/GroceryEndpoint.java를 생성합니다.
    package com.example.application;
    
    import java.util.ArrayList;
    import java.util.List;
    import com.vaadin.flow.server.auth.AnonymousAllowed;
    import dev.hilla.Endpoint;
    import dev.hilla.Nonnull;
    
    @Endpoint 
    @AnonymousAllowed 
    public class GroceryEndpoint {
    
      private final List<GroceryItem> groceryList = new ArrayList<>();
    
      public @Nonnull List<@Nonnull GroceryItem> getGroceries() { 
        return groceryList;
      }
    
      public GroceryItem save(GroceryItem item) {
        groceryList.add(item);
        return item;
      }
    }
    
    일반적인 스프링부트 앱이라면 @Controller 사용할 것 같지만 힐라@RestController는 사용할 것 같다.@Endpoint는 데이터를 얻는 방법getGroceries으로 데이터를 등록하는 방법이다.
    다른 패키지의 같은 이름의 Endipoint 클래스를 만들 수 없습니다.다음 오류를 내보냅니다.
    Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'groceryEndpoint' for bean class [com.example.application.foo.GroceryEndpoint] conflicts with existing, non-compatible bean definition of same name and class [com.example.application.GroceryEndpoint]
    
    잘못 말해줘서 친근해요.
    이에 비해 서로 다른 포장의 동명 모델류를 만들 수 있다.Enpoint 클래스의 내부 클래스로서 모델 클래스를 제작하는 것도 문제가 되지 않습니다.

    TypeScript의 클라이언트 코드 자동 생성


    다음 명령을 사용하여 프로그램을 시작합니다.
    ./mvnw
    
    빌드를 시작하거나 게시할 때 TypeScript의 클라이언트 코드가 자동으로 생성됩니다.
    다음 코드를 생성합니다.이 코드를 사용하면 안전한 통신을 할 수 있다.
    $ tree frontend/generated/
    frontend/generated/
    ├── GroceryEndpoint.ts
    ├── com
    │   └── example
    │       └── application
    │           ├── GroceryItem.ts
    │           └── GroceryItemModel.ts
    ├── connect-client.default.ts
    ├── endpoints.ts
    ├── theme-hilla-grocery-app.generated.js
    ├── theme.d.ts
    ├── theme.js
    ├── vaadin-featureflags.ts
    ├── vaadin.ts
    └── vite-devmode.ts
    
    이 글에서 하고 싶은 말은 모두 여기에 있다.
    이 코드를 생성하는 메커니즘은 프레임워크로 매우 아름답게 제공된다.

    자동으로 생성된 코드 사용

    save가 이미 존재하며 다음 항목으로 덮어씁니다.
    import '@vaadin/button';
    import '@vaadin/text-field';
    import '@vaadin/number-field';
    import '@vaadin/grid/vaadin-grid';
    import { html } from 'lit';
    import { customElement, state } from 'lit/decorators.js';
    import { View } from 'Frontend/views/view';
    import { Binder, field } from '@hilla/form';
    import { getGroceries, save } from 'Frontend/generated/GroceryEndpoint';
    import GroceryItem from 'Frontend/generated/com/example/application/GroceryItem';
    import GroceryItemModel from 'Frontend/generated/com/example/application/GroceryItemModel';
    
    @customElement('grocery-view') 
    export class GroceryView extends View { 
    
      @state()
      private groceries: GroceryItem[] = []; 
      private binder = new Binder(this, GroceryItemModel); 
    
      render() {
        return html`
          <div class="p-m">
            <div>
              <vaadin-text-field
                ${field(this.binder.model.name)}
                label="Item"> </vaadin-text-field> 
              <vaadin-number-field
                ${field(this.binder.model.quantity)}
                has-controls
                label="Quantity"></vaadin-number-field> 
              <vaadin-button
                theme="primary"
                @click=${this.addItem}
                ?disabled=${this.binder.invalid}>Add</vaadin-button> 
            </div>
    
            <h3>Grocery List</h3>
            <vaadin-grid .items="${this.groceries}" theme="row-stripes" style="max-width: 400px">
              
              <vaadin-grid-column path="name"></vaadin-grid-column>
              <vaadin-grid-column path="quantity"></vaadin-grid-column>
            </vaadin-grid>
          </div>
        `;
      }
    
      async addItem() {
        const groceryItem = await this.binder.submitTo(save); 
        if (groceryItem) { 
          this.groceries = [...this.groceries, groceryItem];
          this.binder.clear();
        }
      }
    
      async firstUpdated() { 
        const groceries = await getGroceries();
        this.groceries = groceries;
      }
    }
    
    이렇게 Quickstart 응용 프로그램이 완성되었습니다.

    Lit의 HTML 템플릿에 대한 정적 해석 정보


    VS 코드로 개발할 때 프로젝트lit-plugin는 처음부터 편입되어 템플릿 부분의 정적 해석을 진행했다.그러나 발행 구축 시 처리는 이 정적 분석을 포함하지 않습니다.CLI 의 lit-analyzer 를 실행하려면 다음 절차를 따르십시오.
    다음 명령을 사용하여 lit-analyzer를 설치합니다.
    npm install lit-analyzer -D
    
    package.json에 다음과 같은 내용을 추가합니다.
      "scripts": {
        "lint:lit-analyzer": "lit-analyzer frontend/views --strict"
      },
    
    다음 명령을 통해 수행할 수 있습니다.
    npm run lint:lit-analyzer
    
    이 명령의 실행을 발표할 때의 구축에 통합합니다.

    Gradle Plugin


    현재(2022-05-01) 마벤트용pluggin만 제공되고,Gradle용pluggin은 없습니다.Watch 아래 Issue의 상황입니다.
    https://github.com/vaadin/hilla/issues/141

    끝맺다


    이전에 나는 아래의 보도를 썼다.
    https://qiita.com/chibato/items/e4a748db12409b40c02f
    Springfox[2]OpenAPI Generator를 결합하여 TypeScript 코드를 생성합니다.
    Hilla는 이 코드가 생성한 구조를 프레임워크로 매우 아름답게 제공하고 있다(2차).
    나는 이것이 매우 좋은 틀의 작업이라고 생각한다. 반드시 사용해 주십시오.[3]

    잡담

  • 발표된 구축된jar에도 swagger-codegen이 포함되어 있어 정식으로 실행할 때 필요하지 않다고 생각합니다.
  • 스웨거-codegen이 아니라 오픈 앱-generator 안 돼요?
  • springfox,springdoc-openapi를 사용하여 내부 OPEN API의 Spec 정보를 생성하지 않았습니다.JavaParser.
  • 개발 시 시작 시 전단과 BFF는 단독 서버가 상승하지 않으며 Request forward와 유사한 일이 발생하지 않습니다.
  • 그게 다야.
    각주
    원래 힐라는 고대부터'Vaadin Fusion'이라는 이름으로 개발된 Vaadin 프레임워크의 하위 프로젝트였다.2022년에 이름이 바뀌었다.↩︎
    지금쯤이면 쓰겠죠springdoc-openapi.↩︎
    그런 나는 실제 사건에서도 사용하지 않았다.↩︎

    좋은 웹페이지 즐겨찾기