Skip to content

Commit

Permalink
Add config option and warning message
Browse files Browse the repository at this point in the history
  • Loading branch information
ia3andy committed Jan 26, 2024
1 parent e3154d9 commit 48ed0f4
Show file tree
Hide file tree
Showing 35 changed files with 323 additions and 176 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -141,15 +142,23 @@ void produceWebAssets(BuildProducer<EntryPointBuildItem> bundles,
WebAssetsLookupDevContext context,
boolean checkIfExists) {
for (Map.Entry<String, List<BundleWebAsset>> e : context.bundleAssets().entrySet()) {
bundles.produce(new EntryPointBuildItem(e.getKey(), checkIfExists ? checkWebAssets(e.getValue()) : e.getValue()));
produceWebAssetsWithCheck(checkIfExists, e.getValue(),
webAssets -> bundles.produce(new EntryPointBuildItem(e.getKey(), webAssets)));
}

bundleConfigAssets.produce(new BundleConfigAssetsBuildItem(
checkIfExists ? checkWebAssets(context.bundleConfigWebAssets()) : context.bundleConfigWebAssets()));
produceWebAssetsWithCheck(checkIfExists, context.bundleConfigWebAssets(),
webAssets -> bundleConfigAssets.produce(new BundleConfigAssetsBuildItem(webAssets)));

quteTagsAssets.produce(new QuteTagsBuildItem(
checkIfExists ? checkWebAssets(context.quteWebAssets()) : context.quteWebAssets()));
produceWebAssetsWithCheck(checkIfExists, context.quteWebAssets(),
webAssets -> quteTagsAssets.produce(new QuteTagsBuildItem(webAssets)));
}

private static <T extends WebAsset> void produceWebAssetsWithCheck(boolean checkIfExists, List<T> e,
Consumer<List<T>> consumer) {
final List<T> webAssets = checkIfExists ? checkWebAssets(e) : e;
if (!webAssets.isEmpty()) {
consumer.accept(webAssets);
}
}

private static <T extends WebAsset> List<T> checkWebAssets(List<T> webAssets) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@

import org.jboss.logging.Logger;

import io.quarkiverse.web.bundler.deployment.items.HtmlTemplatesBuildItem;
import io.quarkiverse.web.bundler.deployment.items.ProjectResourcesScannerBuildItem;
import io.quarkiverse.web.bundler.deployment.items.QuteTemplatesBuildItem;
import io.quarkiverse.web.bundler.deployment.items.WebAsset;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.LiveReloadBuildItem;

