CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-vaadin--vaadin-maven-plugin

Maven plugin for Vaadin Flow applications that handles frontend resource management, webpack bundling, and development workflow automation

Overview
Eval results
Files

production-build.mddocs/

Production Build

The build-frontend goal creates optimized frontend bundles for production deployment with comprehensive dependency management and build optimization.

Goal Configuration

<goal>build-frontend</goal>
<!-- Default phase: process-classes -->
<!-- Dependency resolution: compile-plus-runtime -->

Purpose

This goal performs production build tasks:

  • Updates package.json with @NpmPackage annotations from classpath
  • Copies frontend resources from JAR files to node_modules
  • Installs dependencies via npm/pnpm/bun
  • Updates import files with @JsModule, @Theme, and @JavaScript annotations
  • Generates optimized webpack bundles
  • Validates licenses for commercial components
  • Cleans temporary build files

Configuration Parameters

<configuration>
  <!-- Bundle generation -->
  <generateBundle>true</generateBundle>
  <optimizeBundle>true</optimizeBundle>
  <generateEmbeddableWebComponents>true</generateEmbeddableWebComponents>
  <compressBundle>true</compressBundle>

  <!-- NPM behavior -->
  <runNpmInstall>true</runNpmInstall>
  <ciBuild>false</ciBuild>
  <forceProductionBuild>false</forceProductionBuild>

  <!-- Directories -->
  <frontendResourcesDirectory>${project.basedir}/src/main/resources/META-INF/frontend</frontendResourcesDirectory>
  <frontendOutputDirectory>${project.build.outputDirectory}/META-INF/VAADIN/webapp</frontendOutputDirectory>

  <!-- Cleanup -->
  <cleanFrontendFiles>true</cleanFrontendFiles>
</configuration>

Boolean Parameters

<generateBundle>true|false</generateBundle>                     <!-- Generate frontend bundle -->
<runNpmInstall>true|false</runNpmInstall>                      <!-- Run npm install -->
<generateEmbeddableWebComponents>true|false</generateEmbeddableWebComponents> <!-- Generate web components -->
<optimizeBundle>true|false</optimizeBundle>                    <!-- Use bytecode scanner optimization -->
<ciBuild>true|false</ciBuild>                                  <!-- Use npm ci instead of npm install -->
<forceProductionBuild>true|false</forceProductionBuild>        <!-- Force build even with default bundle -->
<cleanFrontendFiles>true|false</cleanFrontendFiles>            <!-- Clean generated files after build -->

Directory Parameters

<frontendResourcesDirectory>path/to/frontend/resources</frontendResourcesDirectory>
<frontendOutputDirectory>path/to/output/directory</frontendOutputDirectory>

Usage Examples

Basic Production Build

<plugin>
  <groupId>com.vaadin</groupId>
  <artifactId>vaadin-maven-plugin</artifactId>
  <version>24.9.0</version>
  <executions>
    <execution>
      <goals>
        <goal>build-frontend</goal>
      </goals>
    </execution>
  </executions>
</plugin>

CI/CD Optimized Build

<plugin>
  <groupId>com.vaadin</groupId>
  <artifactId>vaadin-maven-plugin</artifactId>
  <version>24.9.0</version>
  <configuration>
    <ciBuild>true</ciBuild>
    <forceProductionBuild>true</forceProductionBuild>
    <optimizeBundle>true</optimizeBundle>
    <runNpmInstall>true</runNpmInstall>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>build-frontend</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Development Build (Faster)

<configuration>
  <generateBundle>false</generateBundle>
  <runNpmInstall>false</runNpmInstall>
  <optimizeBundle>false</optimizeBundle>
  <cleanFrontendFiles>false</cleanFrontendFiles>
</configuration>

Custom Resource Directories

<configuration>
  <frontendResourcesDirectory>${project.basedir}/frontend-src</frontendResourcesDirectory>
  <frontendOutputDirectory>${project.build.directory}/classes/static</frontendOutputDirectory>
