如何在Ubuntu 20.04上使用Nginx发布一个Vuetify应用程序
作为“为捐赠而写”计划的一部分,作者选择了多元技术基金作为接受捐赠的机构。
简介
组件是现代前端开发的一个重要特性。一个组件通常包括两个部分的代码。
- The logic of the component: what the component can do.
- The template: how the user will interact with the web application.
将你的应用程序组织成组件有助于编写现代、稳健的网页应用。JavaScript框架,如React和Vue.js,可以帮助你开发多种类型的组件,并被开发人员广泛使用。
然而,这些框架的一个痛点是你需要创建许多组件,即使是像输入文本字段这样简单的东西。因此,更加简化的方法是使用一个组件库,它里面有预制的组件可以根据需要选择和使用。通过使用组件库,你无需担心CSS设计、颜色、大小和字体,可以专注于功能。
对于Vue.js,有一个基于Material Design原则的Vue UI库叫做Vuetify。Vuetify非常可配置和可自定义。您可以修改组件以满足自己的需求,并且可以设置自己的主题来创建一个基于自己品牌风格的一致组件库。
在这个教程中,你将基于Vuetify创建一个待办事项应用,并使用Nginx作为反向代理将其发布。这是部署Vue应用所必需的。
Note
先决条件
要按照这个教程,你需要以下物品:
- One Ubuntu 20.04 server with a sudo non-root user. To get started, follow our Initial Server Setup Guide for Ubuntu 20.04. For this tutorial, the non-root user is sammy.
- Nginx installed, which you can do by following Steps 1-3 of the tutorial, How To Install Nginx on Ubuntu 20.04.
- A fully registered domain name. This tutorial will use your_domain throughout. You can purchase a domain name on Namecheap, get one for free on Freenom, or use the domain registrar of your choice.
- Node.js (at least v14.0.0) installed, which you can do by following the How to Install Node.js and Create a Local Development Environment tutorial for your operating system.
- Familiarity with Vue.js, which you can find in the Vue quick start guide and our series, How To Develop Websites with Vue.js.
第一步 – 设置您的Vue应用程序
在这一步中,您将配置您的Vue.js应用程序。Vue.js有一个客户端,您可以使用它来创建项目的样板,这是一个从零开始的好方法。
你可以使用以下命令全局安装Vue.js客户端来开始操作:
- sudo npm install -g @vue/cli
接下来,验证版本。
- vue –version
在写这篇教程时,最新版本是5.0.8。
@vue/cli 5.0.8
现在你已经安装了@vue/cli,可以用它来创建vuejs的应用程序。在这个教程中,该应用程序将被称为vuetify-meets-nginx-app,但你可以将其名称更改为任何你喜欢的名字。
要创建这个应用程序,请运行以下命令:
- vue create vuetify-meets-nginx-app
这个命令是交互式的,并且有多个选项。对于这个教程,选择Vue 2的默认选项。
Vue CLI v5.0.8 ? Please pick a preset: (Use arrow keys) Default ([Vue 3] babel, eslint) ❯ Default ([Vue 2] babel, eslint) Manually select features
Warning
输出错误:您无法在没有路径的集合上调用“get”。请先检查“length”属性,以验证至少存在一个路径。**
如需更多信息,请参阅Vuetify路线图。
一旦应用程序创建完成,您会注意到Vue生成的文件和目录。
├── README.md
├── babel.config.js
├── jsconfig.json
├── node_modules
├── package-lock.json
├── package.json
├── public/
├── favicon.ico
└── index.html
├── src
...
└── vue.config.js
这里有一个简要概述:
- babel.config.js: Babel is a Javascript compiler, and this file defines its behavior. This is necessary to run, build, and generate the final application.
- jsconfig.json: This file is also necessary to compile the app. For example, this file sets the version of the Javascript code to ECMAScript 2009 (ES5), the default one. For more information, check out this documentation.
- node_modules: Directory containing all installed and configured libraries.
- package.json: The main configuration file of your app. You will see here information about the dependencies and the commands available to run or build your app.
- package-lock.json: This is a dump file of all the dependencies used by your app. This file is especially useful if you want to install your app on another laptop or server with npm.
- public: Here, you have the base code that npm run serve command needs to publish your app. It is generated by the @vue/cli command.
- vue.config.js: Vue configuration file.
在源文件夹中,你将看到以下文件和目录:
src
├── App.vue
├── assets
│ ├── logo.png
│ └── logo.svg
├── components
│ └── HelloWorld.vue
├── main.js
这是一个简要概述:
- App.vue: The Vue.js application’s top-level component. All other components will be inside the component defined here.
- assets: All assets, such as images, CSS files, and fonts, must be placed here.
- components: This contains all the components you create. The @vue/cli command generated one called HelloWorld.vue.
- main.js: The app main file. If you need to configure a library or plugin, this is the file. It also created the Vue app.
现在您可以导航到vuetify-meets-nginx-app目录。
- cd vuetify-meets-nginx-app
要以开发模式启动应用程序,请运行以下命令:
- npm run serve
你的输出将会是这样的:
INFO Starting development server… DONE Compiled successfully in 27235ms App running at: – Local: http://localhost:8080/ – Network: unavailable Note that the development build is not optimized. To create a production build, run npm run build.
一旦开发服务器启动,打开 localhost:8080 即可查看应用程序。
Note
ssh -L 8080:localhost:8080 您的非根用户@您的服务器IP
连接到服务器后,在本地计算机的Web浏览器中导航到http://localhost:8080。在本教程的剩余部分,保持第二个终端打开。
在这一步中,你创建了自己的Vue.js应用程序。接下来,你将为项目添加Vuetify。
第二步—将Vuetify集成到Vue应用中
在这一步中,您将向您的Vue.js应用程序中添加Vuetify。
如果没有像Vuetify这样的组件库,你必须使用HTML的input元素,比如div和button,为你的网络应用设计CSS,并且自己创建组件,如果你想要一些可重复使用的块。但是有了Vuetify库,你只需要导入你想要的组件并且添加到你的模板中。
Vuetify也可以高度定制化。例如,你可以使用主题。一个主题是一个包含颜色调色板、自定义屏幕大小和字体等内容的CSS库。比如,如果你的主要颜色是蓝色,你可以配置Vuetify以这种方式,每次你使用`primary` CSS类时,Vuetify都会使用蓝色。你可以在Vuetify文档中找到有关主题的更多信息。有关这些和其他组件的更多信息可以在Vuetify功能指南中找到。
要开始添加Vuetify,首先要停止在前一步中启动的开发服务器,在运行开发服务器的终端中按下CTRL+C键。
接下来,在vuetify-meets-nginx-app目录中运行以下命令。
- vue add vuetify
使用Vue.js客户端安装Vuetify的命令是这样的。
在预设选项列表中选择默认配置。
? Installing vue-cli-plugin-vuetify… added 38 packages, and audited 39 packages in 2s 7 packages are looking for funding run `npm fund` for details found 0 vulnerabilities ✔ Successfully installed plugin: vue-cli-plugin-vuetify ? Choose a preset: (Use arrow keys) Configure (advanced) ❯ Default (recommended) Vite Preview (Vuetify 3 + Vite) Prototype (rapid development) Vuetify 3 Preview (Vuetify 3)
几分钟后,您可以再次启动开发服务器。
- npm run serve
导航到localhost:8080,在那里你可以看到一个应用程序,具有全新的“vuetified”样式。
在这一点上,您已经创建了一个基本应用程序,并添加了Vuetify进行样式设置。接下来,您将创建一个拥有额外功能的待办事项应用程序。
第三步 — 创建一个使用Vuetify的待办事项应用
在这个步骤中,你将创建一个待办事项应用程序。待办事项应用程序是一个任务列表,需要一些基本功能。
- A way to add new tasks.
- A way to mark them as done.
- A method to display them, allowing users to see what is pending.
要将这些功能添加到您的应用程序中,您将修改App.vue文件,该文件是应用程序的顶级组件。所有其他组件都将包含在这里定义的组件中。
Note
Vue.js 和很多其他框架一样,默认采用热加载。在你开发代码时,只要持续运行 npm run serve 命令,你保存修改后,浏览器上就会立即显示更新内容。
导航到src/App.vue并使用nano或您喜欢的文本编辑器打开以进行编辑。
- cd src
- nano App.vue
这里是默认代码
<template>
<v-app>
<v-app-bar
app
color="primary"
dark
>
<div class="d-flex align-center">
<v-img
alt="Vuetify Logo"
class="shrink mr-2"
contain
src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png"
transition="scale-transition"
width="40"
/>
<v-img
alt="Vuetify Name"
class="shrink mt-1 hidden-sm-and-down"
contain
min-width="100"
src="https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png"
width="100"
/>
</div>
<v-spacer></v-spacer>
<v-btn
href="https://github.com/vuetifyjs/vuetify/releases/latest"
target="_blank"
text
>
<span class="mr-2">Latest Release</span>
<v-icon>mdi-open-in-new</v-icon>
</v-btn>
</v-app-bar>
<v-main>
<HelloWorld/>
</v-main>
</v-app>
</template>
<script>
import HelloWorld from './components/HelloWorld';
export default {
name: 'App',
components: {
HelloWorld,
},
data: () => ({
//
}),
};
</script>
每个组件都有两个部分:一个模板(通常是HTML代码)和一个用Javascript编写的具有功能的脚本。
模板是最终用户在浏览器中看到的,它决定了用户与你的应用程序的交互方式。通常情况下,你需要导入要在模板中使用的组件,但由于你将Vuetify安装为插件,所有组件都可以在模板中直接使用,无需显式导入。
模板块中有很多v- HTML标签。尽管对于HTML来说非标准,但这些标签是Vuetify组件,并且始终以v-开头。
在模板中,您目前有:
- v-app: the main component, which is attached to the body of the website.
- v-app-bar: the default side bar.
- v-img: a component that loads images.
- v-icon: a component for showing icons.
- v-spacer: a component that aligns the next component to the right.
关于App.vue文件中的脚本块,在Vuetify安装中并没有添加任何代码在这里,所以你所拥有的只是由Vue cli命令生成的起始代码以及Vue组件所需的最小代码。
现在你已经查看了App.vue文件中的默认代码,准备开始创建你的待办事项应用。第一步将是删除一些你不会使用的默认代码。
整理App.vue文件
默认的HelloWorld组件在您的待办事项应用中不再需要,因此您将其从App.vue文件中删除。
要在另一个组件或视图中使用一个Vue组件,你必须将该组件导入到文件的脚本块中。在你的App.vue文件中,你在第一行导入了HelloWorld组件。
...
import HelloWorld from './components/HelloWorld';
...
既然你不会使用这个组件,就删除导入行。
下一步是从App.vue页面的组件依赖列表中移除该组件。在脚本块中,找到以下行:
...
<script>
...
components: {
HelloWorld,
},
...
</script>
从组件列表中删除 HelloWorld 这一行。
最后一步是将它从模板块中移除。
...
<template>
...
<v-main>
<HelloWorld/>
</v-main>
</v-app>
</template>
...
删除HelloWorld这一行。
现在默认的HelloWorld组件已经被移除了,你可以开始创建你的待办事项应用了。
添加组件数据字段
为了构建你的待办事项应用程序,你需要为你的应用程序添加数据字段。组件的数据是一个函数,它返回你将能够在模板中使用的所有数据模型。所有这些数据模型都是一个对象中的JavaScript变量,并且还可以被组件的方法访问。
在脚本块中找到数据字段位置。
...
<script>
...
data: () => ({
//
}),
};
</script>
你将修改数据函数以存储你的任务列表。将以下突出显示的行添加到数据函数中。
...
<script>
...
data: () => ({
tasks: ['task 1', 'task 2', 'task 3'],
newTask: null
}),
};
</script>
通过这个更新,你增加了两个数据模型:一个新的任务变量用于存储任务名称,以及任务列表的任务。现在模板和方法中都可以使用这两个数据模型。
Note
为您的应用程序添加功能
接下来,您将添加功能。在Vue.js组件中,功能位于一个名为methods的函数列表中。在数据模型下的脚本块中,添加下面突出显示的行以添加三个函数:
...
<script>
export default {
name: 'App',
data: () => ({
tasks: ['task 1', 'task 2', 'task 3'],
newTask: null
}),
methods: {
addNewTask() {
this.tasks.push(this.newTask);
this.clearNewTask();
},
clearNewTask() {
this.newTask = '';
},
removeTask(i) {
this.tasks.splice(i, 1);
}
}
};
你加了三个功能:
你增加了三个功能:
你添加了三个功能:
你新增了三个功能:
- addNewTask: To add the new task inside the newTask data model to the tasks list.
- clearNewTask: To clear the data model for newTask.
- removeTask: To remove a task from tasks based on an array index.
你现在已经添加了你的待办事项应用程序的功能。接下来,你将修改模板来使用这些方法。
更新模板
你的待办事项应用的最后一部分是模板。在这个部分,你将会更新模板,使用之前部分中添加的方法和数据模型。
你需要从v-app-bar中删除一些不需要的组件。删除v-btn块。然后,你的代码将如下所示:
<template>
<v-app>
<v-app-bar
app
color="primary"
dark
>
<div class="d-flex align-center">
<v-img
alt="Vuetify Logo"
class="shrink mr-2"
contain
src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png"
transition="scale-transition"
width="40"
/>
<v-img
alt="Vuetify Name"
class="shrink mt-1 hidden-sm-and-down"
contain
min-width="100"
src="https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png"
width="100"
/>
</div>
<v-spacer></v-spacer>
</v-app-bar>
...
</v-app>
</template>
接下来,您将添加一些组件来定义您的应用程序的基本布局。首先是v-container,它是一个提供将应用程序内容居中和水平填充的能力的组件。有关该组件和其他容器的更多信息,请参阅Vuetify的网格系统文档。
在v-container中,您将添加一个v-card组件,它是另一个Vuetify容器。它用于在屏幕上组织内容,例如面板或静态图像。要了解有关v-card组件的更多信息,请查阅Vuetify文档中的卡片部分。
找到当前模板中的v-main块并添加高亮显示的行。
...
<v-main>
<v-container>
<v-card elevation="0">
</v-card>
</v-container>
</v-main>
...
正如您在代码中看到的那样,v-card组件中有一个elevation=”0″属性。在Vuetify组件中,elevation是一个常见属性,用于调整两个组件之间的相对Z轴距离。在这种情况下,您不需要任何距离,而0是用来去除elevation的值。但是,您可以尝试进行调整来观察不同之处,或者查看elevation文档。
接下来,你将使用两个v-card功能组件:v-title,它为卡片标题提供了默认的字体大小和内边距;以及v-card-text,它将包含卡片的内容。将下面的行添加到你的v-card组件中:
...
<v-main>
<v-container>
<v-card elevation="0">
<v-card-title></v-card-title>
<v-card-text></v-card-text>
</v-card>
</v-container>
</v-main>
...
功能组件是仅渲染模板的组件。它没有任何逻辑,并且由于它仅仅是一个模板,所以渲染速度更快。了解更多有关功能组件的信息,或学习如何创建您自己的功能组件,请参阅Vue.js指南中的功能组件部分。
现在你已经有了容器组件,你需要添加一个 v-text-field 组件来处理新任务的名称。在你刚刚添加的 v-card-title 组件中,插入需要突出显示的行:
vuetify-meets-nginx-app/src/App.vue
...
<v-main>
<v-container>
<v-card elevation="0">
<v-card-title>
<v-text-field
v-model="newTask"
label="Task Name"
prepend-icon="mdi-content-save"
clear-icon="mdi-close-circle"
clearable
filled
type="text"
@click:prepend="addNewTask"
@click:clear="clearNewTask"
></v-text-field>
</v-card-title>
...
</v-card>
</v-container>
</v-main>
...
v-text-field是为命名新任务而必需的组件。
它具有以下特性:
- v-model=”newTask” attaches the data model to the component. Any text you put in the input will also be added to the data model.
- label=”Task Name” is the text in the input type’s placeholder.
- prepend-icon=”mdi-content-save” will display the Save icon in the text box’s left corner.
- clear-icon=”mdi-close-circle” is the Clear button’s icon.
- clearable shows the Clear icon.
- filled applies an alternate filled input style to the component.
- type=”text” sets the input type of the underlying HTML input field. Other options include email or password.
- @click: prepend=”addNewTask” attaches the Save button’s click event to the addNewTask function.
- @click: clear=”clearNewTask” connects the Save button’s click event to the clearNewTask function.
下一步是展示任务列表模型中的每个任务。为此,您将使用v-timeline组件,这是一个用于显示基于时间或顺序的信息的显示组件。您将将其添加到v-card-text中,该组件是v-card主体组件。在已添加的v-card-text组件内,插入高亮显示的行。
vuetify-meets-nginx-app/src/App.vue 可以用下面的中文方式来表达:
vuetify-meets-nginx-app/src/App.vue
...
<v-main>
<v-container>
<v-card elevation="0">
<v-card-title>
...
</v-card-title>
<v-card-text>
<v-timeline
v-if="tasks.length > 0"
dense
></v-timeline>
</v-card-text>
...
</v-card>
</v-container>
</v-main>
...
v-timeline会显示列表中的所有任务。v-if是只有当数据模型中有至少一个任务时才显示该组件。dense用于紧凑显示内容(基本上,它会从组件的CSS样式中删除一些填充和边距)。
现在,为了显示每个任务的名称,你需要使用一个 v-timeline 的功能组件:v-timeline-item。在 v-timeline 组件内添加以下行:
...
<v-main>
<v-container>
<v-card elevation="0">
<v-card-title>
...
</v-card-title>
<v-card-text>
<v-timeline
v-if="tasks.length > 0"
dense
>
<v-timeline-item
v-for="(t, index) in tasks"
:key="index"
>
{{ t }}
</v-timeline-item>
</v-timeline>
</v-card-text>
</v-card>
</v-container>
</v-main>
...
该代码使用v-for循环,在任务列表模型中为每个任务显示一个v-timeline-item组件。由于v-timeline-item是v-timeline的功能组件,因此会以时间顺序的列表样式呈现。
你在v-for循环中将索引添加为键是因为它对于v-for指令是必需的。关于如何在v-for中使用唯一键,请查阅Vue产品文档。
通过{{ t }}行,您将能在v-timeline-item组件中显示任务的名称。
下一步是在列表中添加一个按钮来删除任务。但在此之前,您需要添加一些额外的网格系统组件来组织任务名称和按钮。在v-timeline-item组件中添加突出显示的行:
...
<v-main>
<v-container>
<v-card elevation="0">
<v-card-title>
...
</v-card-title>
<v-card-text>
<v-timeline
v-if="tasks.length > 0"
dense
>
<v-timeline-item
v-for="(t, index) in tasks"
:key="index"
>
<v-row class="display-1 text-capitalize">
<v-col cols="7">
{{ t }}
</v-col>
<v-col
class="text-right"
cols="5"
>
</v-col>
</v-row>
</v-timeline-item>
</v-timeline>
</v-card-text>
</v-card>
</v-container>
</v-main>
...
用上面的代码,你增加了:
- A v-row component with two classes to set the size of the text of the task (display-1, similar to H1 in HTML) and with all the characters in capital letters (text-capitalize).
- A v-col component inside the row to show the name of every task that will need 7/12 parts of the space (the cols=”7″ property).
- Another v-col component that places the remove button. It needs 5/12 parts of the space (cols=”5″ property) and has all the components inside aligned to the right, determined by the text-right class.
最后,是时候将 removeTask 函数附加到一个按钮组件上,使用 v-btn 组件。为了简化,你将使用一个图标按钮,即只有图标没有文本的按钮。为此,你还需要一个 v-icon 组件。
加入被突出显示的行。
...
<v-timeline
v-if="tasks.length > 0"
dense
>
<v-timeline-item
v-for="(t, index) in tasks"
:key="index"
>
<v-row class="display-1 text-capitalize">
<v-col cols="7">
{{ t }}
</v-col>
<v-col
class="text-right"
cols="5"
>
<v-btn
icon
@click="removeTask(index)"
>
<v-icon color="red lighten-1" large>
mdi-sticker-remove
</v-icon>
</v-btn>
</v-col>
</v-row>
...
</v-timeline-item>
</v-timeline>
在你刚刚添加的代码中,v-btn组件的icon属性指定了不需要文本。它修改了组件,只对v-icon组件进行样式设置。
@click组件事件将您的removeTask方法绑定到按钮的点击事件上。因此,每当底层的按钮点击事件被触发时,您的方法将被调用。
你使用了v-for循环提供的索引作为removeTask方法的参数。
最后,v-icon的颜色将是红色 lighten-1,大小将为大号,且您使用的是mdi-sticker-remove材料设计的图标。
现在你已经使用一些Vuetify组件更新了模板,并配置了它们以使用和显示数据模型的内容,同时还允许你的应用用户通过页面方法与它们进行交互。
这是App.vue文件的最终代码。
vuetify-meets-nginx-app/src/App.vue
<template>
<v-app>
<v-app-bar
app
color="primary"
dark
>
<div class="d-flex align-center">
<v-img
alt="Vuetify Logo"
class="shrink mr-2"
contain
src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png"
transition="scale-transition"
width="40"
/>
<v-img
alt="Vuetify Name"
class="shrink mt-1 hidden-sm-and-down"
contain
min-width="100"
src="https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png"
width="100"
/>
</div>
<v-spacer></v-spacer>
</v-app-bar>
<v-main>
<v-container>
<v-card elevation="0">
<v-card-title>
<v-text-field
v-model="newTask"
label="Task Name"
prepend-icon="mdi-content-save"
clear-icon="mdi-close-circle"
clearable
filled
type="text"
@click:prepend="addNewTask"
@click:clear="clearNewTask"
></v-text-field>
</v-card-title>
<v-card-text>
<v-timeline
v-if="tasks.length > 0"
dense
>
<v-timeline-item
v-for="(t, index) in tasks"
:key="index"
>
<v-row class="display-1 text-capitalize">
<v-col cols="7">
{{ t }}
</v-col>
<v-col
class="text-right"
cols="5"
>
<v-btn
icon
@click="removeTask(index)"
>
<v-icon color="red lighten-1" large>
mdi-sticker-remove
</v-icon>
</v-btn>
</v-col>
</v-row>
</v-timeline-item>
</v-timeline>
</v-card-text>
</v-card>
</v-container>
</v-main>
</v-app>
</template>
<script>
export default {
name: 'App',
data: () => ({
tasks: ['task 1', 'task 2', 'task 3'],
newTask: null
}),
methods: {
addNewTask() {
this.tasks.push(this.newTask);
this.clearNewTask();
},
clearNewTask() {
this.newTask = '';
},
removeTask(i) {
this.tasks.splice(i, 1);
}
}
};
</script>
保存并关闭你的文件。
如果你的开发服务器还没有运行, 请重新启动它。
- npm run serve
现在你可以导航到 localhost:8080 来查看你的应用程序运行。
在这个步骤中,您创建了一个待办事项应用。您增加了功能并更新了用户界面。现在,您已经编写了该应用程序,可以生成一个可用于生产的版本。下一步是为生产构建该应用程序。
第四步 — 将您的应用程序进行生产环境编译
在之前的步骤中,你已经编写了待办事项应用。但在使用Nginx发布之前,你需要为应用做好生产准备。这一步骤称为构建应用。
构建步骤将应用转换为浏览器可读的内容。如果您尝试在浏览器中打开您的源文件,您将什么都看不到。这是因为它们是Vue.js文件,而不是浏览器可以读取的HTML、JS和CSS文件。在使用Nginx发布您的应用之前,您需要将应用构建为生产环境,这就是您在此步骤中要做的事情。
您可以使用构建命令来自动完成此操作。package.json 是您应用程序的主要配置文件。它包含有关依赖项和可运行或构建应用程序的命令的信息,例如构建命令,如下所示:
{
...
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
...
}
关于package.json文件配置的更多详情,请查阅package.json指南。
要开始建立过程,请使用CTRL+C停止开发服务器。
在同一个终端中,切换到项目目录。
- cd vuetify-meets-nginx-app
执行构建命令:
- npm run build
当构建完成后,你将在 dist 目录中拥有一个可供生产使用的应用版本。
接下来,您将设置Nginx作为反向代理来部署和访问应用程序。
第五步 – 将Nginx配置为反向代理
现在你已经有了一个可工作的应用程序,你必须将Nginx配置为反向代理,以提供你的应用程序文件并将其与你的域名连接起来。
一个反向代理是运行在服务器上的应用程序或服务,它可以将外部请求转发到另一个位置。在你的情况下,每当用户在浏览器中访问你的域名时,Nginx会通过返回来自你的应用程序的文件来处理该请求。它会返回文件,因为当你构建应用程序时,会生成HTML、JS和CSS文件,Nginx会将其视为服务器上其他静态文件或网站处理。
Nginx与站点配合工作。每个站点都是在一个单独的文件中配置的不同网站。所有的配置文件默认放在 /etc/nginx/sites-available/ 目录中。前往该目录。
- cd /etc/nginx/sites-available/
创建一个名为vuetify-meets-nginx-app的文件。
- sudo nano vuetify-meets-nginx-app
Note
在您的vuetify-meets-nginx-app文件中,添加以下行,并确保使用您自己的信息更新server_name:
server {
listen 80;
listen [::]:80;
server_name your_domain;
autoindex on;
root /home/sammy/vuetify-meets-nginx-app/dist/;
index index.html;
}
在本教程中,您正在配置Nginx监听80端口,但您可以使用任何您想要的端口。将your_domain替换为您的域名。如果您正在本地开发环境中进行测试,您也可以使用服务器的IP地址或localhost。
通过根目录行,您告诉 Nginx 所有文件都位于 /home/sammy/vuetify-meets-nginx-app/dist/ 目录中,该目录在前一步骤中创建。最后,通过索引行,您告诉 Nginx 主文件是 index.html。
保存并关闭您的文件。
接下来,你需要解决Nginx配置文件中的权限问题。
Nginx是在你的服务器上运行的服务。你可以使用以下命令列出所有与Nginx相关的运行进程。
- ps -fea | grep nginx
使用带有-fae选项的ps命令以完整格式列出所有当前的进程。然后将该命令的输出进行过滤,仅列出与nginx匹配的进程。
输出的结果将类似于以下内容:
root 39922 1 0 Jul14 ? 00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on; www-data 39923 39922 0 Jul14 ? 00:00:01 nginx: worker process sammy 117909 117434 0 21:27 pts/0 00:00:00 grep –color=auto nginx
如图所示,nginx服务正以www-data用户运行。
接下来,使用这个命令查看/home/sammy/vuetify-meets-nginx-app/dist/的权限:
- ls -l /home/sammy/vuetify-meets-nginx-app/dist/
输出将与以下类似:
total 20 drwxrwxr-x 2 sammy sammy 4096 Jul 14 18:54 css -rw-rw-r– 1 sammy sammy 4286 Jul 14 18:54 favicon.ico -rw-rw-r– 1 sammy sammy 853 Jul 14 18:54 index.html drwxrwxr-x 2 sammy sammy 4096 Jul 14 18:54 js
所有的文件和文件夹都具有对用户”Sammy”开放的权限。如果你配置Nginx来读取这些文件,由于Nginx用户”www-data”没有执行权限,这将无法工作。
解决此问题有几个选择:
- Grant Nginx read, write, and execution permissions to the dist folder. However, granting a service that is accessible from the entire network with permissions to read local user files is not secure. Additionally, Nginx will need permission to access all the parent folders because it needs to navigate to the final folder, which would basically open the /home directory to the world. This is not recommended.
- Run nginx with sudo. This is also not secure, since now you would have a service with access to all the files on your server.
- Move your dist content to a location where only Nginx has access and no one else does. This is the safest option.
在本教程中,您将使用第三个选项。
在Ubuntu和一些其他基于Linux的发行版中,服务之间用于交换文件的共享位置是/var路径。您将把文件复制到/var/www,这是Nginx用于网站的默认路径。
从您的项目目录中运行以下命令,将您的文件复制到/var/www路径中。
- sudo cp -r /home/sammy/vuetify-meets-nginx-app/dist /var/www/vuetify-meets-nginx-app
将所有的文件复制时将保持与之前相同的权限,即为sammy用户的权限,因此您需要将sammy用户添加到与www-data相同的权限组中。您可以使用以下命令来实现此操作:
- sudo usermod -aG www-data sammy
目前,Nginx可以以安全方式访问所需的文件。然而,每当生成新版本的应用程序时,您都需要复制项目文件,这可能会增加自动部署、CI/CD工具等的复杂性。更好的解决方案是修改构建命令,直接在正确的路径生成文件。
要做到这一点,打开 package.json 进行编辑,并添加加亮的文本。
...
"build": "vue-cli-service build --dest /var/www/vuetify-meets-nginx-app",
...
保存并关闭文件。
现在你可以完成Nginx的配置了。打开Nginx配置文件并将其更新为新的应用程序路径。
/etc/nginx/sites-available/vuetify-meets-nginx-app – 简体 Nginx 配置文件中可用的 Vuetify meets Nginx 应用程序。
server {
listen 80;
listen [::]:80;
server_name your_domain OR your_server_IP;
autoindex on;
root /var/www/vuetify-meets-nginx-app;
index index.html;
}
保存并关闭你的文件。
现在你的网站文件准备好了,你需要启用它。为此,请转到启用的网站路径:
- cd /etc/nginx/sites-enabled/
禁用默认网站以确保您不会在同一端口(端口80)上启用和监听两个网站。
- sudo rm default
最后,创建一个符号链接文件到你的应用配置文件。
- sudo ln -s /etc/nginx/sites-available/vuetify-meets-nginx-app
Nginx只会考虑放置在启用目录中的站点文件。您可以直接复制配置文件,但不建议重复文件,因为可能会出现不一致。这就是为什么符号链接(可用文件的文件快捷方式)是更好的方法。
测试以确保您的Nginx文件中没有语法错误。
- sudo nginx -t
你的输出将会像这样:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
为应用更改,请重新启动Nginx服务。
- sudo systemctl restart nginx
现在,您可以通过导航到您的域名(或者您服务器的IP地址)来查看您的待办应用程序已经准备好并且已发布。
在这一步中,你将Nginx配置为反向代理以发布你的应用程序。
结论
在本教程中,你创建了一个Vue.js应用程序并安装和配置了Vuetify框架。然后,你生成了一个静态版本的应用程序,准备上线生产环境,并最后配置了Nginx服务以发布应用。
想要更详细地了解项目文件,请查看Github仓库。
作为下一步,请尝试配置Nginx以通过HTTPS提供您的应用程序。要开始,请遵循我们的教程《如何在Ubuntu 20.04上使用Let’s Encrypt保护Nginx》。
要了解更多关于 Vuetify 的内容,请查阅 Vuetify 文档。如果你有兴趣扩展 Vuetify 组件的功能,请查看我们的教程《扩展 Vuetify 表单字段验证》。