public class HtmlTemplateAssetsScannerProcessor {
public class QuteTemplateAssetsScannerProcessor {

private static final Logger LOGGER = Logger.getLogger(HtmlTemplateAssetsScannerProcessor.class);
private static final Logger LOGGER = Logger.getLogger(QuteTemplateAssetsScannerProcessor.class);

@BuildStep
HtmlTemplatesBuildItem scan(ProjectResourcesScannerBuildItem scanner,
QuteTemplatesBuildItem scan(ProjectResourcesScannerBuildItem scanner,
WebBundlerConfig config,
LiveReloadBuildItem liveReload)
throws IOException {
Expand All @@ -28,13 +28,13 @@ HtmlTemplatesBuildItem scan(ProjectResourcesScannerBuildItem scanner,
&& context != null
&& !hasChanged(config, liveReload, s -> s.substring(config.webRoot().length()).matches("^/.+\\.html$"))) {
LOGGER.debug("Web bundler html templates scan not needed for live reload");
return new HtmlTemplatesBuildItem(context.assets());
return new QuteTemplatesBuildItem(context.assets());
}
final List<WebAsset> assets = scanner.scan(new ProjectResourcesScannerBuildItem.Scanner(config.webRoot(),
"glob:*.html", config.charset()));
liveReload.setContextObject(HtmlTemplatesContext.class, new HtmlTemplatesContext(assets));
LOGGER.debugf("Web bundler %d html templates found.", assets.size());
return new HtmlTemplatesBuildItem(assets);
return new QuteTemplatesBuildItem(assets);
}

private record HtmlTemplatesContext(List<WebAsset> assets) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ default String fromWebRoot(String dir) {
*/
WebDependenciesConfig dependencies();

/**
* When enabled, Quarkus will create redirections from {bundlePath}/{entryPointKey}.{js,css} to the corresponding file
* containing the unique hash.
* This is useful for fixed external access to the bundle files (fullstack microservices).
*/
@WithDefault("false")
Boolean bundleRedirect();

/**
* The default charset
*/
Expand Down Expand Up @@ -117,10 +125,17 @@ interface WebDependenciesConfig {
Optional<String> nodeModules();

/**
* If enabled web dependencies will also be served, this is usually not needed as they are already bundled.
* Disable this option to allow using runtime web dependencies.
* When a runtime scope web dependency is used, the dependency will be present in the target app and served at runtime.
* When a compile only scope web dependency is used, the dependency will only be used at build time and will not be
* present in the target app.
*
* WARNING: Maven compile scope is considered as a runtime scope, use 'provided' for compile only. On Gradle,
* 'compileOnly' is compile only.
*
*/
@WithDefault("false")
boolean serve();
@WithDefault("true")
boolean compileOnly();

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;

import io.quarkus.builder.item.MultiBuildItem;

Expand Down Expand Up @@ -40,4 +41,12 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(entryPointKey, webAssets);
}

@Override
public String toString() {
return new StringJoiner(", ", EntryPointBuildItem.class.getSimpleName() + "[", "]")
.add("entryPointKey='" + entryPointKey + "'")
.add("webAssets=" + webAssets)
.toString();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.quarkiverse.web.bundler.deployment.items;

import java.util.List;

public final class QuteTemplatesBuildItem extends WebAssetsBuildItem {

public QuteTemplatesBuildItem(List<WebAsset> webAssets) {
super(webAssets);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import static io.quarkiverse.web.bundler.deployment.staticresources.GeneratedStaticResourceBuildItem.WatchMode.RESTART;
import static io.quarkiverse.web.bundler.deployment.util.PathUtils.prefixWithSlash;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
Expand All @@ -13,6 +12,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.jboss.logging.Logger;

Expand All @@ -26,6 +26,7 @@
import io.quarkus.deployment.builditem.LiveReloadBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.vertx.http.deployment.spi.AdditionalStaticResourceBuildItem;

public class GeneratedStaticResourcesProcessor {
Expand All @@ -39,9 +40,14 @@ public void processStaticFiles(
BuildProducer<AdditionalStaticResourceBuildItem> vertxStaticResourcesProducer,
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles,
CurateOutcomeBuildItem curateOutcome,
OutputTargetBuildItem outputTarget,
LiveReloadBuildItem liveReload,
LaunchModeBuildItem launchModeBuildItem) {
final File buildDir = launchModeBuildItem.getLaunchMode().isDevOrTest() ? getBuildDirectory(curateOutcome) : null;
if (staticResources.isEmpty()) {
return;
}
final Path buildDir = launchModeBuildItem.getLaunchMode().isDevOrTest() ? getBuildDirectory(outputTarget, curateOutcome)
: null;
final StaticResourcesDevContext staticResourcesDevContext = liveReload
.getContextObject(StaticResourcesDevContext.class);
if (liveReload.isLiveReload() && staticResourcesDevContext != null) {
Expand All @@ -51,7 +57,7 @@ public void processStaticFiles(
// a build tool clean might be necessary to make sure the static resources are clean
if (staticResources.stream().map(GeneratedStaticResourceBuildItem::getResourceName).noneMatch(r::equals)) {
try {
Files.deleteIfExists(buildDir.toPath().resolve(r));
Files.deleteIfExists(buildDir.resolve(r));
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down Expand Up @@ -81,7 +87,7 @@ public void processStaticFiles(
.produce(new AdditionalStaticResourceBuildItem(prefixWithSlash(staticResource.getPublicPath()), false));
// for dev/test mode
if (launchModeBuildItem.getLaunchMode().isDevOrTest()) {
Path targetPath = buildDir.toPath().resolve(staticResource.getResourceName());
Path targetPath = buildDir.resolve(staticResource.getResourceName());
// TODO: Change detection could also be done automatically by comparing the content (might be slow) or a hash of it using dev context
if (!Files.exists(targetPath) || staticResource.isChanged()) {
try {
Expand All @@ -98,32 +104,31 @@ public void processStaticFiles(
liveReload.setContextObject(StaticResourcesDevContext.class, new StaticResourcesDevContext(generatedStaticFiles));
}

public static File getBuildDirectory(CurateOutcomeBuildItem curateOutcomeBuildItem) {
File buildDir = null;
public static Path getBuildDirectory(OutputTargetBuildItem outputTarget, CurateOutcomeBuildItem curateOutcomeBuildItem) {
if (Files.exists(outputTarget.getOutputDirectory().resolve("classes/META-INF/resources"))) {
return outputTarget.getOutputDirectory().resolve("classes");
}
if (Files.exists(outputTarget.getOutputDirectory().resolve("resources/main/META-INF/resources"))) {
return outputTarget.getOutputDirectory().resolve("resources/main");
}
Path buildDir = null;
ArtifactSources src = curateOutcomeBuildItem.getApplicationModel().getAppArtifact().getSources();
if (src != null) { // shouldn't be null in dev mode
Collection<SourceDir> srcDirs = src.getResourceDirs();
if (srcDirs.isEmpty()) {
Collection<SourceDir> dirs = src.getResourceDirs();
if (dirs.isEmpty()) {
// in the module has no resources dir?
srcDirs = src.getSourceDirs();
dirs = src.getSourceDirs();
}
if (!srcDirs.isEmpty()) {
if (!dirs.isEmpty()) {
final Set<Path> outputDirs = dirs.stream().map(SourceDir::getOutputDir).collect(Collectors.toSet());
// pick the first resources output dir
Path resourcesOutputDir = srcDirs.iterator().next().getOutputDir();
buildDir = resourcesOutputDir.toFile();
if (srcDirs.size() > 1) {
buildDir = outputDirs.iterator().next();
if (outputDirs.size() > 1) {
LOGGER.warnf("Multiple resources directories found, using the first one in the list: %s",
resourcesOutputDir);
outputDirs);
}

}
}
if (buildDir == null) {
// the module doesn't have any sources nor resources, stick to the build dir
buildDir = new File(
curateOutcomeBuildItem.getApplicationModel().getAppArtifact().getWorkspaceModule().getBuildDir(),
"classes");
}

return buildDir;
}
Expand Down
16 changes: 5 additions & 11 deletions deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,6 @@
<artifactId>quarkus-web-bundler-sass-compiler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yahoo.platform.yui</groupId>
<artifactId>yuicompressor</artifactId>
<version>${yuicompressor.version}</version>
</dependency>
<!--
<dependency>
<groupId>com.sksamuel.scrimage</groupId>
<artifactId>scrimage-core</artifactId>
<version>${scrimage-core.version}</version>
</dependency>-->
<dependency>
<groupId>io.quarkus.qute</groupId>
<artifactId>qute-core</artifactId>
Expand All @@ -53,6 +42,11 @@
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
import static java.util.concurrent.CompletableFuture.completedFuture;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
Expand All @@ -22,7 +21,7 @@
import org.eclipse.microprofile.config.ConfigProvider;

import io.quarkiverse.web.bundler.deployment.items.GeneratedBundleBuildItem;
import io.quarkiverse.web.bundler.deployment.items.HtmlTemplatesBuildItem;
import io.quarkiverse.web.bundler.deployment.items.QuteTemplatesBuildItem;
import io.quarkiverse.web.bundler.deployment.items.WebAsset;
import io.quarkiverse.web.bundler.deployment.staticresources.GeneratedStaticResourceBuildItem;
import io.quarkiverse.web.bundler.runtime.Bundle;
Expand All @@ -32,10 +31,10 @@
import io.quarkus.deployment.builditem.LiveReloadBuildItem;
import io.quarkus.qute.*;

public class HtmlTemplateWebAssetsProcessor {
public class QuteTemplateWebAssetsProcessor {
@BuildStep
void processHtmlTemplateWebAssets(WebBundlerConfig config,
HtmlTemplatesBuildItem htmlTemplates,
QuteTemplatesBuildItem htmlTemplates,
GeneratedBundleBuildItem generatedBundle,
BuildProducer<GeneratedStaticResourceBuildItem> staticResourceProducer,
LiveReloadBuildItem liveReload,
Expand Down Expand Up @@ -104,24 +103,25 @@ public Optional<TemplateLocation> locate(String id) {
return Optional.empty();
}
String name = id.replace("web-bundler/", "");
try (InputStream templateStream = this.getClass().getResourceAsStream("/templates/tags/" + name)) {
if (templateStream == null) {
return Optional.empty();
}
return Optional.of(new TemplateLocation() {
@Override
public Reader read() {
return new InputStreamReader(templateStream, StandardCharsets.UTF_8);
final URL resource = this.getClass().getResource("/templates/tags/" + name);
if (resource == null) {
return Optional.empty();
}
return Optional.of(new TemplateLocation() {
@Override
public Reader read() {
try {
return new InputStreamReader(resource.openStream(), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public Optional<Variant> getVariant() {
return Optional.empty();
}
});
} catch (IOException e) {
throw new UncheckedIOException(e);
}
@Override
public Optional<Variant> getVariant() {
return Optional.empty();
}
});
}

}
Expand Down
Loading

0 comments on commit 48ed0f4

Please sign in to comment.