Quarkus for the Web

Quarkus 提供了几个扩展来创建 Web 应用程序,本文旨在为在不同用例中使用哪个扩展提供指导。

Quarkus provides several extensions to create web applications, this document aims to provide directions on which extension to use for different use cases.

The basics

Serving static resources

假设您有一个 Quarkus 后端,并且您希望提供静态文件。这是最基本的情况,它在所有基于 Vert.x 的扩展中都得到开箱即用的支持,您必须将它们放置在应用程序的 META-INF/resources 目录中。

Let’s assume you have a Quarkus backend, and you want to serve static files. This is the most basic case, it is supported out of the box with all our Vert.x based extensions, you must place them in the META-INF/resources directory of your application.

您可以在 HTTP reference guide 中找到更多信息。

You can find more information in the HTTP reference guide.

Serving scripts, styles, and web libraries

但是,如果您想在您的网页中插入脚本、样式和库,您有 3 个选择:

However, if you want to insert scripts, styles, and libraries in your web pages, you have 3 options:

  1. Consume libraries from public CDNs such as cdnjs, unpkg, jsDelivr and more, or copy them to your META-INF/resources directory.

  2. Use runtime web dependencies such as mvnpm or WebJars, when added to your pom.xml or build.gradle they can be directly accessed from your web pages.

  3. Package your scripts (js, ts), styles (css, scss), and web dependencies together using a bundler (see bundling).

We recommend using a bundler for production 因为它提供了更好的控制、一致性、安全性和性能。好消息是,Quarkus 使用 Quarkus Web Bundler extension 使其变得非常容易和快速。

We recommend using a bundler for production as it offers better control, consistency, security, and performance. The good news is that Quarkus makes it really easy and fast with the Quarkus Web Bundler extension.

Bundling scripts, styles, and libraries

有两种捆绑 Web 资产的方法:

There are two ways to bundle your web assets:

  1. Using the Quarkus Web Bundler extension, which is the recommended way. Without any configuration, it puts everything together in an instant, and follows good practices such as dead-code elimination, minification, caching, and more.

  2. Using a custom bundler such as Webpack, Parcel, Rollup, etc. This can be easily integrated with Quarkus using the Quarkus Quinoa extension.

web bundle transition

Server-side rendering (SSR)

对于使用 Quarkus 的模板和服务器端渲染,有不同的引擎可用,例如 QuteFreemarker等。

For templating and server-side rendering with Quarkus, there are different engines available such as Qute or Freemarker and others.

Qute Web

Qute 专门设计来满足 Quarkus 需求,并帮助你处理模板、代码段和部分,以及渲染存储中的数据。它受到最著名的模板引擎的启发,它快速、类型安全、在本地工作,并具有许多不错的功能。

Qute is designed specifically to meet the Quarkus needs, and help you deal with templates, snippets, and partials and render the data from your storage. It is inspired by the most famous template engines, it is fast, type-safe, works in native, and has a lot of nice features.

要安装 Qute Web,请按照 the instructions进行操作。

To install Qute Web, follow the instructions.

以下是一个简单的 Qute 模板示例:

Here is a simple example of a Qute template:

