使用 Vue:NW.js 构建桌面应用程序

2025-05-25

使用 Vue:NW.js 构建桌面应用程序

之前我写过两篇关于使用 Vue 框架构建桌面应用的文章:一篇是关于Vuido 库的,另一篇是关于Electron的。之前有人留言说想写一篇关于NW.js的文章,我答应了……现在终于写完了!迟到总比不到好😅

NW.js(原名 node-webkit)是一个使用 HTML、CSS 和 JavaScript 构建桌面应用程序的框架。它基于ChromiumNode.js。NW.js允许您直接从浏览器调用 Node.js 代码和模块,并在应用中使用 Web 技术。此外,您可以轻松地将 Web 应用程序打包为原生应用程序。

⚛️ 与 Electron 的区别

Electron 和 NW.js 有很多共同的特性:它们都基于 Chromium 和 Node.js 构建,并使用 HTML、CSS 和 JS 来构建桌面应用。但它们也有一些显著的区别:

  • 在 NW.js 中,应用程序的主入口点是网页或 JS 脚本。您可以通过package.json main属性指定入口点。在 Electron 中,入口点是 JavaScript 脚本。您无需直接提供 URL,而是手动创建浏览器窗口并使用 API 加载 HTML 文件。
  • 在构建过程中,NW.js 构建所有 Chromium;Electron 使用libchromiumcontent访问 Chromium 的内容 API
  • NW.js内置支持将源代码编译为受保护的二进制文件。Electron 使用asar打包其应用程序,其中包含应用程序未受保护的源代码。

💻我们要构建什么

现在,当我们了解了它与 Electron 的区别后,我们将构建与上一篇文章相同的应用程序:一个基于OpenWeatherMap API构建的应用程序,用于查看用户所选城市的天气。该项目将使用Vue CLI构建,我推荐使用这种方式来搭建任何 Vue 应用程序。

如果您只想检查最终的 NW.js 应用程序代码,请点击此处

🛠️ 安装

使用 Vue CLI 创建应用程序

首先,让我们用 Vue CLI 搭建一个应用。请确保你已经在控制台中输入以下命令安装了它:



vue --version


Enter fullscreen mode Exit fullscreen mode

如果你没有版本或者版本低于 3.x,请运行



npm install -g @vue/cli


Enter fullscreen mode Exit fullscreen mode

现在,您可以从控制台创建 Vue 项目了!请运行



vue create <<YOUR-PROJECT-NAME>>


Enter fullscreen mode Exit fullscreen mode

并选择您需要的选项。我将在本项目中使用默认设置。

太好了,现在我们可以添加一些桌面魔法了🧙

添加 NW.js

NW.js 官方文档建议使用以下两个构建器之一来打包您的应用程序:

我选择了 nwjs-builder-phoenix,我将描述进一步的步骤,假设你也会使用它😅

因此,首先需要将其作为依赖项添加到您的项目中:



npm install --save-dev nwjs-builder-phoenix
## OR
yarn add --dev nwjs-builder-phoenix


Enter fullscreen mode Exit fullscreen mode

现在您需要修改package.json文件以便为打包程序提供正确的条目。

package.json提示:您可以在应用程序的根文件夹中找到。

打包器条目应在main属性下指定。我们将在桌面上运行一个开发环境,因此让我们package.json使用以下内容进行扩展:



"main": "http://localhost:8080"


Enter fullscreen mode Exit fullscreen mode

它是我们搭建的 Web 应用在本地运行的端口。通常情况下main是这样index.html,但现在我们希望在每次应用变更时都进行热重载。因此,我们指定了main一个带有热重载模块的 Vue 应用。

运行应用程序

现在让我们运行我们的 Web 应用程序:



npm run serve
## OR
yarn serve


Enter fullscreen mode Exit fullscreen mode

你可以http://localhost:8080在浏览器中检查应用是否正在运行。应该显示类似以下内容:

浏览器中的应用程序

最后,我们准备启动桌面应用程序:



./node_modules/.bin/run .


Enter fullscreen mode Exit fullscreen mode

这将获取指定版本的 NW.js(默认情况下是sdk)并运行开发环境。

run是一个由 和 点添加的命令,表示我们正在从根目录nwjs-builder-phoenix使用。package.json

现在你应该有一个在桌面上运行的应用程序

桌面上的应用程序

