Skip to content

Commit

Permalink
feat: add file system router plugin for vite (#18878)
Browse files Browse the repository at this point in the history
* feat: add file system router plugin for vite

Adds vitePluginFileSystemRouter to Vite plugins by default when React and Hilla is in use.

Fixes: #18832

* chore: removed dep from default vite packages

Hilla packages adds the dep in dependencies already.

* test: added tests
  • Loading branch information
tltv committed Mar 4, 2024
1 parent 0f7bf62 commit 260fa5f
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public class TaskUpdateVite implements FallibleCommand, Serializable {
getSimplifiedTemplate("vite.config-react.ts"),
getSimplifiedTemplate("vite.config-react-swc.ts") };

static final String FILE_SYSTEM_ROUTER_DEPENDENCY = "@vaadin/hilla-file-router/vite-plugin.js";

TaskUpdateVite(Options options, Set<String> webComponentTags) {
this.options = options;
this.webComponentTags = webComponentTags;
Expand Down Expand Up @@ -126,11 +128,27 @@ private void createGeneratedConfig() throws IOException {
webComponentTags == null || webComponentTags.isEmpty()
? ""
: String.join(";", webComponentTags));
template = updateFileSystemRouterVitePlugin(template);

FileIOUtils.writeIfChanged(generatedConfigFile, template);
log().debug("Created vite generated configuration file: '{}'",
generatedConfigFile);
}

private String updateFileSystemRouterVitePlugin(String template) {
if (options.isReactEnabled() && FrontendUtils.isHillaUsed(
options.getFrontendDirectory(), options.getClassFinder())) {
return template
.replace("//#vitePluginFileSystemRouterImport#",
"import vitePluginFileSystemRouter from '"
+ FILE_SYSTEM_ROUTER_DEPENDENCY + "';")
.replace("//#vitePluginFileSystemRouter#",
", vitePluginFileSystemRouter()");
}
return template.replace("//#vitePluginFileSystemRouterImport#", "")
.replace("//#vitePluginFileSystemRouter#", "");
}

private Logger log() {
return LoggerFactory.getLogger(this.getClass());
}
Expand Down
3 changes: 3 additions & 0 deletions flow-server/src/main/resources/vite.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { createRequire } from 'module';
import { visualizer } from 'rollup-plugin-visualizer';
import reactPlugin from '@vitejs/plugin-react';

//#vitePluginFileSystemRouterImport#

// Make `require` compatible with ES modules
const require = createRequire(import.meta.url);

Expand Down Expand Up @@ -846,6 +848,7 @@ export const vaadinConfig: UserConfigFn = (env) => {
typescript: true
}),
productionMode && visualizer({ brotliSize: true, filename: bundleSizeFile })
//#vitePluginFileSystemRouter#
]
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.MockedStatic;
import org.mockito.Mockito;

import com.vaadin.flow.di.Lookup;
import com.vaadin.flow.server.PwaConfiguration;
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
import com.vaadin.tests.util.MockOptions;

import elemental.json.Json;
import elemental.json.JsonObject;
Expand All @@ -26,10 +29,20 @@ public class TaskUpdateViteTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

private ClassFinder finder;

private Options options;

@Before
public void setUp() throws IOException {
finder = Mockito.spy(new ClassFinder.DefaultClassFinder(
this.getClass().getClassLoader()));
options = new MockOptions(finder, temporaryFolder.getRoot())
.withBuildDirectory("build");
}

@Test
public void generatedTemplate_correctSettingsPath() throws IOException {
Options options = new Options(Mockito.mock(Lookup.class),
temporaryFolder.getRoot()).withBuildDirectory("build");
TaskUpdateVite task = new TaskUpdateVite(options, null);
task.execute();

Expand All @@ -49,8 +62,6 @@ public void configFileExists_fileNotOverwritten() throws IOException {
FrontendUtils.VITE_CONFIG);
final String importString = "Hello Fake configuration";
FileUtils.write(configFile, importString, StandardCharsets.UTF_8);
Options options = new Options(Mockito.mock(Lookup.class),
temporaryFolder.getRoot()).withBuildDirectory("build");

new TaskUpdateVite(options, null).execute();

Expand All @@ -70,9 +81,6 @@ public void generatedConfigFileExists_alwaysOverwritten()
FileUtils.write(generatedConfigFile, importString,
StandardCharsets.UTF_8);

Options options = new Options(Mockito.mock(Lookup.class),
temporaryFolder.getRoot()).withBuildDirectory("build");

new TaskUpdateVite(options, null).execute();

String template = IOUtils.toString(generatedConfigFile.toURI(),
Expand All @@ -85,9 +93,6 @@ public void generatedConfigFileExists_alwaysOverwritten()
@Test
public void usedSettings_matchThoseCreatedToSettingsFile()
throws IOException {
Options options = new Options(Mockito.mock(Lookup.class),
temporaryFolder.getRoot()).withBuildDirectory("build");

TaskUpdateVite task = new TaskUpdateVite(options, null);
task.execute();

Expand Down Expand Up @@ -122,4 +127,49 @@ public void usedSettings_matchThoseCreatedToSettingsFile()
+ "that are not generated in settings file.",
faulty.toString().isEmpty());
}

@Test
public void generatedTemplate_reactAndHillaUsed_correctFileRouterImport()
throws IOException {
TaskUpdateVite task = new TaskUpdateVite(options.withReact(true), null);
try (MockedStatic<FrontendUtils> util = Mockito
.mockStatic(FrontendUtils.class, Mockito.CALLS_REAL_METHODS)) {
util.when(() -> FrontendUtils.isHillaUsed(Mockito.any(),
Mockito.any())).thenReturn(true);
task.execute();
}

File configFile = new File(temporaryFolder.getRoot(),
FrontendUtils.VITE_GENERATED_CONFIG);

String template = IOUtils.toString(configFile.toURI(),
StandardCharsets.UTF_8);

Assert.assertTrue("vitePluginFileSystemRouter should be imported.",
template.contains("import vitePluginFileSystemRouter from '"
+ TaskUpdateVite.FILE_SYSTEM_ROUTER_DEPENDENCY + "';"));
Assert.assertTrue("vitePluginFileSystemRouter() should be used.",
template.contains(", vitePluginFileSystemRouter()"));
}

@Test
public void generatedTemplate_reactDisabled_correctFileRouterImport()
throws IOException {
TaskUpdateVite task = new TaskUpdateVite(options.withReact(false),
null);
task.execute();

File configFile = new File(temporaryFolder.getRoot(),
FrontendUtils.VITE_GENERATED_CONFIG);

String template = IOUtils.toString(configFile.toURI(),
StandardCharsets.UTF_8);

Assert.assertFalse("vitePluginFileSystemRouter should not be imported.",
template.contains("import vitePluginFileSystemRouter from '"
+ TaskUpdateVite.FILE_SYSTEM_ROUTER_DEPENDENCY + "';"));
Assert.assertFalse("vitePluginFileSystemRouter() should be used.",
template.contains(", vitePluginFileSystemRouter()"));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"dependencies": {
"@vaadin/hilla-react-auth": "24.4.0-alpha2",
"@vaadin/hilla-react-crud": "24.4.0-alpha2",
"@vaadin/hilla-react-form": "24.4.0-alpha2"
"@vaadin/hilla-react-form": "24.4.0-alpha2",
"@vaadin/hilla-file-router": "24.4.0-alpha2"
},
"devDependencies": {
"react-dev-dependency": "1.0.0"
Expand Down

0 comments on commit 260fa5f

Please sign in to comment.