新的Vaadin 14应用程序无法运行,错误提示为“无法确定'node'工具”。缺少Node.js和npm工具。

12

我使用 起步页 来创建一个新的 Vaadin 14 应用程序,在选择 Plain Java Servlet 选项后。

网页成功地下载了一个 .zip 文件,我解压缩并在 IntelliJ Ultimate Edition 2019.2 版本中打开它。我等待了几分钟,Maven 完成了它的工作,下载并重新配置项目。最终,我进入 IntelliJ 中的 Maven 面板,并运行了 Lifecycle 中的 cleaninstall 项。

我在控制台上收到了以下错误消息。

[ERROR] Failed to execute goal com.vaadin:vaadin-maven-plugin:14.0.0:prepare-frontend (default) on project acme: Execution default of goal com.vaadin:vaadin-maven-plugin:14.0.0:prepare-frontend failed: 
[ERROR] 
[ERROR] ======================================================================================================
[ERROR] Failed to determine 'node' tool.
[ERROR] Please install it either:
[ERROR]   - by following the https://nodejs.org/en/download/ guide to install it globally
[ERROR]   - or by running the frontend-maven-plugin goal to install it in this project:
[ERROR]   $ mvn com.github.eirslett:frontend-maven-plugin:1.7.6:install-node-and-npm -DnodeVersion="v10.16.0" 
[ERROR] ======================================================================================================

查看Vaadin论坛上的讨论.

我提交了Ticket # 6262 配置Maven以自动安装Node.js & npm,建议Vaadin团队在要求和省略Node.js & npm方面存在问题。


3
需要使用Node和Node依赖项真是太麻烦了。1:我们的开发机器没有直接访问互联网的权限。2:即使设置HTTP_PROXY,npm也无法正常工作。3:我们使用Vaadin只是因为我们需要远离Node.js的麻烦,但现在启动起始应用程序却变成了一团糟(哈哈)。已经花费了1.5天的时间,但仍然无法解决问题。 - SashikaXP
请注意,在 Vaadin 14.2 中,如果在系统中找不到 Node,则 Maven 插件已更改为自动在项目中安装它。 - Tatu Lund
1
@TatuLund 在我的回答中已经注意到了。感谢您提供的信息,以及在Vaadin上所做的所有工作。 - Basil Bourque
7个回答

20

更新:14.2版本不存在问题

Vaadin 14.2和16已经更改,现在在Maven驱动的项目中自动包含必要的npm工具,无需手动安装Node.jsnpm

引用这篇博客文章

自动安装Node.js

从14.2和16版本开始,Node.js安装(包括npm)会自动发生。它安装到主文件夹内的.vaadin文件夹中,并在所有Vaadin项目中重复使用。与以前一样,Node仅用于构建前端部分;在部署生产后不会运行!

并进一步改进:pnpm代替npm

前端依赖管理,只需要用pnpm - pnpm 在幕后,自14.0版本以来,npm已被用于管理前端依赖项。现在,我们增加了对pnpm的支持,它引入了以下好处: 1.与本地计算机和CI系统上的npm相比,构建时间更短,因为pnpm仅下载包一次并从本地缓存中重复使用。 2.在更新项目中的Vaadin版本时,无需删除package.json、锁定文件或node_modules文件夹。 在14.2版本中,默认仍使用npm,但我们鼓励您测试pnpm并给我们反馈。尝试pnpm很容易:只需使用配置属性或Maven插件配置启用它即可,无需迁移。您可以在这里了解更多关于pnpm的信息。Vaadin 16将默认使用pnpm。 我已经验证了这个功能很好。现在我已经手动从我的Mac中删除了Node.js/npm安装。

tl;dr

Vaadin 14团队希望您在计算机上安装Node.jsnpm工具。

作为替代方案,Vaadin 14与Node.js / npm似乎可以通过frontend-maven-plugin工具在您的项目中自动安装(而不是全局安装在您的计算机上)。 您可以在Maven POM文件中指定。请查看下面的XML片段以获取有关您的POM的详细信息。

如果您更喜欢在计算机上全局安装Mode / npm,请务必阅读Tom Novosad的other Answer

Details

截至Vaadin 14,Vaadin团队正在切换

…作为他们从Polymer 2向Polymer 3过渡的一部分。

详见博客文章Bower and npm in Vaadin 14+

希望作为Vaadin-on-Java用户,我们不需要关心这些底层技术细节......但有一件事:不幸的是,默认情况下,npmNode.js工具是必需的,但未绑定在您的Vaadin项目中。
你有两个解决方案:
  • 全局安装工具。
  • 在项目中安装。