让我们稍微自动化一下运行开发环境。关闭你的桌面应用,然后安装 NW.js SDK 版本:



npm install --save-dev nw@sdk
## OR
yarn add --dev nw@sdk


Enter fullscreen mode Exit fullscreen mode

现在,向部分添加一个新任务package.json scripts



"scripts": {
  "serve": "vue-cli-service serve",
  "build": "vue-cli-service build",
  "nw-serve": "nw ." /* <--- here is your new npm task */
},


Enter fullscreen mode Exit fullscreen mode

我们尝试运行它:



npm run nw-serve
## OR
yarn nw-serve


Enter fullscreen mode Exit fullscreen mode

您的应用程序应该可以再次在桌面上运行,但现在无需下载步骤🎉

好消息:你可以像在浏览器中一样轻松打开 DevTools,并使用它们来调试你的应用程序!只需点击Window->Devtools

开发工具

🕹️ 搭建应用程序

与 Electron 类似,NW.js 驱动的应用程序的构建方式与通常的 Web 应用程序类似,因此我们将创建一个 Web 应用程序,使用一些 CSS 设置其样式,然后将nwjs-builder-phoenix其打包到桌面应用程序中。

注意:与 Electron 应用一样,我特意没有安装任何 CSS 框架或组件库:我想在不添加任何依赖项的情况下比较包大小。所有桌面项目使用的唯一库是axios

打开App.vue文件并将其内容替换为以下代码:



<template>
  <div id="app">
    <p>Enter the city name to check current weather in it</p>
    <section class="weather-input">
      <input type="text" v-model="query">
      <button :disabled="!query.length">Check</button>
    </section>
  </div>
</template>

<script>
export default {
  data() {
    return {
      query: "",
    };
  }
};
</script>

<style>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

.button {
  color: #000;
}
</style>


Enter fullscreen mode Exit fullscreen mode

现在我们的应用程序看起来是这样的:

无样式的应用程序

🔗 进行 API 调用

我使用了OpenWeatherMap 的当前天气 API。它提供了许多不同的信息,您可以在此处查看 JSON 响应的示例。

我们将使用axios进行 API 调用。显然,我们需要安装它:



npm install axios
## OR
yarn add axios


Enter fullscreen mode Exit fullscreen mode

为了能够在任何 Vue 组件中使用 axios,我们将其导入main.js,设置基本 URL,然后在 Vue 原型中为其创建一个属性:



//main.js

import axios from 'axios'

axios.defaults.baseURL = 'http://api.openweathermap.org/data/2.5';
Vue.http = Vue.prototype.$http = axios;


Enter fullscreen mode Exit fullscreen mode

现在App.vue我们将创建一组数据属性来显示不同的天气数据:



// App.vue

data() {
    return {
      query: '',
      error: false,
      city: '',
      country: '',
      weatherDescription: '',
      temp: null,
      tempMin: null,
      tempMax: null,
      humidity: null,
      icon: '',
    };
},


Enter fullscreen mode Exit fullscreen mode

与 Electron 类似,与 Vuido 版本相比,我添加了一个附加属性,即icon。API 提供了一个天气图标,但我们无法在 Vuido 应用中使用它,因为目前不支持显示图像。

我们还创建一个方法来获取数据:



methods: {
  showWeather() {
    this.$http
      .get(`/weather?q=${this.query}&units=metric&&appid=${API_KEY}`)
      .then(response => {
        this.city = response.data.name;
        this.country = response.data.sys.country;
        this.weatherDescription = response.data.weather[0].description;
        this.temp = response.data.main.temp;
        this.tempMin = response.data.main.temp_min;
        this.tempMax = response.data.main.temp_max;
        this.humidity = response.data.main.humidity;
        this.icon = `http://openweathermap.org/img/w/${
          response.data.weather[0].icon
        }.png`;
        this.error = false;
      })
      .catch(() => {
        this.error = true;
        this.city = '';
      });
  },
},


Enter fullscreen mode Exit fullscreen mode

不要忘记API_KEY使用您的 OpenWeather API 密钥创建一个 const!

并将其添加到按钮的点击回调中:



<button :disabled="!query.length" @click="showWeather">Check</button>


Enter fullscreen mode Exit fullscreen mode

现在,如果您在输入字段中输入文本并单击按钮,您可以在选项Network卡中观察 API 调用:

API 调用响应

💅 显示天气数据

让我们将这些数据添加到模板中:



