Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rethink "production builds" and get rid of production profile #17737

Open
mstahv opened this issue Sep 28, 2023 · 21 comments
Open

Rethink "production builds" and get rid of production profile #17737

mstahv opened this issue Sep 28, 2023 · 21 comments

Comments

@mstahv
Copy link
Member

mstahv commented Sep 28, 2023

Describe your motivation

Currently our project build files looks ugly and you need special Vaadin skills to build a deployable artifact (typically in Maven project build with production profile that builds the front-end bundle). This makes deploying Vaadin applications harder than it should be and requires special tricks when for example using packeto buildpacks to pack your Vaadin app.

In addition to "just" not being like a standard Java project, this makes Vaadin build files look much more complicated.

Describe the solution you'd like

Make our Maven plugin smarter so that we don't need a special profile for it. It could detect if the front-end build is needed from the environment and/or have some flag to trigger developmentmode/productionmode.

With cloud native buildpacks I have for example used this configuration in my pom.xml to enable production front-end build:

        <activation>
            <property>
                <name>env.CNB_TARGET_OS</name>
                <value>linux</value>
            </property>
        </activation>

But there are probably other ways to detect the situation as well. And most likely we need a flag to set this explicitly as well.

@knoobie
Copy link
Contributor

knoobie commented Sep 28, 2023

For Jenkins I do:

   <activation>
        <!-- Profile that is automatically activated when run in Jenkins because Jenkins creates a env.BUILD_NUMBER-->
        <property>
          <name>env.BUILD_NUMBER</name>
        </property>
    </activation>

@Legioth
Copy link
Member

Legioth commented Oct 2, 2023

Could we do production builds by default? If you do mvn or mvn spring-boot:run, then you want to run in development mode. If you do mvn package or mvn install, then you want to build for production. The same is also the case with Quarkus or if you use e.g. wildfly-maven-plugin or jetty-maven-plugin.

It's a special case if you want to build a .war or .jar that isn't for production use. Maybe we should have a dedicated profile (or just documentation) for that case instead?

@knoobie
Copy link
Contributor

knoobie commented Oct 2, 2023

I'm not sure how good the automatic detection works with all the possible configuration options for the flow maven plugin and e.g. looking at my configuration how different it is for development and production mode. I also often run mvn clean install locally in multi module projects where Vaadin is only used in one and I don't care about a runnable artefact for that anyway, cause I'm starting it locally with spring boot anyway and just need to refresh IDEAs cache or testing other things.

@Legioth
Copy link
Member

Legioth commented Oct 2, 2023

Good point. You might do mvn install locally because you've got a multi-module project even though you're not actually interested in a slow production build for for the Vaadin part.

On the other hand, we might also have a simpler default for tutorials and starters that are based on the single-module use case where production could be the default and then separately show a multi-module setup where a production build isn't the default?

@knoobie
Copy link
Contributor

knoobie commented Oct 2, 2023

It depends on the audience Vaadin wants to target with this. I don't have the numbers, but I would think that multi module projects are wider used in corporate environments, so this change would only benefit starters in terms of repo and developer / user.

I personally would more focus on the idea of Matti and improve auto detection of environments where the production build normally runs (GitHub, gitlab, Jenkins, bit bucket and so on) and activate the profile by default

@mstahv
Copy link
Member Author

mstahv commented Oct 3, 2023

The most common case for development mode is you launch it via IDE's public static void main string args support. If we can detect that (or everything else) and provide a flag to set development mode explicitly 🤔

@knoobie
Copy link
Contributor

knoobie commented Oct 3, 2023

Now I'm feeling like a unicorn, never done that, always using the mvn boot run command 🤫

@mcollovati
Copy link
Collaborator

Now I'm feeling like a unicorn, never done that, always using the mvn boot run command

You're not alone, we are at least in two 😁

@Legioth
Copy link
Member

Legioth commented Oct 3, 2023

One thing to keep in mind here is that we're always balancing between two partially conflicting goals:

  1. Keep the getting-started experience as easy as possible for new users. We want to make sure they immediately get on a path towards succeeding with Vaadin. This means that we want to have good defaults and we want to make things like the default pom.xml file look simple rather than intimidating.
  2. Help users succeed with all the complex stuff that pops up in real-world applications. It's acceptable if users need to do som additional setup based on their needs as long as we can guide them in the right direction.

@knoobie
Copy link
Contributor

knoobie commented Oct 3, 2023

