Configuration

Role definitions:

  1. proto defines standards
  2. app defines application
  3. ui defines interaction

All sources originate from the protocol generated by proto, which then generates the application foundation, and the application links to ui. The general process is:

  1. Compile proto to generate protocol
  2. Generate application through protocol stub
  3. Choose whether to generate UI during application generation

UI generation rules need to be configured for the app, and the app triggers UI generation.

Open the vue generation flag in {app}/build.gradle:

hopeStub {
    enableFrontVue = true
}

{app}/ui.json:

{
  "projectDir": "../good-app-ui"
}

Last Update: 1.3.9-M2 (2025-05-27 Frontend architecture is changing rapidly, some variables are also changing, use with caution) auto router has been moved into the built-in plugin, no longer through app, router is now purely frontend work!

PropertyComment
uiModuleDirUI module relative path
httpVendor../http, provides useGet/Post
apiDirpackages/service/src, API output directory(relative to uiModuleDir)
requestTypeRequestItem form type
requestModule../types form type reference path
responseTypeResponseItem column type
responseModule../types column type reference path
pathToUrlimport { pathToUrl } from '../utils' path parsing helper function
langDirpackages/common/locales/src/langs internationalization output path(relative to uiModuleDir)
firstLanguagezh-CN internationalization, first language
secondLanguageen-US internationalization, second language
typesDirsrc/types type output path(relative to uiModuleDir)
authSplitAuthorization separator, used for assembling tree structure, default :
noMergerfalse reserved, unused
alwaysEraseOldfalse reserved, unused

Router

The project has a built-in plugin that automatically scans pages and generates routing rules according to the file directory structure.

router.json configuration is located under the {module}-ui module, used to configure the automatic route generation rules for applications under the ui module.

Multiple modules are supported. For example, under apps there are web1, web2, each can be configured independently and isolated from each other.

{
  "items": [
      {
          "moduleDir": "apps/web1"
      },{
          "moduleDir": "apps/web2"
      }
  ]
}
PropertyComment
moduleDirSubmodule directory under ui module, such as apps/web
pagesDirsrc/pages page directory relative path for this module
pagesPath@/pages page module path
routerOutDirsrc/router/auto automatic route output directory
menuItemMenuItem menu class name
menuItemImport./types menu class import path
disablefalse whether to disable
firstLanguageFirst language
secondLanguageSecond language
langDirsrc/locales/langs language output directory

Compilation

Simply execute the stub command to generate UI content:

./gradlew.bat {app}:clean stub build -x test -x stubTest

  1. i18n
  2. Api Stub
  3. Api Model
  4. form/table Stub
  5. type
  6. other
├─assets
│....
├─locales
│  │  
│  └─langs
│      ├─en-US
│      │      app.json
│      │
│      └─zh-CN
│              app.json
├─service
│  │  http.ts
│  │  index.ts
│  │  type.ts
│  │  utils.ts
│  │
│  ├─api
│  │      api-example-api.ts
│  │      api-system-system.ts
│  │      index.ts
│  │
│  ├─form
│  │      TemplateExampleRequest.ts
│  │      UploadBookCoverToLocalRequest.ts
│  │
│  ├─model
│  │      api-example-request-example.ts
│  │      api-example-response-example.ts
│  │      index.ts
│  │      _common.ts
│  │      _error.ts
│  │
│  └─table
│          TemplateExampleResponse.ts
├─types
│      api.d.ts
│      app.d.ts
│      auth.d.ts

Runtime

Since modern frameworks all use SPA(Single Page Application) architecture, which brings challenges to frontend-backend collaboration, ApiHug attempts to reduce the complexity of understanding and synchronization delays in multi-person frontend-backend collaboration. Therefore, it adopts:

  1. Frontend and backend projects in different submodules within the same project
  2. Tool chain integration, gradle + vite, seamless integration, tasks can call each other
  3. Runtime, java application static proxy + vue proxy

This achieves maximum collaboration between frontend and backend personnel with minimal context switching and understanding difficulty.

App Build Hook

Package resources depend on UI project build, while copying UI resources dist to runtime static file directory:

    //Really Static resource of the UI to Output Dir
    tasks.register('copyUIResources', Copy) {
        dependsOn project(':good-app-ui').tasks.named('build')
        from project(':good-app-ui').layout.projectDirectory.dir('dist')
        into "${layout.buildDirectory.get()}/resources/main/static"
    }

    tasks.named('processResources') {
        dependsOn 'copyUIResources'
    }

SPA Filter

Whether the hope.open.api.spa flag is enabled:

  1. hope.common.spring.api.spa.wbmvc.SpaMvcConfiguration controls SPA configuration under SERVLET
  2. hope.common.spring.api.spa.webflux.SpaFluxConfiguration controls SPA configuration under REACTIVE

URL reverse proxy rules are defined in SpaPathChecker:

SpaPathChecker DEFAULT =
      path ->
          !path.startsWith("/api")
              && !path.startsWith("/management")
              && !path.startsWith("/v3/api-docs")
              && !path.startsWith("/hope/meta")
              && !path.startsWith("/h2-console")
              && !path.contains(".")
              && path.matches("/(.*)");

if (checker.passToSpa(path)) {
      request.getRequestDispatcher("/index.html").forward(request, response);
      return;
}

Default rules:

  1. Don’t start with /api
  2. Don’t start with /management
  3. Don’t start with /v3/api-docs
  4. Don’t start with /h2-console
  5. Don’t contain a period (.)
  6. Match the pattern ”/(.*)

For example:

  1. If someone visits /api/users → request goes to backend
  2. If someone visits /about → request is forwarded to index.html
  3. If someone visits /static/image.jpg → request is served directly

Then you can fully enjoy the same smooth convenience and experience as the frontend!