<template>
  <main id="app">
    <p>Enter the city name to check current weather in it</p>
    <section class="weather-input">
      <input type="text" v-model="query">
      <button :disabled="!query.length" @click="showWeather">Check</button>
    </section>
    <section v-if="error" class="weather-error">
      There is no such city in the database
    </section>
    <section v-if="city.length" class="weather-result">
      <h1>{{city}}, {{country}}</h1>
      <p><em>{{weatherDescription}}</em></p>
      <div class="weather-result__main">
        <img :src="icon" alt="Weather icon">
        <div class="weather-result__temp">
          {{temp}}&deg;C
        </div>
      </div>
      <div class="weather-result__details">
        <p>Min: {{tempMin}}&deg;C</p>
        <p>Max: {{tempMax}}&deg;C</p>
        <p>Humidity: {{humidity}}%</p>
      </div>
    </section>
  </main>
</template>


Enter fullscreen mode Exit fullscreen mode

我们的应用视图:

无样式的应用程序

它看起来仍然太基础了,所以是时候添加一些 CSS 了。让我们用以下代码替换整个style部分:App.vue



<style>
* {
  margin: 0;
  padding: 0;
}
html,
body,
#app {
  height: 100%;
}

#app {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 16px;
  padding: 10px;
  background: rgb(212, 228, 239);
  background: radial-gradient(
    ellipse at center,
    rgba(212, 228, 239, 1) 0%,
    rgba(134, 174, 204, 1) 100%
  );
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d4e4ef', endColorstr='#86aecc',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
}

.weather-input {
  display: flex;
  align-items: center;
  padding: 20px 0;
}

.weather-result {
  text-align: center;
}

.weather-result__main {
  display: flex;
  align-items: center;
  justify-content: center;
  padding-top: 5px;
  font-size: 1.3rem;
  font-weight: bold;
}

.weather-result__details {
  display: flex;
  align-items: center;
  justify-content: space-around;
  color: dimgray;
}

.weather-error {
  color: red;
  font-weight: bold;
}

input {
  width: 75%;
  outline: none;
  height: 20px;
  font-size: 0.8rem;
}

button {
  display: block;
  width: 25%;
  height: 25px;
  outline: none;
  border-radius: 5px;
  white-space: nowrap;
  margin: 0 10px;
  font-size: 0.8rem;
}
</style>


Enter fullscreen mode Exit fullscreen mode

最后,我们得到了一个美观且功能齐全的应用程序:

应用程序就绪

打包之前要做的最后一件事是缩小窗口大小。为此,我们需要添加一个window属性package.json



"window": {
  "width": 600,
  "height": 400
},


Enter fullscreen mode Exit fullscreen mode

📦包装

要打包 NW.js 应用,nwjs-builder-phoenix您需要运行带有适当参数的构建命令。我将在 Mac 上构建它,以便将其大小与 Electron 和 Vuido 应用进行比较。

首先,我们需要指定构建过程中使用的 NW.js 版本。我们可以build通过package.json



"build": {
  "nwVersion": "0.35.3"
},


Enter fullscreen mode Exit fullscreen mode

然后我们在终端中运行一个构建命令:



./node_modules/.bin/build --tasks mac-x64 .


Enter fullscreen mode Exit fullscreen mode

再次强调,命令中的点表示我们正在使用package.json位于根项目文件夹中的文件

让我们检查一下包大小...233 MB😱!

应用程序大小

哇,好多啊!比 Electron 应用还大!

🌟 结论

优点:

  • 真的很容易上手
  • 可以通过 CSS 样式进行定制
  • 好的文档
  • 支持受保护的二进制文件

缺点

  • 包装尺寸非常大
  • 命名不太好(也许只是我的看法,但 Electron/Vuido 比 NW.js 更容易记住)
  • 小生态系统。

💖 特别感谢

我要感谢Jared Wilcurt ,他帮助我解答了 NW.js 方面的问题。Jared 是NW.js Vue devtools的作者,该工具可以直接在桌面上调试 Vue 应用程序。

更新:如果您想知道如何显著减少包的大小,这里有一篇由 Jared Wilcurt 撰写的文章。

文章来源:https://dev.to/n_tepluhina/building-a-desktop-app-with-vue-nwjs-1f9e
PREV
使用 Vue 构建桌面应用程序:Vuido
NEXT
使用 Vue: Electron 构建桌面应用程序