Skip to content

Commit

Permalink
Improve version resolution (#5681)
Browse files Browse the repository at this point in the history
* Improve version resolution

- Support any syntax in NpmPackage version field.
- Split package.json in main one and app one
- User can pin versions by editing main package.json or with annotation
- Remove packages dependency when not used anymore
- Allow multiple version, but warn about it
- Add name and version fields to generate files to avoid warnings

* Fix checks for DevModeInitializer to point to correct folders

* We only need a parameter to disable updaters

* Always write application package file

* update main package file when exists

* Suggestions and other fixes

* Disable webpack liveReloading
  • Loading branch information
manolo authored and bogdanudrescu committed May 16, 2019
1 parent c019763 commit 049a2f2
Show file tree
Hide file tree
Showing 20 changed files with 475 additions and 365 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,6 @@
*/
package com.vaadin.flow.plugin.maven;

import static com.vaadin.flow.server.Constants.PACKAGE_JSON;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.FLOW_NPM_PACKAGE_NAME;
import static com.vaadin.flow.server.frontend.FrontendUtils.IMPORTS_NAME;
import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES;
import static com.vaadin.flow.server.frontend.FrontendUtils.TARGET;
import static com.vaadin.flow.server.frontend.FrontendUtils.WEBPACK_CONFIG;
import static com.vaadin.flow.server.frontend.FrontendUtils.WEBPACK_PREFIX_ALIAS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.File;
import java.io.IOException;
import java.net.URL;
Expand Down Expand Up @@ -60,6 +49,17 @@
import elemental.json.Json;
import elemental.json.JsonObject;

import static com.vaadin.flow.server.Constants.PACKAGE_JSON;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.FLOW_NPM_PACKAGE_NAME;
import static com.vaadin.flow.server.frontend.FrontendUtils.IMPORTS_NAME;
import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES;
import static com.vaadin.flow.server.frontend.FrontendUtils.WEBPACK_CONFIG;
import static com.vaadin.flow.server.frontend.FrontendUtils.WEBPACK_PREFIX_ALIAS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class NodeBuildFrontendMojoTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
Expand All @@ -68,7 +68,8 @@ public class NodeBuildFrontendMojoTest {
private File generatedFolder;
private File nodeModulesPath;
private File flowPackagPath;
private String packageJson;
private String mainPackage;
private String appPackage;
private String webpackConfig;

private final NodeBuildFrontendMojo mojo = new NodeBuildFrontendMojo();
Expand All @@ -79,15 +80,16 @@ public void setup() throws Exception {
Mockito.when(project.getRuntimeClasspathElements())
.thenReturn(getClassPath());

File tmpRoot = temporaryFolder.getRoot();
generatedFolder = new File(tmpRoot, TARGET);
File npmFolder = temporaryFolder.getRoot();
generatedFolder = new File(npmFolder, DEFAULT_GENERATED_DIR);
importsFile = new File(generatedFolder, IMPORTS_NAME);
nodeModulesPath = new File(tmpRoot, NODE_MODULES);
nodeModulesPath = new File(npmFolder, NODE_MODULES);
flowPackagPath = new File(nodeModulesPath, FLOW_NPM_PACKAGE_NAME);
File frontendDirectory = new File(tmpRoot, DEFAULT_FRONTEND_DIR);
File frontendDirectory = new File(npmFolder, DEFAULT_FRONTEND_DIR);

packageJson = new File(tmpRoot, PACKAGE_JSON).getAbsolutePath();
webpackConfig = new File(tmpRoot, WEBPACK_CONFIG).getAbsolutePath();
mainPackage = new File(npmFolder, PACKAGE_JSON).getAbsolutePath();
appPackage = new File(generatedFolder, PACKAGE_JSON).getAbsolutePath();
webpackConfig = new File(npmFolder, WEBPACK_CONFIG).getAbsolutePath();

ReflectionUtils.setVariableValueInObject(mojo, "project", project);
ReflectionUtils.setVariableValueInObject(mojo, "generatedFolder",
Expand All @@ -97,23 +99,26 @@ public void setup() throws Exception {
ReflectionUtils.setVariableValueInObject(mojo,
"generateEmbeddableWebComponents", false);
ReflectionUtils.setVariableValueInObject(mojo, "convertHtml", true);
ReflectionUtils.setVariableValueInObject(mojo, "npmFolder", tmpRoot);
ReflectionUtils.setVariableValueInObject(mojo, "npmFolder", npmFolder);
ReflectionUtils.setVariableValueInObject(mojo, "generateBundle", false);
ReflectionUtils.setVariableValueInObject(mojo, "runNpmInstall", false);

Assert.assertTrue(flowPackagPath.mkdirs());
flowPackagPath.mkdirs();
generatedFolder.mkdirs();

setProject(mojo, "war", "war_output");

// Install all imports used in the tests on node_modules so as we don't
// need to run `npm install`
createExpectedImports(frontendDirectory, nodeModulesPath);
FileUtils.fileWrite(packageJson, "UTF-8", "{}");
FileUtils.fileWrite(mainPackage, "UTF-8", "{}");
FileUtils.fileWrite(appPackage, "UTF-8", "{}");
}

@After
public void teardown() {
FileUtils.fileDelete(packageJson);
FileUtils.fileDelete(mainPackage);
FileUtils.fileDelete(appPackage);
FileUtils.fileDelete(webpackConfig);
}

Expand Down Expand Up @@ -221,49 +226,23 @@ public void should_AddRemove_Imports() throws Exception {

@Test
public void mavenGoal_when_packageJsonExists() throws Exception {
FileUtils.fileWrite(appPackage, "{\"dependencies\":{\"foo\":\"bar\"}}");

FileUtils.fileWrite(packageJson, "{}");
long tsPackage1 = FileUtils.getFile(packageJson).lastModified();

// need to sleep because timestamp is in seconds
sleep(1000);
mojo.execute();
long tsPackage2 = FileUtils.getFile(packageJson).lastModified();

sleep(1000);
mojo.execute();
long tsPackage3 = FileUtils.getFile(packageJson).lastModified();

Assert.assertTrue(tsPackage1 < tsPackage2);
Assert.assertEquals(tsPackage2, tsPackage3);

assertPackageJsonContent();
}

private void assertPackageJsonContent() throws IOException {
JsonObject packageJsonObject = getPackageJson(packageJson);

JsonObject packageJsonObject = getPackageJson(appPackage);
JsonObject dependencies = packageJsonObject.getObject("dependencies");

Assert.assertTrue("Missing @vaadin/vaadin-button package",
dependencies.hasKey("@vaadin/vaadin-button"));
Assert.assertTrue("Missing @webcomponents/webcomponentsjs package",
dependencies.hasKey("@webcomponents/webcomponentsjs"));
assertContainsPackage(dependencies,
"@vaadin/vaadin-button",
"@vaadin/vaadin-element-mixin",
"@vaadin/vaadin-core-shrinkwrap");

JsonObject devDependencies = packageJsonObject
.getObject("devDependencies");
Assert.assertFalse("Has foo", dependencies.hasKey("foo"));
}

Assert.assertTrue("Missing webpack dev package",
devDependencies.hasKey("webpack"));
Assert.assertTrue("Missing webpack-cli dev package",
devDependencies.hasKey("webpack-cli"));
Assert.assertTrue("Missing webpack-dev-server dev package",
devDependencies.hasKey("webpack-dev-server"));
Assert.assertTrue(
"Missing webpack-babel-multi-target-plugin dev package",
devDependencies.hasKey("webpack-babel-multi-target-plugin"));
Assert.assertTrue("Missing copy-webpack-plugin dev package",
devDependencies.hasKey("copy-webpack-plugin"));
static void assertContainsPackage(JsonObject dependencies, String... packages) {
Arrays.asList(packages)
.forEach(dep -> Assert.assertTrue("Missing " + dep, dependencies.hasKey(dep)));
}

private void assertContainsImports(boolean contains, String... imports)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import elemental.json.JsonObject;

import static com.vaadin.flow.plugin.maven.NodeBuildFrontendMojoTest.assertContainsPackage;
import static com.vaadin.flow.plugin.maven.NodeBuildFrontendMojoTest.getPackageJson;
import static com.vaadin.flow.plugin.maven.NodeBuildFrontendMojoTest.setProject;
import static com.vaadin.flow.server.Constants.PACKAGE_JSON;
Expand Down Expand Up @@ -152,27 +153,29 @@ public void assertWebpackContent_NotWarNotJar() throws Exception {
mojo.execute();
}

@Test
public void should_keepDependencies_when_packageJsonExists() throws Exception {
FileUtils.fileWrite(packageJson, "{\"dependencies\":{\"foo\":\"bar\"}}");
mojo.execute();
assertPackageJsonContent();

JsonObject packageJsonObject = getPackageJson(packageJson);
assertContainsPackage(packageJsonObject.getObject("dependencies"), "foo");
}

private void assertPackageJsonContent() throws IOException {
JsonObject packageJsonObject = getPackageJson(packageJson);
JsonObject dependencies = packageJsonObject.getObject("dependencies");

Assert.assertTrue("Missing @webcomponents/webcomponentsjs package",
dependencies.hasKey("@webcomponents/webcomponentsjs"));
Assert.assertTrue("Missing @polymer/polymer package",
dependencies.hasKey("@polymer/polymer"));

JsonObject devDependencies = packageJsonObject.getObject("devDependencies");

Assert.assertTrue("Missing webpack dev package",
devDependencies.hasKey("webpack"));
Assert.assertTrue("Missing webpack-cli dev package",
devDependencies.hasKey("webpack-cli"));
Assert.assertTrue("Missing webpack-dev-server dev package",
devDependencies.hasKey("webpack-dev-server"));
Assert.assertTrue("Missing webpack-babel-multi-target-plugin dev package",
devDependencies.hasKey("webpack-babel-multi-target-plugin"));
Assert.assertTrue("Missing copy-webpack-plugin dev package",
devDependencies.hasKey("copy-webpack-plugin"));

assertContainsPackage(packageJsonObject.getObject("dependencies"),
"@webcomponents/webcomponentsjs",
"@polymer/polymer");

assertContainsPackage(packageJsonObject.getObject("devDependencies"),
"webpack",
"webpack-cli",
"webpack-dev-server",
"webpack-babel-multi-target-plugin",
"copy-webpack-plugin");
}


Expand Down
14 changes: 2 additions & 12 deletions flow-server/src/main/java/com/vaadin/flow/server/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ public final class Constants implements Serializable {
* Configuration name for the parameter that indicates the tcp port of a webpack-dev-server
* already running. This property is automatically defined when
* {@link DevModeHandler} starts the webpack server. If you have your own
* server already running, define this property and {@link DevModeHandler}
* will re-use that server.
* server already running, define this property, then {@link DevModeHandler}
* will re-use that server and will disable updaters.
*/
public static final String SERVLET_PARAMETER_DEVMODE_WEBPACK_RUNNING_PORT = "devmode.webpack.running-port";

Expand Down Expand Up @@ -187,16 +187,6 @@ public final class Constants implements Serializable {
*/
public static final String SERVLET_PARAMETER_DEVMODE_WEBPACK_OPTIONS = "devmode.webpack.options";

/**
* Configuration name which disables the node imports updater.
*/
public static final String SERVLET_PARAMETER_DEVMODE_SKIP_UPDATE_IMPORTS = "devmode.skip.update-imports";

/**
* Configuration name which disables the node dependencies updater.
*/
public static final String SERVLET_PARAMETER_DEVMODE_SKIP_UPDATE_NPM = "devmode.skip.update-npm-dependencies";

private Constants() {
// prevent instantiation constants class only
}
Expand Down
Loading

0 comments on commit 049a2f2

Please sign in to comment.