Replies: 4 comments 9 replies
-
@niloc132 thank you for such a detailed explanation of the externs issue. First of all, i think we need the @realityforge opinion, simply because he is a maintainer of the most complete set of externs that exists. The Closure team is not very active at merging fixes and updates, so we might rethink which externs we are going to use as base level for our projects. I like the idea of a public folder because it’s close to gwt2 experience and very familiar to all gwt devs and it’s nice to be able to hold all app related resources in one place. Also I like the idea of /META-INF/externs/ as a mandatory path for externs just because it helps us keep our libs clean. An ability to serve web jars out of the box is a very cool feature, so it’s great to have. Resolving externs conflicts is a huge and complex topic, so maybe we can resolve it later. |
Beta Was this translation helpful? Give feedback.
-
I agree that maximum flexibility and control would be to offer a manifest file of some kind per artifact, but at this time I have to reject that as being necessary or reasonable in the j2cl ecosystem. There are several factors for this:
|
Beta Was this translation helpful? Give feedback.
-
Apologies, for having too much unrelated content in my reply, I'll be more explicit: The bazel ecosystem will not support manifests, this is not an option. Maven jars that require a manifest to be read will not be understood in bazel, and jars published to maven via bazel will not contain them even if maven requires them. This will make the ecosystems incompatible. The bazel build rules become a manifest of a sort, though with some conventions that are configurable and many that are not. Google is the maintainer of the j2cl bazel rules, and will not support a manifest except the build rules themselves, which makes sense since you must declare explicit build rules for each and every dependency that doesn't live in a bazel project (and often even for those that do). In contrast, offering consistent conventions will give us a chance to demonstrate good ways of handling complexity that make sense to support in multiple build systems. These conventions could be offered to bazel to ensure compatibility, and they might accept them (they will not accept a manifest file). As such, there is no build tool agnostic manifest that can exist, unless maven itself invokes bazel, at which time it probably makes more sense to stop using maven entirely. I am not interested in designing a maven plugin that cannot interoperate with bazel, that is a major loss from my perspective. I know you maintain your own plugin to support other features that I consider anti-goals - I have no objection to that, but this repo has specific aims of performance and interoperability that must be met. |
Beta Was this translation helpful? Give feedback.
-
I think the most important question to answer before any decision can be made is roughly. "Do you want to use the same jar to support both GWT 2.x and J2CL?" In the beginning of our journey we thought the answer was yes. We would only switch Essentially the code that is optimal for J2CL is rarely the optimal shape for GWT when it comes to optimisations and vice versa. i.e. In Akasha (the browser adapter layer for those not familiar) we very deliberately use typedefs (which closure compiler can optimise) in preference to Unlike @niloc132, in almost all the places where we have javascript included via the public directives in GWT modules we have multiple public paths in every GWT jar. In the javascript ecosystem it is pretty common to have a Conceptually, in a "normal library" we would typically include non-closure js, closure js, It should be noted that this thinking is very different (the opposite?) from my past thinking where I thought that it would be possible to use a single jar between GWT and J2CL and we should include a manifest that multiple tools could read and process. While such a tool may be possible I would be more inclined to have separate tools for each task. i.e. the j2clmavenplugin includes all javascript in jar ignoring |
Beta Was this translation helpful? Give feedback.
-
JS included in Jars falls into roughly three categories:
.native.js
files, which are consumed explicitly by j2cl and hidden from closure).Externs fall into another category of problems: briefly, duplication of externs by independent sources will cause compile errors, with no option to "union" them in the compiler. As they cannot be simply detected while setting up the build (all JS would need to be parsed to achieve this), a convention of "extern JS" vs "code JS" would help to let the plugin make decisions about externs, such as a hypothetical "merge externs" step.
Aside from the special case of the
.native.js
standard enforced by j2cl, there is no convention that distinguishes these files, except from checking the actual contents of an externs file and finding a@externs
annotation. This discussion aims to propose an approach where we can at least make it clear how these files can be handled by j2cl-maven-plugin when found in a jar or in a java project, and perhaps suggest a consistent standard to be followed by other j2cl build tools.Exclude
*/public/*
from Closure, copy*/public/*
to outputIn GWT 2, the "public" package is used to indicate that some sources will be copied directly to the output, though nothing is said about whether or not those sources are present in the rest of the build. One proposal is to exclude all public/ directories from having their contents be passed to closure, and in turn, expect that any contents found within any public/ directory end up in the final output.
Exclude
/META-INF/resources/*
from Closure, copy*/META-INF/resources/*
to outputAnother option, borrowed from webjars.org, is to include these resources in the jar's META-INF/ directory at its root. From https://www.webjars.org/documentation#servlet3
I am not proposing that we actually use the same path, since that would generally imply either that client-only jars are deployed to the server, or that client libraries split their resources into a jar just for server content and another just for j2cl/gwt. There is also the problem of the J2cl/Java code within a project understanding the appropriate absolute/relative path to use the find the resources (a *.war file might be hosted at
/
, or might have a sub-path). With that said, the idea does offer a canonical source directory to indicate what should be copied to the output directory.It might make sense to use some path within
META-INF/
rather thanresources/
to be clear that this is specific to Java being compiled to JS before being built into a server, rather than just following the same conventions as webjars. On the other hand, allowing arbitrary webjars to be added to a j2cl project as a runtime dependency would be a handy way to depend on external JS resources without otherwise copying them into source control, or adding npm build steps.Mark all contents that match
/META-INF/closure-externs
or*/*.externs.js
as externs and pass them to ClosureThis would serve as a convention, any jar following this would enable the application author to opt-in to a later "merge externs" step, or "exclude externs, I'll provide my own" for manual merging or preferring one set of externs over another.
Handling externs in this way also suggests that j2cl libraries should include their own externs, rather than rely on closure-compiler's built in ones (which vary from release to release). Note that this is already possible through the
<env>CUSTOM</env>
configuration option, though the default value isBROWSER
, as it is in closure-compiler itself. We would need to coordinate with libraries such as https://github.com/google/elemental2/ and https://github.com/akasha/akasha/ to achieve this consistency.Proposed summary for discussion, sample patch to follow
/META-INF/*
entirely from closure-compiler, to allow these use cases and more unanticipated ones*/public/*
entirely from closure-compiler*.externs.js
OR/META-INF/externs/
is an externs file, emit an optional warning otherwise (to future-proof libraries for a merge/exclude option)META-INF/resources/
and*/public/
to the same output directory as the generated JS. This would not be exclusive to .js files, but could include other resources like images, fonts, css, etc.Beta Was this translation helpful? Give feedback.
All reactions