Skip to content

Commit

Permalink
feat: Move default frontend to src/main and enable frontend fallback (#…
Browse files Browse the repository at this point in the history
…18828)

Move frontend folder from root to src/main.

Enable falling back to the
original frontend folder if
the new one doesn't exist.

Closes #18436
  • Loading branch information
caalador committed Feb 29, 2024
1 parent 69b1d4f commit bb25955
Show file tree
Hide file tree
Showing 458 changed files with 518 additions and 168 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,4 @@ vaadin-dev-server/src/main/resources/META-INF/frontend
vaadin-dev-server/src/main/resources/META-INF/metadata

/flow-tests/**/frontend/routes.tsx
flow-tests/**/src/main/bundles/*
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ public class BuildDevBundleMojo extends AbstractMojo
@Parameter(property = InitParameters.REACT_ENABLE, defaultValue = "true")
private boolean reactEnable;

/**
* A directory with project's frontend source files.
*/
@Parameter(defaultValue = "${project.basedir}/src/main/" + FRONTEND)
private File frontendDirectory;

@Override
public void execute() throws MojoFailureException {
long start = System.nanoTime();
Expand Down Expand Up @@ -262,12 +268,12 @@ public boolean eagerServerLoad() {

@Override
public File frontendDirectory() {
return new File(projectBasedir, FRONTEND);
return frontendDirectory;
}

@Override
public File generatedTsFolder() {
return new File(projectBasedir, FRONTEND + "/generated");
return new File(frontendDirectory(), "generated");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ class VaadinSmokeTest : AbstractGradleTest() {
*/
@Test
fun vaadinPrepareFrontendDeletesFrontendGeneratedFolder() {
val generatedFolder = testProject.newFolder("frontend/generated")
val generatedFile = testProject.newFile("frontend/generated/index.ts")
val generatedFlowFolder = testProject.newFolder("frontend/generated/flow")
val generatedOldFlowFile = testProject.newFolder("frontend/generated/flow/extra.js")
val generatedFolder = testProject.newFolder(FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR)
val generatedFile = testProject.newFile(FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR + "index.ts")
val generatedFlowFolder = testProject.newFolder(FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR + "flow")
val generatedOldFlowFile = testProject.newFolder(FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR + "/flow/extra.js")
testProject.build("vaadinPrepareFrontend")
expect(true) { generatedFolder.exists() }
expect(false) { generatedFile.exists() }
Expand Down Expand Up @@ -166,8 +166,8 @@ class VaadinSmokeTest : AbstractGradleTest() {
*/
@Test
fun vaadinCleanDeletesGeneratedFolder() {
val generatedFolder = testProject.newFolder("frontend/generated")
val generatedFile = testProject.newFile("frontend/generated/index.ts")
val generatedFolder = testProject.newFolder(FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR)
val generatedFile = testProject.newFile(FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR + "index.ts")
testProject.build("vaadinClean")
expect(false) { generatedFile.exists() }
expect(false) { generatedFolder.exists() }
Expand Down Expand Up @@ -317,11 +317,11 @@ class VaadinSmokeTest : AbstractGradleTest() {
result.expectTaskSucceded("vaadinBuildFrontend")

expect(false) {
File(testProject.dir, "frontend/generated/index.ts").exists()
File(testProject.dir, FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR + "index.ts").exists()
}
expect(true) {
// Only generated for executing project or building bundle
File(testProject.dir, "src/main/frontend/generated/index.tsx").exists()
File(testProject.dir, FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR + "index.tsx").exists()
}
}

Expand Down Expand Up @@ -365,7 +365,7 @@ class VaadinSmokeTest : AbstractGradleTest() {
result.expectTaskSucceded("vaadinPrepareFrontend")
result.expectTaskSucceded("vaadinBuildFrontend")

val cssFile = File(testProject.dir, "frontend/generated/jar-resources/mystyle.css")
val cssFile = File(testProject.dir, FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR + "jar-resources/mystyle.css")
expect(true, cssFile.toString()) { cssFile.exists() }

}
Expand Down Expand Up @@ -403,7 +403,7 @@ class VaadinSmokeTest : AbstractGradleTest() {
}

private fun enableHilla() {
testProject.newFolder("frontend")
testProject.newFile("frontend/index.ts")
testProject.newFolder(FrontendUtils.DEFAULT_FRONTEND_DIR)
testProject.newFile(FrontendUtils.DEFAULT_FRONTEND_DIR + "index.ts")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ public class PluginEffectiveConfiguration(
.convention(project.projectDir)

public val frontendDirectory: Provider<File> = extension.frontendDirectory
.convention(File(project.projectDir, "frontend"))
.convention(File(project.projectDir, FrontendUtils.DEFAULT_FRONTEND_DIR))

public val generateBundle: Provider<Boolean> = extension.generateBundle
.convention(true)
Expand Down Expand Up @@ -362,7 +362,7 @@ public class PluginEffectiveConfiguration(
.convention(File(project.projectDir, "src/main/resources"))

public val generatedTsFolder: Property<File> = extension.generatedTsFolder
.convention(File(project.projectDir, "frontend/generated"))
.convention(File(frontendDirectory.get(), FrontendUtils.GENERATED))

public val nodeVersion: Property<String> = extension.nodeVersion
.convention(FrontendTools.DEFAULT_NODE_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static com.vaadin.flow.server.Constants.VAADIN_SERVLET_RESOURCES;
import static com.vaadin.flow.server.Constants.VAADIN_WEBAPP_RESOURCES;
import static com.vaadin.flow.server.frontend.FrontendUtils.FRONTEND;
import static com.vaadin.flow.server.frontend.FrontendUtils.GENERATED;

import java.io.File;
import java.net.URI;
Expand Down Expand Up @@ -74,13 +75,13 @@ public abstract class FlowModeAbstractMojo extends AbstractMojo
/**
* A directory with project's frontend source files.
*/
@Parameter(defaultValue = "${project.basedir}/" + FRONTEND)
@Parameter(defaultValue = "${project.basedir}/src/main/" + FRONTEND)
private File frontendDirectory;

/**
* The folder where flow will put TS API files for client projects.
*/
@Parameter(defaultValue = "${project.basedir}/" + FRONTEND + "/generated")
@Parameter(defaultValue = "${null}")
private File generatedTsFolder;

/**
Expand Down Expand Up @@ -298,14 +299,15 @@ public boolean eagerServerLoad() {

@Override
public File frontendDirectory() {

return frontendDirectory;
}

@Override
public File generatedTsFolder() {

return generatedTsFolder;
if (generatedTsFolder != null) {
return generatedTsFolder;
}
return new File(frontendDirectory(), GENERATED);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ private Properties getProperties() {
}

private boolean createDirectoryIfNotExists() {
int lastIndex = outputFilePath.lastIndexOf('/');
int lastIndex = outputFilePath
.lastIndexOf(FrontendUtils.isWindows() ? '\\' : '/');
File directory = new File(outputFilePath.substring(0, lastIndex));
return directory.exists() || directory.mkdirs();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public void setup() throws Exception {
defaultJavaSource = new File(".", "src/test/java");
openApiJsonFile = new File(npmFolder,
"target/classes/com/vaadin/hilla/openapi.json");
generatedTsFolder = new File(npmFolder, "frontend/generated");
generatedTsFolder = new File(npmFolder, "src/main/frontend/generated");

Assert.assertTrue("Failed to create a test project resources",
projectFrontendResourcesDirectory.mkdirs());
Expand Down Expand Up @@ -469,7 +469,7 @@ public void existingTokenFile_parametersShouldBeRemoved()
JsonObject initialBuildInfo = Json.createObject();
initialBuildInfo.put(SERVLET_PARAMETER_PRODUCTION_MODE, false);
initialBuildInfo.put(Constants.NPM_TOKEN, "npm");
initialBuildInfo.put(Constants.FRONTEND_TOKEN, "frontend");
initialBuildInfo.put(Constants.FRONTEND_TOKEN, "src/main/frontend");

initialBuildInfo.put(InitParameters.SERVLET_PARAMETER_ENABLE_PNPM,
true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ public void setup() throws Exception {
Mockito.when(project.getBasedir()).thenReturn(projectBase);

packageJson = new File(projectBase, PACKAGE_JSON).getAbsolutePath();
frontendGenerated = new File(projectBase, "frontend/generated");
frontendGenerated = new File(projectBase,
"src/main/frontend/generated");

ReflectionUtils.setVariableValueInObject(mojo, Constants.NPM_TOKEN,
projectBase);
Expand All @@ -75,7 +76,7 @@ public void setup() throws Exception {
"resourceOutputDirectory",
new File(projectBase, VAADIN_SERVLET_RESOURCES));
ReflectionUtils.setVariableValueInObject(mojo, "frontendDirectory",
new File(projectBase, "frontend"));
new File(projectBase, "src/main/frontend"));

ReflectionUtils.setVariableValueInObject(mojo, "openApiJsonFile",
new File(projectBase,
Expand Down Expand Up @@ -301,8 +302,9 @@ private void enableHilla() throws IOException {
.resolve("test-classes/com/vaadin/hilla"));
Files.createFile(Paths.get(projectBase.toString(), "target").resolve(
"test-classes/com/vaadin/hilla/EndpointController.class"));
Files.createDirectories(Paths.get(projectBase.toString(), "frontend"));
Files.createFile(Paths.get(projectBase.toString(), "frontend")
Files.createDirectories(
Paths.get(projectBase.toString(), "src/main/frontend"));
Files.createFile(Paths.get(projectBase.toString(), "src/main/frontend")
.resolve("index.ts"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ public void setup() throws Exception {
VAADIN_SERVLET_RESOURCES);
defaultJavaSource = new File(".", "src/test/java");
defaultJavaResource = new File(".", "src/test/resources");
generatedTsFolder = new File(projectBase, "frontend/generated");
generatedTsFolder = new File(projectBase,
"src/main/frontend/generated");

ReflectionUtils.setVariableValueInObject(mojo, Constants.NPM_TOKEN,
projectBase);
Expand All @@ -111,7 +112,7 @@ public void setup() throws Exception {
ReflectionUtils.setVariableValueInObject(mojo,
"resourceOutputDirectory", resourceOutputDirectory);
ReflectionUtils.setVariableValueInObject(mojo, "frontendDirectory",
new File(projectBase, "frontend"));
new File(projectBase, "src/main/frontend"));

ReflectionUtils.setVariableValueInObject(mojo, "openApiJsonFile",
new File(projectBase,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@
import static com.vaadin.flow.server.Constants.FRONTEND_TOKEN;
import static com.vaadin.flow.server.Constants.JAVA_RESOURCE_FOLDER_TOKEN;
import static com.vaadin.flow.server.Constants.NPM_TOKEN;
import static com.vaadin.flow.server.Constants.PACKAGE_JSON;
import static com.vaadin.flow.server.Constants.PROJECT_FRONTEND_GENERATED_DIR_TOKEN;
import static com.vaadin.flow.server.InitParameters.FRONTEND_HOTDEPLOY;
import static com.vaadin.flow.server.InitParameters.NODE_DOWNLOAD_ROOT;
import static com.vaadin.flow.server.InitParameters.NODE_VERSION;
import static com.vaadin.flow.server.InitParameters.REACT_ENABLE;
import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_INITIAL_UIDL;
import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.GENERATED;
import static com.vaadin.flow.server.frontend.FrontendUtils.LEGACY_FRONTEND_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES;
import static com.vaadin.flow.server.frontend.FrontendUtils.TOKEN_FILE;

Expand Down Expand Up @@ -145,13 +147,14 @@ public static void prepareFrontend(PluginAdapterBase adapter)
Lookup lookup = adapter.createLookup(classFinder);

Options options = new Options(lookup, adapter.npmFolder())
.withFrontendDirectory(adapter.frontendDirectory())
.withFrontendDirectory(getFrontendDirectory(adapter))
.withBuildDirectory(adapter.buildFolder())
.withJarFrontendResourcesFolder(
getJarFrontendResourcesFolder(adapter))
.createMissingPackageJson(true).enableImportsUpdate(false)
.enablePackagesUpdate(false).withRunNpmInstall(false)
.withFrontendGeneratedFolder(adapter.generatedTsFolder())
.withFrontendGeneratedFolder(
getGeneratedFrontendDirectory(adapter))
.withNodeVersion(adapter.nodeVersion())
.withNodeDownloadRoot(nodeDownloadRootURI)
.setNodeAutoUpdate(adapter.nodeAutoUpdate())
Expand Down Expand Up @@ -179,7 +182,8 @@ public static void prepareFrontend(PluginAdapterBase adapter)
private static File getJarFrontendResourcesFolder(
PluginAdapterBase adapter) {
return new File(
new File(adapter.frontendDirectory(), FrontendUtils.GENERATED),
new File(getFrontendDirectory(adapter),
FrontendUtils.GENERATED),
FrontendUtils.JAR_RESOURCES_FOLDER);
}

Expand Down Expand Up @@ -228,7 +232,7 @@ public static File propagateBuildInfo(PluginAdapterBase adapter) {
e);
}
buildInfo.put(FRONTEND_TOKEN,
adapter.frontendDirectory().getAbsolutePath());
getFrontendDirectory(adapter).getAbsolutePath());
buildInfo.put(CONNECT_JAVA_SOURCE_FOLDER_TOKEN,
adapter.javaSourceFolder().getAbsolutePath());
buildInfo.put(JAVA_RESOURCE_FOLDER_TOKEN,
Expand All @@ -238,7 +242,7 @@ public static File propagateBuildInfo(PluginAdapterBase adapter) {
buildInfo.put(CONNECT_OPEN_API_FILE_TOKEN,
adapter.openApiJsonFile().getAbsolutePath());
buildInfo.put(PROJECT_FRONTEND_GENERATED_DIR_TOKEN,
adapter.generatedTsFolder().getAbsolutePath());
getGeneratedFrontendDirectory(adapter).getAbsolutePath());

buildInfo.put(InitParameters.SERVLET_PARAMETER_ENABLE_PNPM,
adapter.pnpmEnable());
Expand Down Expand Up @@ -302,7 +306,7 @@ public static void runNodeUpdater(PluginAdapterBuild adapter)
try {
Options options = new com.vaadin.flow.server.frontend.Options(
lookup, adapter.npmFolder())
.withFrontendDirectory(adapter.frontendDirectory())
.withFrontendDirectory(getFrontendDirectory(adapter))
.withBuildDirectory(adapter.buildFolder())
.withRunNpmInstall(adapter.runNpmInstall())
.withWebpack(adapter.webpackOutputDirectory(),
Expand All @@ -320,7 +324,8 @@ public static void runNodeUpdater(PluginAdapterBuild adapter)
.withEnablePnpm(adapter.pnpmEnable())
.withEnableBun(adapter.bunEnable())
.useGlobalPnpm(adapter.useGlobalPnpm())
.withFrontendGeneratedFolder(adapter.generatedTsFolder())
.withFrontendGeneratedFolder(
getGeneratedFrontendDirectory(adapter))
.withHomeNodeExecRequired(adapter.requireHomeNodeExec())
.withNodeVersion(adapter.nodeVersion())
.withNodeDownloadRoot(nodeDownloadRootURI)
Expand Down Expand Up @@ -367,7 +372,7 @@ public static void runDevBuildNodeUpdater(PluginAdapterBuild adapter)
try {
Options options = new com.vaadin.flow.server.frontend.Options(
lookup, adapter.npmFolder()).withProductionMode(false)
.withFrontendDirectory(adapter.frontendDirectory())
.withFrontendDirectory(getFrontendDirectory(adapter))
.withBuildDirectory(adapter.buildFolder())
.withRunNpmInstall(adapter.runNpmInstall())
.withWebpack(adapter.webpackOutputDirectory(),
Expand All @@ -384,7 +389,8 @@ public static void runDevBuildNodeUpdater(PluginAdapterBuild adapter)
.withEnablePnpm(adapter.pnpmEnable())
.withEnableBun(adapter.bunEnable())
.useGlobalPnpm(adapter.useGlobalPnpm())
.withFrontendGeneratedFolder(adapter.generatedTsFolder())
.withFrontendGeneratedFolder(
getGeneratedFrontendDirectory(adapter))
.withHomeNodeExecRequired(adapter.requireHomeNodeExec())
.withNodeVersion(adapter.nodeVersion())
.withNodeDownloadRoot(nodeDownloadRootURI)
Expand All @@ -407,6 +413,45 @@ public static void runDevBuildNodeUpdater(PluginAdapterBuild adapter)
}
}

/**
* Get the legacy frontend folder if available and new folder doesn't exist.
*
* @param adapter
* PluginAdapterBase
* @return correct folder or legacy folder if not user defined
*/
private static File getFrontendDirectory(PluginAdapterBase adapter) {
File frontendDir = adapter.frontendDirectory();
if (!frontendDir.exists() && frontendDir.toPath()
.endsWith(DEFAULT_FRONTEND_DIR.substring(2))) {
File legacy = new File(adapter.npmFolder(), LEGACY_FRONTEND_DIR);
if (legacy.exists()) {
return legacy;
}
}
return frontendDir;
}

/**
* The generated folder should be under frontend folder and will be moved to
* the legacy package if not changed by the user.
*
* @param adapter
* PluginAdapterBase
* @return correct generated folder as child to frontend
*/
private static File getGeneratedFrontendDirectory(
PluginAdapterBase adapter) {
if (adapter.generatedTsFolder().toPath()
.startsWith(adapter.frontendDirectory().toPath())) {
// Possibly move frontend folder.
File frontendDirectory = getFrontendDirectory(adapter);
return new File(frontendDirectory, GENERATED);
}
// Return given generated folder
return adapter.generatedTsFolder();
}

/**
* Execute the frontend build with the wanted build system.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public void setup() throws IOException {
adapter = Mockito.mock(PluginAdapterBuild.class);
Mockito.when(adapter.npmFolder()).thenReturn(baseDir);
Mockito.when(adapter.generatedTsFolder())
.thenReturn(new File(baseDir, "frontend/generated"));
.thenReturn(new File(baseDir, "src/main/frontend/generated"));
Mockito.when(adapter.projectBaseDirectory())
.thenReturn(tmpDir.getRoot().toPath());
ClassFinder classFinder = Mockito.mock(ClassFinder.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.nio.file.Path;
import java.nio.file.Paths;

import com.vaadin.flow.internal.hilla.EndpointRequestUtil;
import com.vaadin.flow.server.frontend.BundleUtils;
import com.vaadin.flow.server.frontend.FileIOUtils;
import com.vaadin.flow.server.frontend.FrontendUtils;
Expand Down
Loading

0 comments on commit bb25955

Please sign in to comment.