</configuration>

Build Process Flow

  1. Dependency Analysis: Scans classpath for @NpmPackage annotations
  2. Resource Copying: Copies frontend resources from JAR dependencies
  3. Package Installation: Runs npm/pnpm/bun install with resolved dependencies
  4. Import Generation: Updates generated-flow-imports.js with discovered modules
  5. Webpack Configuration: Updates webpack.generated.js with build settings
  6. Bundle Build: Executes webpack build for production optimization
  7. License Validation: Checks commercial component licenses
  8. Cleanup: Removes temporary files (if cleanFrontendFiles enabled)

Bundle Optimization

Bytecode Scanner Optimization

When optimizeBundle is enabled, the plugin uses bytecode analysis to discover frontend components:

<optimizeBundle>true</optimizeBundle>

Benefits:

  • Faster builds by skipping unnecessary file scanning
  • More accurate dependency detection
  • Reduced bundle size through dead code elimination

Production Mode Detection

The plugin automatically detects production mode based on:

  • Maven profiles
  • System properties
  • Execution phase context

License Management

Commercial Components

The plugin validates licenses for commercial Vaadin components:

<commercialWithBanner>false|true</commercialWithBanner>
  • false (default): Requires valid license for commercial components
  • true: Allows commercial components with banner warning

License Validation Process

  1. Scans dependencies for commercial components
  2. Checks for valid license keys in configuration
  3. Throws MissingLicenseKeyException if license required
  4. Updates build file with license status

React Support

Automatic React integration when React Router is detected:

<reactEnable>true|false|null</reactEnable>
  • null (default): Auto-detect based on routes file
  • true: Force React mode
  • false: Disable React support

Hilla Integration

Special handling for Hilla (full-stack) applications:

  • Automatically detects Hilla usage
  • Preserves generated frontend files for development
  • Configures TypeScript generation paths

Command Line Execution

# Standard production build
mvn flow:build-frontend

# Force production build
mvn flow:build-frontend -Dvaadin.forceProductionBuild=true

# CI build with locked dependencies
mvn flow:build-frontend -Dvaadin.ciBuild=true

# Build with custom output directory
mvn flow:build-frontend -Dvaadin.frontendOutputDirectory=target/static

# Debug build process
mvn flow:build-frontend -X

Performance Tuning

Memory Settings

For large projects, increase Maven memory:

export MAVEN_OPTS="-Xmx2g -XX:MaxPermSize=512m"
mvn flow:build-frontend

Parallel Builds

Enable parallel dependency resolution:

<configuration>
  <pnpmEnable>true</pnpmEnable>  <!-- pnpm has better parallel performance -->
</configuration>

Build Caching

The plugin includes intelligent caching:

  • Bundle validation checks if rebuild needed
  • Dependency change detection
  • Incremental compilation support

Error Handling

Build Failures

Error: Frontend build failed
Solution: Check webpack output, verify Node.js version, ensure dependencies are compatible

Memory Issues

Error: JavaScript heap out of memory
Solution: Increase Node.js memory limit or Maven heap size

License Errors

Error: Missing license key for commercial component
Solution: Add license key or enable commercialWithBanner mode

Dependency Conflicts

Error: npm ERR! peer dependency conflict
Solution: Use ciBuild=false for development, resolve version conflicts in package.json

Integration with Maven Phases

Typical phase binding:

<plugin>
  <executions>
    <execution>
      <id>prepare-frontend</id>
      <phase>process-resources</phase>
      <goals>
        <goal>prepare-frontend</goal>
      </goals>
    </execution>
    <execution>
      <id>build-frontend</id>
      <phase>process-classes</phase>
      <goals>
        <goal>build-frontend</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Install with Tessl CLI

npx tessl i tessl/maven-com-vaadin--vaadin-maven-plugin

docs

code-migration.md

frontend-cleanup.md

frontend-development.md

index.md

production-build.md

sbom-generation.md

tile.json