src/main/resources/templates/pub/index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Qute Page</title>
    {#bundle /} 1
</head>
<body>
    <h1>Hello {http:param('name', 'Quarkus')}</h1> 2
    <ul>
    {#for item in cdi:Product.items} 3
       <li>{item.name} {#if item.active}{item.price}{/if}</li> 4
    {/for}
    </ul>
</body>
</html>
1 With the Web Bundler extension, this expression will be replaced by the bundled scripts and styles.
2 You can directly use the HTTP parameters in your templates.
3 This expression is validated. Try to change the expression to cdi:Product.notHere and the build will fail.
4 If you install Quarkus IDEs plugins, you will have autocompletion, link to implementation and validation.

Model-View-Controller (MVC)

得益于 the Renarde extension,使用类似 Rails 的 Qute 框架,MVC 方法在 Quarkus 中也非常容易使用。

The MVC approach is also made very easy with Quarkus thanks to the Renarde extension, a Rails-like framework using Qute.

Web Bundler extension相关联,为满足你所有需求的构建现代 Web 应用程序打开了一条道路。以下是一个简单的 Renarde 控制器的外观:

Associated with the Web Bundler extension, the road is open to build modern web applications for all your needs. Here is what a simple Renarde controller looks like:

src/main/java/rest/Todos.java
package rest;

[...]

public class Todos extends Controller {

    @CheckedTemplate
    static class Templates {
        public static native TemplateInstance index(List<Todo> todos);
    }

    public TemplateInstance index() {
        // list every todo
        List<Todo> todos = Todo.listAll();
        // render the index template
        return Templates.index(todos);
    }

    @POST
    public void add(@NotBlank @RestForm String task) {
        // check if there are validation issues
        if(validationFailed()) {
            // go back to the index page
            index();
        }
        // create a new Todo
        Todo todo = new Todo();
        todo.task = task;
        todo.persist();
        // send loving message
        flash("message", "Task added");
        // redirect to index page
        index();
    }

    @POST
    public void delete(@RestPath Long id) {
        // find the Todo
        Todo todo = Todo.findById(id);
        notFoundIfNull(todo);
        // delete it
        todo.delete();
        // send loving message
        flash("message", "Task deleted");
        // redirect to index page
        index();
    }

    @POST
    public void done(@RestPath Long id) {
        // find the Todo
        Todo todo = Todo.findById(id);
        notFoundIfNull(todo);
        // switch its done state
        todo.done = !todo.done;
        if(todo.done)
            todo.doneDate = new Date();
        // send loving message
        flash("message", "Task updated");
        // redirect to index page
        index();
    }
}

Single Page Applications

Quarkus 提供了非常可靠的工具,用于为 Quarkus(React、Angular、Vue、…)创建或集成单页应用程序,这里有 3 个选项:

Quarkus provides very solid tools for creating or integrating Single Page Applications to Quarkus (React, Angular, Vue, …), here are 3 options:

  • Quarkus Quinoa bridges your npm-compatible web application and Quarkus for both dev and prod. No need to install Node.js or configure your framework, it will detect it and use sensible defaults.

  • The Quarkus Web Bundler is also a good approach, it is closer to the Java ecosystem and removes a lot of boilerplate and configuration, it is fast and efficient. For examples of such SPAs, see code.quarkus.io and mvnpm.org.

  • Your automation using the maven-frontend-plugin or similar tools.

Full-stack microservices (Micro-frontends)

Quarkus 是全栈 Web 组件和全栈微服务(又称微型前端)的绝佳选择。通过使用 Web Bundler 或 Quinoa,你可以在很大程度上减少样板代码,并有效管理多个服务,而无需太多重复配置。

Quarkus is an excellent choice for both full-stack web components and full-stack microservices aka Micro-frontends. By utilizing the Web Bundler or Quinoa, you can significantly reduce boilerplate code and manage multiple services efficiently without much configuration duplication.

例如, quarkus.io上的 Quarkus documentation search engine使用 Web Bundler 创建全栈 Web 组件。利用 Lit Element 处理 Web 组件和 OpenSearch 处理索引,这是一种以动态方式增强静态网站体验的好方法。

For example the Quarkus documentation search engine on quarkus.io uses the Web Bundler to create a full-stack web-component. With Lit Element for the web-component and OpenSearch for the indexation it is a nice way to enhance the static web-site experience in a dynamic way.

更多关于此内容即将推出…

More content about this is coming soon…​

Other ways

我们已经描述了 Quarkus 最常见的创建 Web 应用程序的方法,但还有其他选择:

We described Quarkus most common ways to create web applications but there are other options:

  • Vaadin Flow extension, for this unique framework that lets you build web apps directly from Java code without writing HTML or JavaScript.

  • JavaServer Faces (jsf) is a specification for building component-based web apps in Java. It available in Quarkus, the MyFaces extension is an implementation of Faces for Quarkus. PrimeFaces is a Faces components suite, and OmniFaces, a utility library. More information is available in this blog post.

  • Create a new extension for your favorite web framework.

Testing your web applications

对于测试 Web 应用程序来说, Quarkus Playwright非常易于使用。你可以创建有效的跨浏览器端到端测试,模仿用户交互并确保你的 Web 应用程序作为一个整体正常工作。最大的优势在于,它可以从所有 dev-service 和 Quarkus mocking 特性中受益。

For testing web applications, Quarkus Playwright is very easy to use. You can create effective cross-browser end-to-end tests mimicking user interaction and making sure your web application is working as a whole. The big advantage is that it benefits from all dev-services and Quarkus mocking features.

@QuarkusTest
@WithPlaywright
public class WebApplicationTest {

    @InjectPlaywright
    BrowserContext context;

    @TestHTTPResource("/")
    URL index;

    @Test
    public void testIndex() {
        final Page page = context.newPage();
        Response response = page.navigate(index.toString());
        Assertions.assertEquals("OK", response.statusText());

        page.waitForLoadState();

        String title = page.title();
        Assertions.assertEquals("My Awesome App", title);

        // Make sure the web app is loaded and hits the backend
        final ElementHandle quinoaEl = page.waitForSelector(".toast-body.received");
        String greeting = quinoaEl.innerText();
        Assertions.assertEquals("Hello from REST", greeting);
    }
}

Q&A

Why is Quarkus a very good option for Web Applications compared to other frameworks?

Quarkus 以其后端扩展生态系统和开发者体验而闻名,如果你将其与适用于前端的优秀扩展功能相结合,那将是完美的组合!现在,所有测试和开发模式特性都可以用于前端和后端。

Quarkus is well known for its backend extensions ecosystem and developer experience, if you combine it with great extensions for frontend, then it is a perfect mix! All the testing and dev-mode features are now available for both frontend and backend.

What are the advantages of SSR (Server Side Rendering) over SPA (Single Page App)?

以下是在服务器上执行渲染工作的优势:

Here are the benefits of performing rendering work on the server:

*Data Retrieval:*从服务器上抓取数据,靠近数据源。这可以通过减少检索渲染数据所需的时间和最小化客户端请求来提高性能。

Data Retrieval: Fetching data on the server, closer to the data source. This enhances performance by reducing the time needed to retrieve data for rendering and minimizes client requests.

*Enhanced Security:*敏感数据和逻辑的存储发生在服务器上,例如令牌和 API 密钥,不将它们暴露给客户端风险。

Enhanced Security: Storage of sensitive data and logic is happening on the server, such as tokens and API keys, without exposing them to client-side risks.

*Caching Efficiency:*服务器端渲染支持结果缓存,可以在用户和后续请求之间重复使用。这可以通过减少每次请求的渲染和数据抓取来优化性能并降低成本。

Caching Efficiency: Server-side rendering allows for result caching, which can be reused across users and subsequent requests. This optimizes performance and lowers costs by reducing rendering and data fetching per request.

*Improved Initial Page Load and First Contentful Paint (FCP):*在服务器上生成 HTML 使得用户可以立即查看页面,无需等待客户端 JavaScript 下载、解析和执行才能进行渲染。

Improved Initial Page Load and First Contentful Paint (FCP): Generating HTML on the server enables users to view the page immediately, eliminating the need to wait for client-side JavaScript to download, parse, and execute for rendering.

*Search Engine Optimization (SEO) and Social Media Shareability:*经过渲染的 HTML 有助于搜索引擎索引和社交网络预览,从而提高可发现性和可共享性。

Search Engine Optimization (SEO) and Social Media Shareability: The rendered HTML aids search engine indexing and social network previews, enhancing discoverability and shareability.

I am hesitating between Quinoa and the Web Bundler, how should I make my decision?

你必须认为,使用这两个解决方案,捆绑输出的内容基本相同。另外,从一个解决方案切换到另一个解决方案并不是什么大问题,选择取决于开发人员体验以及找到最适合你的团队的解决方案。

You have to think that the bundled output is essentially the same with both solutions. Also, switching from one to the other is not a big deal, the choice is about the developer experience and finding the best fit for your team.

一些指南:

Some guidelines:

Go for Quinoa:

  • You have an existing frontend configured with a npm-compatible build tool, Quinoa is the most direct option.

  • You have a dedicated frontend team familiar with tools such as NPM, Yarn and other for building Single Page Apps.

  • You want to write Javascript unit tests (such as Jest, Jasmine, ..), it is not possible with the Web Bundler. However, you could publish a components library on NPM and consume it from the Web Bundler.

  • You use very specific bundling options or specific tools in your build process

  • You love package.json and configurations tweaking

Go for Web Bundler:

  • For simple web applications, the Web Bundler is the easiest and fastest way to get started

  • You prefer to stay close to the Maven/Gradle ecosystem (Node.js is not needed), it uses an extremely fast bundler for the web (esbuild)

  • You want to reduce boilerplate and configuration

How do I scale a Quarkus Web Application?

从现有的 Quarkus 后端提供几个静态页面和脚本并不是什么大开销,因此按照通常最简单的选项来扩展整个应用程序非常简单。您也可以将其分成两项服务:一项用于后端,一项用于前端。但是,在大多数情况下,与此种最初方法相比,此种方法不会产生实质性好处。

Serving a few static pages and scripts from an existing Quarkus backend is not a big overhead, so scaling the full app is usually the simplest option. You could also split it in two services: one for the backend and one for the frontend. However, in most cases, this approach wouldn’t yield substantial benefits compared to the initial method.

如果您的应用程序涉及大量静态资源,请考虑使用 CDN。Web Bundler 和 Quinoa 都可以配置为与 CDN 无缝配合工作,从而提高性能并改进资产分配。

If your application involves a substantial number of static resources, consider using a CDN. Both the Web Bundler and Quinoa can be configured to work seamlessly with a CDN, providing improved performance and distribution of assets.