Don't get me wrong, I totally understand the desire and need to appeal to new developer - especially those that are scared away by more than two lines of config (over exaggerated). But I feel that the amount of "goodies" are already plenty out there with the default development and prod bundle making the whole development process for new developer or rapid prototyping relatively painless.

Just some ideas:

  • add more comments to the pom with explanations about each important part with links to the docs for further reading
  • add a do 1., 2. and 3. depending on your needs to the pom's comment on top so that everyone can read it
  • Improve the workflow for new users that development and prod bundle can work without the need of rebuilding even when adding css (e.g. serve those as static resources) so that the whole additional config for production is gone / can be a text / explanation in the pom when people need it.. or even:
  • add a prominent message to the log: "you have added an addon / Javascript which needs a new development / prod bundle: read here more about it. You can also find here ready made snippets for your pom"
  • Make flow more intelligent in guiding users: feature: provide an API to make router ignore an anchor #17745 (comment)

All those points expect that people are able to read cough - let's hope, with ChatGPT and others.. people are more likely to read than before..

@mstahv
Copy link
Member Author

mstahv commented Feb 28, 2024

Here is a design for you. Prototyped this a bit with V24.4 test project and at least for Spring Boot based projects I'm quite confiden this would work pretty well:

  • vaadin-dev artifact should be made optional in core artifacts and defined as optional in projects, just like spring-boot-devtools. This way no ugly exclusions are needed in production profile, it is simply left out of the production artifact. This could be done eagerly without big regression risks even in 24.4 🤔 Release notes & clear error message would make it easy for developers to "add back" the vaadin-dev as optional dependency. Now that there are also other dependency dance, it would be a perfect time to do this kind of change.
  • The Vaadin maven plugin should work like spring boot plugin, its magic should be enabled implicitly. E.g. skip goals if spring-boot:run is executed by @knoobie via CLI/IDE 😜 Add flags to enable/disable explicitly for thing that are needed.
  • Without special configuration, maven plugin generated stuff should be ignored if vaadin-dev is on the classpath. Basiclly we would by default start in dev mode, even if "production front-end stuff" is available.
  • The production profile should be entirely removed from new starters.