我更喜欢后者。而且我更喜欢Maven自动在我的项目中安装它们,这样我就不用手动进行太多的维护。
注意:我不知道我的每个项目解决方案的限制或影响。我几乎不知道node/npm的目的或性质,并不知道Vaadin如何使用它们。所以请自行决定是否使用此解决方案。我只能说,它对我来说似乎是有效的。
frontend-maven-plugin添加到您的项目中 frontend-maven-plugin工具可被Maven用于下载并安装Node.js与npm到您的Vaadin项目中。
打开Vaadin项目中的Maven POM文件。
将以下块添加到该POM的<build> <defaultGoal>jetty:run</defaultGoal> <plugins>元素内。
    <plugin>
        <groupId>com.github.eirslett</groupId>
        <artifactId>frontend-maven-plugin</artifactId>
        <!-- Use the latest released version:
        https://repo1.maven.org/maven2/com/github/eirslett/frontend-maven-plugin/ -->
        <version>1.8.0</version>

        <executions>
            <execution>
                <!-- optional: you don't really need execution ids, but it looks nice in your build log. -->
                <id>install node and npm</id>
                <goals>
                    <goal>install-node-and-npm</goal>
                </goals>
                <!-- optional: default phase is "generate-resources" -->
                <phase>generate-resources</phase>
            </execution>
        </executions>
        <configuration>
            <nodeVersion>v10.16.3</nodeVersion>

            <!-- optional: with node version greater than 4.0.0 will use npm provided by node distribution -->
            <!--                    <npmVersion>2.15.9</npmVersion>-->

            <!-- optional: where to download node and npm from. Defaults to https://nodejs.org/dist/ -->
            <!--                    <downloadRoot>http://myproxy.example.org/nodejs/</downloadRoot>-->
        </configuration>
    </plugin>

当然,您可以调整那段代码以使用最新的版本号。请查看Node.js页面以获取最新版本号。
请注意,我们将npm项注释掉了,因为该工具已捆绑在最新版本的Node.js中。
剩下的步骤:
1. 在IntelliJ中的Maven面板中运行名为cleaninstallLifecycle项目。等待一会儿,因为会下载和配置更多的项目。(在您的控制台历史记录中注意到"Installing node version v10.16.3")。 2. 在相同的面板中,在Plugins > jetty部分中,运行jetty:run项。稍等片刻,因为Jetty服务器启动以运行您的Vaadin应用程序。
在控制台上,您应该会看到类似于这样的内容(所有Vaadin版本都有一个神秘的Quiet Time警告):
[INFO] Started Jetty Server
[INFO] Using Non-Native Java sun.nio.fs.PollingWatchService
[WARNING] Quiet Time is too low for non-native WatchService [sun.nio.fs.PollingWatchService]: 1000 < 5000 ms (defaulting to 5000 ms)
  1. 在浏览器中输入: http://localhost:8080/ ,即可看到“Click Me” 按钮,表示您的应用程序成功运行。

这个解决方案来自 frontend-maven-plugin 的项目页面。请注意,那里的示例 POM 片段不正确,并未将 <execution> 标签包装在复数的 <executions> 标签内。我已经在那里提交了ticket # 838

您可能想要在 Vaadin 论坛中关注 this discussion

供您参考,这是一个完整的 POM 文件,可与您的进行比较。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>work.basil.example</groupId>
    <artifactId>acme</artifactId>
    <name>acme</name>
    <version>2.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>13</maven.compiler.source>
        <maven.compiler.target>13</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <failOnMissingWebXml>false</failOnMissingWebXml>

        <vaadin.version>14.0.5</vaadin.version>

        <drivers.downloader.phase>pre-integration-test</drivers.downloader.phase>
    </properties>

    <repositories>
        <repository>
            <id>central</id>
            <url>https://repo1.maven.org/maven2/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <!-- Repository used by many Vaadin add-ons -->
        <repository>
            <id>Vaadin Directory</id>
            <url>https://maven.vaadin.com/vaadin-addons</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>central</id>
            <url>https://repo1.maven.org/maven2/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>
                <type>pom</type>
                <scope>import</scope>
                <version>${vaadin.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <!-- Replace artifactId with vaadin-core to use only free components -->
            <artifactId>vaadin</artifactId>
            <exclusions>
                <!-- Webjars are only needed when running in Vaadin 13 compatibility mode -->
                <exclusion>
                    <groupId>com.vaadin.webjar</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.insites</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.polymer</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.polymerelements</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.vaadin</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.webcomponents</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Added to provide logging output as Vaadin uses -->
        <!-- the unbound SLF4J no-operation (NOP) logger implementation -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-testbench</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <defaultGoal>jetty:run</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
            </plugin>
            <!-- Jetty plugin for easy testing without a server -->
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.19.v20190610</version>
                <configuration>
                    <!-- If using IntelliJ IDEA with autocompilation, this
                    might cause lots of unnecessary compilations in the
                    background.-->
                    <scanIntervalSeconds>2</scanIntervalSeconds>
                    <!-- Use war output directory to get the webpack files -->
                    <webAppConfig>
                        <allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
                    </webAppConfig>
                </configuration>
            </plugin>

            <!--
                Take care of synchronizing java dependencies and imports in
                package.json and main.js files.
                It also creates webpack.config.js if not exists yet.
            -->
            <plugin>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-maven-plugin</artifactId>
                <version>${vaadin.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-frontend</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>com.github.eirslett</groupId>
                <artifactId>frontend-maven-plugin</artifactId>
                <!-- Use the latest released version:
                https://repo1.maven.org/maven2/com/github/eirslett/frontend-maven-plugin/ -->
                <version>1.8.0</version>

                <executions>
                    <execution>
                        <!-- optional: you don't really need execution ids, but it looks nice in your build log. -->
                        <id>install node and npm</id>
                        <goals>
                            <goal>install-node-and-npm</goal>
                        </goals>
                        <!-- optional: default phase is "generate-resources" -->
                        <phase>generate-resources</phase>
                    </execution>
                </executions>
                <configuration>
                    <nodeVersion>v10.16.3</nodeVersion>

                    <!-- optional: with node version greater than 4.0.0 will use npm provided by node distribution -->
                    <!--                    <npmVersion>2.15.9</npmVersion>-->

                    <!-- optional: where to download node and npm from. Defaults to https://nodejs.org/dist/ -->
                    <!--                    <downloadRoot>http://myproxy.example.org/nodejs/</downloadRoot>-->
                </configuration>
            </plugin>

        </plugins>
    </build>

    <profiles>
        <profile>
            <!-- Production mode is activated using -Pproduction -->
            <id>production</id>
            <properties>
                <vaadin.productionMode>true</vaadin.productionMode>
            </properties>

            <dependencies>
                <dependency>
                    <groupId>com.vaadin</groupId>
                    <artifactId>flow-server-production-mode</artifactId>
                </dependency>
            </dependencies>

            <build>
                <plugins>
                    <plugin>
                        <groupId>com.vaadin</groupId>
                        <artifactId>vaadin-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>build-frontend</goal>
                                </goals>
                                <phase>compile</phase>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>integration-tests</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.eclipse.jetty</groupId>
                        <artifactId>jetty-maven-plugin</artifactId>
                        <version>9.4.19.v20190610</version>
                        <configuration>
                            <scanIntervalSeconds>0</scanIntervalSeconds>
                            <stopPort>8081</stopPort>
                            <stopWait>5</stopWait>
                            <stopKey>${project.artifactId}</stopKey>
                        </configuration>
                        <executions>
                            <execution>
                                <id>start-jetty</id>
                                <phase>pre-integration-test</phase>
                                <goals>
                                    <goal>deploy-war</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>stop-jetty</id>
                                <phase>post-integration-test</phase>
                                <goals>
                                    <goal>stop</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>

                    <!-- Runs the integration tests (*IT) after the server is started -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <version>3.0.0-M3</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <trimStackTrace>false</trimStackTrace>
                            <enableAssertions>true</enableAssertions>
                            <systemPropertyVariables>
                                <!-- Pass location of downloaded webdrivers to the tests -->
                                <webdriver.chrome.driver>${webdriver.chrome.driver}</webdriver.chrome.driver>
                            </systemPropertyVariables>
                        </configuration>
                    </plugin>

                    <plugin>
                        <groupId>com.lazerycode.selenium</groupId>
                        <artifactId>driver-binary-downloader-maven-plugin</artifactId>
                        <version>1.0.17</version>
                        <configuration>
                            <onlyGetDriversForHostOperatingSystem>true
                            </onlyGetDriversForHostOperatingSystem>
                            <rootStandaloneServerDirectory>
                                ${project.basedir}/drivers/driver
                            </rootStandaloneServerDirectory>
                            <downloadedZipFileDirectory>
                                ${project.basedir}/drivers/driver_zips
                            </downloadedZipFileDirectory>
                            <customRepositoryMap>
                                ${project.basedir}/drivers.xml
                            </customRepositoryMap>
                        </configuration>
                        <executions>
                            <execution>
                                <!-- use phase "none" to skip download step -->
                                <phase>${drivers.downloader.phase}</phase>
                                <goals>
                                    <goal>selenium</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

请注意,Vaadin并不是“转而使用Node.js和npm”,它正在从polymer2 / bower / webjars迁移到polymer3 / npm。 - rmuller
忘记切换和迁移的措辞,引入另一个词会让人困惑,是我的错。最重要的变化是polymer2 -> 3。 - rmuller
1
@rmuller,我进一步列举了这个库的技术细节,并提供了相关背景信息的链接。我很满意最终结果,再次感谢您。 - Basil Bourque
我曾经让Vaadin使用我全局安装的node.js/npm,直到它对我的同事不起作用。现在使用本地节点与“frontend-maven-plugin”以及您在此处编写的完全相同的插件定义。现在对我和同事都非常好用。而且我不再在安装期间收到烦人的日志消息“failed to execute path-to-global-npm/npm.cmd -v”。感谢Basil的回答。 - kscherrer
关于你提到的在每个项目中安装Node的注意事项,我想说一句。我的一个专注于前端的同事告诉我这实际上是首选做法。Node本身不会占用太多空间,并且你不需要要求其他开发人员自行安装它。在使用本地和全局两种方式后,我现在总是选择本地安装。 - kscherrer
显示剩余2条评论

3
方法`FrontendUtils::getNpmExecutable(String baseDir)`存在问题,该方法位于flow-server.jar中。此方法尝试在$baseDir(即prepare-frontend目标的项目根文件夹)中查找`node/node_modules/npm/bin/npm-cli.js`。当该路径不存在时,代码继续执行“where/which npm.cmd”以获取“npm.cmd”的绝对路径。在我的情况下,已经全局安装了NodeJS,返回了正确的路径。随后,代码继续尝试执行“path-to-npm.cmd\npm.cmd -v”,以确保“npm.cmd”存在并可运行。这里出现了一个问题:在方法`FrontEndUtils::createProcessBuilder(List command)`中,在某些情况下,程序代码将环境变量“PATH”设置为npm.cmd的路径(因为ProcssBuilder.environment()返回不包含“PATH”变量的map)。接下来,当尝试执行命令'path-to-npm\npm.cmd -v'时,进程的退出值为1,并且stderr不为空,因为在“npm.cmd”中的其他内容之前调用了“chcp”命令(可能是SETLOCAL命令),但是由于现在“chcp”不在PATH中。代码评估这些条件(退出代码1,stderr非空)为npm.cmd执行错误,并打印"Failed to determine 'npm.cmd' tool."的消息。发生这种情况时,我使用Windows 10,Vaadin Flow 14.0.1和全局安装的NodeJS。当运行带有应用程序的tomcat服务器时,也会出现相同的问题,因为$baseDir变量包含路径到tomcat bin目录。解决方法是在项目根目录下创建NodeJS目录的符号链接,并且如果应用程序运行在Tomcat上,则还需将NodeJS链接到Tomcat的bin目录中。

这对我很有效。我宁愿拥有一个全局的node安装,而不是每个vaadin项目都有一个。我使用的命令,在管理员提示下,是“mklink /d node c:\nodejs”,显然要调整路径。这是在vaadin项目内运行的。 - fleed

1

当我在测试新的Vaadin 14时,出现了这个问题。 我按照说明安装了node,但是我是在之前打开的Idea中进行操作的,那时我在做另一个项目(不同于这个)。当我重启Idea后,问题就解决了。

enter image description here

enter image description here


0

在安装了Node之后,我编译Vaadin应用程序时遇到了同样的问题。
需要重新启动电脑才能定位Node并成功运行。


0

更确切地说,有一种情况是在插件运行时可以在日志中找到真正的错误: 命令 '[C:\ Program Files \ nodejs \ npm.cmd,-v]' 退出代码为'1'

但是,如果您从提示符中运行相同的命令,则会发现命令没有问题并且退出代码正确。

正如某些人提到的那样,问题在于Windows尝试运行“chcp”,但它不在PATH上(由maven插件操作)。这在我的情况下发生,因为我在注册表中修改了以UTF编码始终运行cmd。在Windows中,这是通过在任何批处理或命令文件(如npm.cmd)之前执行“chcp 65001”来实现的... 我的简单解决方案是将chcp.com从System32目录复制到nodejs目录中...


把 chcp 复制到 nodejs 对我来说不起作用。不幸的是,我不得不使用 mklink 命令在 Vaadin 项目中创建一个符号链接到 nodejs 安装文件夹,就像 Tom Novosad 的回答中所描述的那样。 - fleed

0

-3

我这里也差不多。 Win 10,JDK 11.0.2,全局安装了node 10.16.2

mvn 的结果是

[ERROR] Failed to determine 'npm.cmd' tool. 
[ERROR] Please install it either:
[ERROR] - by following the https://nodejs.org/en/download/ guide to install it globally
[ERROR] - or by running the frontend-maven-plugin goal to install it in this project:
[ERROR] $ mvn com.github.eirslett:frontend-maven-plugin:1.7.6:install-node-and-npm -DnodeVersion="v10.16.0"

所以...第一条建议全局安装失败了,第二条建议可以。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接