In the prototype:

  • production build, ok and "cloud ready" (build pack makes a production ready artifacts without further dance 💪)
  • development mode ok , unless run with spring-boot:run (which triggers vaadin maven plugin as it doesn't have the "magic" and is configured to do the "production build" for better defaults).
  • Various required exculsions (because dev-mode is direct dependency currently) make the build look almost as ugly as the current default starter 🤪

I suggest to do the dev-mod scope change "today", for Vaadin 24.4, and others ASAP without a rush (at least with a bit of creativity I believe it to be possible to introduce these in a perfectly backwards compatible manner whenever we want, only build plugin changes required).

@mstahv
Copy link
Member Author

mstahv commented Feb 28, 2024

After some further investigation, the above is not a perfect solution as such for Spring Boot apps until spring-projects/spring-boot#25403 gets fixed. Based on how Spring Boot treats spring-boot-devtools I kind of thought optional dependencies are not packed in by Spring Boot, but they are, and SB plugin just excludes devtools. Thus, the production jar works in production mode with the prototype, but contains obsolete stuff we don't want there (without further configuration of spring-boot-maven plugin).

With standard war projects (or Quarkus probably) this would nail it.

@shymega
Copy link

shymega commented Mar 26, 2024

I'm just curious about this sentence from OP's post:

requires special tricks when for example using Packeto buildpacks to pack your Vaadin app.

I'm trying to deploy a Hilla app on Fly.io, with Spring Native and Paketo Buildpacks. However, I can't get past the build-frontend exception due to Vite not being located.

I'm assuming OP was referring to that. I would be very grateful if the workaround for this was put in the original issue, or as a comment - just as a workaround. I've subscribed to this issue in the meantime.

@knoobie
Copy link
Contributor

knoobie commented Mar 27, 2024

Please create a issue in Hilla; it should work if configured correctly and used. This issue is about resucing the need for special config altogether.

@shymega
Copy link

shymega commented Mar 30, 2024

Please create a issue in Hilla; it should work if configured correctly and used. This issue is about resucing the need for special config altogether.

Apologies, I felt this is also a Flow issue as the problematic Maven plugin inherits from Flow.

Feel free to hide my original comment as off-topic, and I'll do some more digging to figure out where the best place for the issue would be. At this point, I'm fairly certain it's a Flow Maven issue.

I'm still curious about the workaround OP used (if they did?), but I appreciate this isn't the place to discuss that.

@mstahv
Copy link
Member Author

mstahv commented Apr 25, 2024

Sorry I missed the continued discussion here and returning to the subject bit late (I have overflow in GH notifications 😬). Did you try the trick/workkaround I use (mentioned in the issue description) to active the production profile by default? I think that should work for you.

@mstahv
Copy link
Member Author

mstahv commented Jun 26, 2024

I have been iterating a PoC towards my understanding of "the ideal state", back and forth, with different approaches, for way too long without releasing anything for public discussion. Just a while ago I finally pushed our now a first public iteration for comments. Maven central is probably still syncing, but quite soon you ought to be able to test the example project from this repository https://github.com/viritin/viritin-sb

Things to notice and test, the important parts:

  • No special profiles you need to learn about
  • mvn install creates a production ready artifact, no special tricks or Vaadin knowledge required typical cloud deployments or CI/CD pipelines
  • Starting the app from IDE (main method) ( or in the @knoobie method 😉 using mvn spring-boot:run), gets you into development mode (no special Vaadin knowledge needed if you want back to the dev mode after mvn package)
  • the pom.xml (of the example project) is short and clean

With these things in core Vaadin would feel much easier to take into use for experienced Java developer (partly perceived feeling, but very important!) and would provide less head-ache when integrating to various systems in the cloud era.

Notes about implementation details of this poc in its current form:

  • The PoC is currently Spring Boot only
  • The Hilla setup is currently broken, but probably fixable easily for somebody is familiar with the module structure there
  • The PoC is bit fragile for version changes, if we change what is needed by vaadin-dev (which is a LOT these days). The dev mode exclusion is currently hard coded, as I got frustrated fiddling with my custom maven plugin that would have detected the correct transitive dependency set and would have fed that for spring-boot-maven-plugin as artifacts to exclude from the "repackaged" artifact.
  • The final solution can naturally be built in a different way if bolted directly to core Vaadin artifacts
  • Some more advanced Maven experts can probably come up with better solutions to accomplish the same end user value as this kind of poc on top of current Vaadin release. I'm very eagerly waiting for contributions or alternative solutions.
  • Probably should have built the PoC with Gradle as it is easier platform for various hacks.

Heading now to test this in a couple of hobby projects, please help my by doing the same!

@mstahv
Copy link
Member Author

mstahv commented Jul 5, 2024

Update, version 0.0.2 of the PoC published in previous comment also works with Hilla (smoke tested).

@mstahv
Copy link
Member Author

mstahv commented Jul 18, 2024

Updates regarding my PoC:

  • Version 0.0.3, now uses quite different approach to get pretty much the same DX: The default scope of dependencies is now targeted for production and 'test' scope contains the "dev mode stuff". Kind of what Leif suggested earlier, but instead of custom profile for development, utilising test scope.
    • Same approach as suggested by Spring Boot to use Testcontainers in development time.
    • Requires another Spring Boot main method to src/test/java (bit more code, although can be handy for other test time configuration and e.g. Testcontainers) usage
  • There is also a "viritin-addon-project-parent" for Vaadin add-ons (no need to be a Viritin add-on 🤓). Much cleaner build possible for add-ons as well and Spring Boot works great as a test server (I have used this approach in more complex form in other add-ons as well. Starts faster than Jetty and provides features one might want to utise in tests.

@Dudeplayz
Copy link
Contributor

  • Starting the app from IDE (main method) ( or in the @knoobie method 😉 using mvn spring-boot:run), gets you into development mode (no special Vaadin knowledge needed if you want back to the dev mode after mvn package)

Please keep quarkus:dev in mind, as it is clear for what purpose it is used. Quarkus also allows remote development, which could be a use case were an build is intended with development bundle. I am not using this actually, but it came in my mind.

@mstahv
Copy link
Member Author

mstahv commented Aug 15, 2024

Good point @Dudeplayz. I'm quite confident that this approach can be applied in some for Quarkus apps as well at least with some plugin code. As dev mode is in quarkus started with the CLI tooling or maven plugin, it might even be easier to intercept dev mode startups. Maybe @mcollovati has some good ideas how to get a similar exprience with Quarkus🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 🅿️Parking lot - under consideration
Development

No branches or pull requests

7 participants