十四、使用 Linter、格式化器和部署命令

除了编写测试(无论是端到端测试还是单元测试),代码筛选和格式化也是 web 开发的一部分。所有开发人员,无论您是 Java、Python、PHP 还是 JavaScript 开发人员,都应该了解各自领域的编码标准,并遵守这些标准,以保持代码干净、可读和格式化,以便将来更好地维护。我们通常用于 JavaScript、Vue 和 Nuxt 应用的工具是 ESLint、Prettier 和 StandardJS。在本章中,您将学习在我们的应用中安装、配置和使用它们。最后,在构建、测试和筛选应用之后,您将学习 Nuxt 部署命令,以将应用部署到主机。

我们将在本章中介绍的主题如下:

  • 推出皮棉–更漂亮、更舒适、更标准
  • 集成 ESLint 和 Prettier
  • 在 Vue 和 Nuxt 应用中使用 ESLint 和 Pretter
  • 部署 Nuxt 应用

推出皮棉–更漂亮、更舒适、更标准

简而言之,linter 是一种分析源代码并标记代码和样式中的错误和 bug 的工具。该术语起源于 1978 年的 Unix 实用程序lint,该实用程序评估用 C 编写的源代码,由贝尔实验室的计算机科学家 Stephen C.Johnson 在调试他正在编写的 Yacc 语法时开发。今天,我们在本书中重点介绍的工具是更漂亮的、ESLint 和 StandardJS。让我们逐一调查一下。

漂亮的

Prettier 是一种代码格式化器,支持多种语言,如 JavaScript、Vue、JSX、CSS、HTML、JSON、GraphQL 等。它提高了代码的可读性,并确保代码符合为您设置的规则。它为代码行设置长度限制;例如,请看下面的一行代码:

hello(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne())

前面的代码在一行中被认为很长,很难阅读,因此 Prettier 将按如下方式将其重新打印成多行:

hello(
  reallyLongArg(),
  omgSoManyParameters(),
  IShouldRefactorThis(),
  isThereSeriouslyAnotherOne()
);

此外,任何自定义或混乱的样式也会被解析和重新打印,如以下示例所示:

fruits({ type: 'citrus' },
  'orange', 'kiwi')

fruits(
  { type: 'citrus' },
  'orange',
  'kiwi'
)

Prettier 将打印并将其重新格式化为以下更整洁的格式:

fruits({ type: 'citrus' }, 'orange', 'kiwi');

fruits({ type: 'citrus' }, 'orange', 'kiwi');

但是,如果 Prettier 在代码中找不到分号,它将为您插入分号,就像前面的示例代码一样。如果您不喜欢在代码中使用分号,可以关闭此功能,本书中使用的所有代码都是如此。让我们通过以下步骤关闭此规则:

  1. 通过 npm 将 Prettier 安装到您的项目中:
$ npm i prettier --save-dev --save-exact
  1. 解析特定的 JavaScript 文件:
$ npx prettier --write src/index.js

或者,解析递归文件夹中的所有文件:

$ npx prettier --write "src/**/*"

甚至可以尝试分析并行文件夹中的文件:

$ npx prettier --write "{scripts,config,bin}/**/*"

在使用--write选项提交任何变更到位(注意!)之前,您可以使用其他输出选项,例如:

  • 使用-c--check检查给定文件是否已格式化,然后打印一条人性化的摘要消息,其中包含指向未格式化文件的路径。
  • 使用-l--list-different打印与 Prettier 格式不同的文件名。

For more information about this tool, visit https://prettier.io/.

现在让我们来看看如何在下一节中配置这个工具。

配置更漂亮

Prettier 具有许多定制选项。您可以通过以下选项配置 Prettier:

  • JavaScript 对象中的prettier.config.js.prettierrc.js脚本
  • 使用prettier键的package.json文件
  • A.带有可选扩展名的 YAML 或 JSON 格式的prettierrc文件:.json.yaml.yml
  • TOML 中的.prettierrc.toml文件

定制更漂亮的衣服是个好主意,即使你可以选择不这样做。例如,默认情况下,Prettier 强制使用双引号,并在语句末尾打印分号。如果我们不想要这些默认值,我们可以在项目根目录中创建一个prettier.config.js文件。让我们在我们创建的 API 中使用 Prettier(我们在 GitHub 存储库的/chapter-14/apps-to-fix/koa-api/中复制了一个),并在以下步骤中使用此配置:

  1. 使用以下代码在我们的项目根目录中创建一个prettier.config.js文件:
// prettier.config.js
module.exports = {
  semi: false,
  singleQuote: true
}
  1. 使用以下命令解析/src/目录中的所有 JavaScript 代码:
$ npx prettier --write "src/**/*"

如您所见,当您运行npx prettier --write "src/**/*"时,我们的所有文件都列在终端上:

src/config/google.js 40ms
src/config/index.js 11ms
src/core/database/mysql.js 18ms
src/index.js 8ms
...

Prettier 将突出显示已重新打印和格式化的文件。

For more format options, check out https://prettier.io/docs/en/options.html. You can find this example in /chapter-14/prettier/ in our GitHub repository.

当你看到你的代码如此轻松地被“美化”时,这是非常甜蜜的,不是吗?让我们继续讨论下一个 linter,ESLint,看看它如何帮助我们在下一节中整理代码。

埃斯林特

ESLint 是 JavaScript 的可插入 linter。它的设计使得它的所有规则都是完全可插拔的,并允许开发人员自定义 linting 规则。ESLint 附带了一些内置规则,使其从一开始就很有用,但您可以在任何时间点动态加载规则。例如,ESLint 不允许在对象文本(no-dupe-keys中使用重复键,您将获得以下代码的错误:

var message = {
  text: "Hello World",
  text: "qux"
}

此规则下的正确代码如下所示:

var message = {
  text: "Hello World",
  words: "Hello World"
}

ESLint 将标记前面的错误,我们必须手动修复它。然而,不需要人工干预,T0 可以自动修复问题。让我们看看如何在以下步骤中执行此操作:

  1. 在项目中通过 npm 安装 ESLint:
$ npm i eslint --save-dev
  1. 设置配置文件:
$ ./node_modules/.bin/eslint --init

您将被问及一系列类似于以下内容的问题:

? How would you like to use ESLint? To check syntax, find problems,
  and enforce code style
? What type of modules does your project use? JavaScript modules (import/export)
? Which framework does your project use? None of these
? Where does your code run? (Press <space> to select, <a> to 
  toggle all, <i> to invert selection)Browser
? How would you like to define a style for your project? Use 
  a popular style guide
? Which style guide do you want to follow? Standard (https://github.com/standard/standard)
? What format do you want your config file to be in? JavaScript
...

Successfully created .eslintrc.js file in /path/to/your/project

这些问题可能因您为每个问题选择的选项/答案而异。

  1. lintlint-fix脚本添加到package.json文件中:
"scripts": {
  "lint": "eslint --ignore-path .gitignore .",
  "lint-fix": "eslint --fix --ignore-path .gitignore ."
}
  1. 创建一个.gitignore文件,其中包含我们希望 ESLint 忽略的路径和文件:
// .gitignore
node_modules
build
backpack.config.js
  1. 启动 ESLint 以扫描错误:
$ npm run lint
  1. 使用lint-fix修复这些错误:
$ npm run lint-fix

您可以在查看 ESLint 规则列表 https://eslint.org/docs/rules/ 。ESLint 中的规则按类别分组:可能的错误、最佳实践、变量、风格问题、ECMAScript 6 等等。默认情况下不启用任何规则。您可以在配置文件中使用"extends": "eslint:recommended"属性来启用报告常见问题的规则,这些问题带有复选标记(✓) 在名单上。

For more information about this tool, visit https://eslint.org/.

现在让我们来看看如何在下一节中配置这个工具。

配置 ESLint

正如我们前面提到的,ESLint 是一个可插入的 linter。这意味着它是完全可配置的,您可以关闭每个规则或其中的一些规则,或者混合自定义规则,使 ESLint 特别适合您的项目。让我们在使用以下配置之一创建的 API 中使用 ESLint。有两种方法可以配置 ESLint:

  • 将 JavaScript 注释直接与文件中的 ESLint 配置信息一起使用,如下例所示:
// eslint-disable-next-line no-unused-vars
import authenticate from 'middlewares/authenticate'
  • 使用 JavaScript、JSON 或 YAML 文件指定整个目录及其所有子目录的配置信息。

使用第一种方法可能很耗时,因为您可能需要在每个.js文件中提供 ESLint 配置信息,而在第二种方法中,您只需要在.json文件中配置一次。因此,让我们在以下步骤中使用 API 的第二种方法:

  1. 在根目录中创建一个.eslintrc.js文件或使用--init生成,规则如下:
// .eslintrc.js
module.exports = {
  'rules': {
    'no-undef': ['off'],
    'no-console': ['error']
    'quotes': ['error', 'double']
  }
}

在这些规则中,我们希望确保执行以下操作:

  • 通过将no-undef选项设置为off来允许未声明的变量(no-undef
  • 通过将no-console选项设置为error来禁止使用控制台(no-console
  • 通过将quotes选项设置为errordouble,强制一致使用反勾号、双引号或单引号(quotes

  • lintlint-fix脚本添加到package.json文件中:

// package.json
"scripts": {
  "lint": "eslint --ignore-path .gitignore .",
  "lint-fix": "eslint --fix --ignore-path .gitignore ."
}
  1. 启动 ESLint 以扫描错误:
$ npm run lint

如果出现任何错误,您将得到如下报告:

/src/modules/public/login/_routes/google/me.js 
   36:11  error  A space is required after '{'  object-
          curly-spacing 
   36:18  error  A space is required before '}' object-
          curly-spacing

即使 ESLint 可以使用--fix选项自动修复代码,您仍然需要手动修复一些代码,如下例所示:

/src/modules/public/user/_routes/fetch-user.js 
  9:9  error  'id' is assigned a value but never used  
       no-unused-vars

For more information about the configuration, check out https://eslint.org/docs/user-guide/configuring. You can find this example in /chapter-14/eslint/ in our GitHub repository.

它是用户友好的,不是吗?它确实是另一个很棒的工具,就像 Prettier 一样。让我们转到最后一个 linter,StandardJS,看看它是如何整理代码的。

标准的

StandardJS 或 JavaScript 标准样式是 JavaScript 样式指南、linter 和格式化器。它是完全自以为是的,这意味着它是完全不可编辑的–不需要配置,因此没有需要管理的.eslintrc.jshintrc.jscsrc文件。它是不可压缩和不可配置的。使用 StandardJS 最简单的方法是将其作为节点命令行程序进行全局安装。让我们通过以下步骤了解如何使用此工具:

  1. 通过 npm 全局安装 StandardJS:
$ npm i standard --global

您也可以为单个项目在本地安装它:

$ npm i standard --save-dev
  1. 导航到要检查的目录,并在终端中键入以下命令:
$ standard
  1. 如果您在本地安装 StandardJS,则使用npx运行它:
$ npx standard

您也可以将其添加到package.json文件中,如下所示:

// package.json
{
  scripts": {
    "jss": "standard",
    "jss-fix": "standard --fix"
  },
  "devDependencies": {
    "standard": "^12.0.1"
  },
  "standard": {
    "ignore": [
      "/node_modules/",
      "/build/",
      "backpack.config.js"
    ]
  }
}
  1. 然后,当您使用 npm 运行 JavaScript 项目时,会自动检查该项目的代码:
$ npm run jss

要修复任何混乱或不一致的代码,请尝试以下命令:

$ npm run jss-fix

尽管 StandardJS 无法实现,但它依赖于 ESLint。StandardJS 使用的 ESLint 包如下所示:

  • eslint
  • standard-engine
  • eslint-config-standard
  • eslint-config-standard-jsx
  • eslint-plugin-standard

虽然 Prettier 是一个格式化器,但 StandardJS 与 ESLint 一样主要是一个 linter。如果您在使用 StandardJS 或 ESLint 的代码上使用--fix,然后使用 Prettier 再次运行它,您将看到任何长行(StandardJS 和 ESLint 忽略)都将由 Prettier 格式化。

For more information about this tool, visit https://standardjs.com/. You should also check out the summary of the standard JavaScript rules at https://standardjs.com/rules.html. You can find an example that uses StandardJS in /chapter-14/standard/ in our GitHub repository.

然而,如果您正在寻找一个更灵活、更可定制的解决方案,它位于这些工具之间,那么您可以为您的项目将 Prettier 和 ESLint 结合起来。让我们来看看下一节如何实现这一点。

集成 ESLint 和 Prettier

更漂亮和更漂亮是相辅相成的。我们可以使用 ESLint 将 Prettier 集成到工作流中。这允许您使用 Prettier 格式化代码,同时让 ESLint 专注于对代码进行 lint。因此,为了集成它们,首先,我们需要来自 ESLint 的eslint-plugin-prettier插件来使用 ESLint 下的“Prettier”。然后我们可以像往常一样使用 Prettier 来添加格式化代码的规则。

但是,ESLint 包含与格式相关的规则,这些规则可能与 Prettier 冲突,例如arrow-parensspace-before-function-paren,并且在一起使用时可能会导致一些问题。为了解决这些冲突问题,我们需要eslint-config-prettier配置来关闭与 Prettier 冲突的 ESLint 规则。让我们来看看如何在以下步骤中实现这一点:

  1. 通过 npm 安装eslint-plugin-prettiereslint-config-prettier
$ npm i eslint-plugin-prettier --save-dev
$ npm i eslint-config-prettier --save-dev
  1. .eslintrc.json文件中启用eslint-plugin-prettier的插件和规则:
{
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
}
  1. 通过在.eslintrc.json文件中使用eslint-config-prettier扩展 Prettier 的规则来覆盖 ESLint 的规则:
{
  "extends": ["prettier"]
}

请注意,值“【T0]”应该放在extends数组的最后,以便 Prettier 的配置可以覆盖 ESLint 的配置。此外,对于前面的配置,我们可以使用.eslintrc.js文件而不是 JSON 文件,因为我们可以在 JavaScript 文件中添加注释,这可能会有所帮助。因此,以下是我们在 ESLint 下使用 Prettier 的配置:

// .eslintrc.js
module.exports = {
  //...
  'extends': ['prettier']
  'plugins': ['prettier'],
  'rules': {
    'prettier/prettier': 'error'
  }
}
  1. package.json文件(或prettier.config.js文件)中配置 Prettier,以便 Prettier 不会在代码中打印分号,并且始终使用单引号:
{
  "scripts": {
    "lint": "eslint --ignore-path .gitignore .",
    "lint-fix": "eslint --fix --ignore-path .gitignore ."
  },
  "prettier": {
    "semi": false,
    "singleQuote": true
  }
}
  1. 在终端上运行npm run lint-fix一次性修复并格式化我们的代码。之后,您可以使用npx prettier命令单独使用 Prettier 再次检查代码,如下所示:
$ npx prettier --c "src/**/*"

然后,您应该在终端上获得以下结果:

Checking formatting...
All matched files use Prettier code style!

这意味着我们的代码没有格式问题,并且以更漂亮的代码样式成功地符合要求。将这两个工具结合在一起以满足我们的需求和偏好是很酷的,不是吗?但您仍然只完成了一半——让我们在下一节中为 Vue 和 Nuxt 应用应用这些配置。

You can find this integration example in /chapter-14/eslint+prettier/ in our GitHub repository.

在 Vue 和 Nuxt 应用中使用 ESLint 和 Pretter

eslint 插件 vue 插件是 vue 和 Nuxt 应用的官方 eslint 插件。它允许我们使用 ESLint 检查.vue文件中<template><script>块中的代码,以发现任何语法错误、错误使用 Vue 指令以及违反 Vue 样式指南的 Vue 样式。此外,我们正在使用 Prettier 来强制执行代码格式,因此安装eslint-plugin-prettiereslint-config-prettier就像我们在上一节中为我们喜欢的基本特定配置所做的那样。让我们通过以下步骤对所有这些进行排序:

  1. 使用 npm 安装此eslint-plugin-vue插件:
$ npm i eslint-plugin-vue --save-dev

您可能会得到一些警告:

npm WARN eslint-plugin-vue@5.2.3 requires a peer of eslint@^5.0.0
 but none is installed. You must install peer dependencies
  yourself.
npm WARN vue-eslint-parser@5.0.0 requires a peer of eslint@^5.0.0 
 but none is installed. You must install peer dependencies 
  yourself.

忽略它们,因为eslint-plugin-vue的最低要求是 ESLint v5.0.0 或更高版本和 Node.js v6.5.0 或更高版本,并且您应该已经拥有最新版本。

You can check out the minimum requirements at https://eslint.vuejs.org/user-guide/installation. Besides the Vue style guide, you should also check out the Vue rules at https://eslint.vuejs.org/rules/.

  1. 在 ESLint 配置文件中添加eslint-plugin-vue插件及其通用规则集:
// .eslintrc.js
module.exports = {
  extends: [
    'plugin:vue/recommended'
  ]
}
  1. 安装eslint-plugin-prettiereslint-config-prettier并将其添加到 ESLint 配置文件中:
// .eslintrc.js
module.exports = {
  'extends': [
    'plugin:vue/recommended',
    'plugin:prettier/recommended'
  ],
  'plugins': [
    'prettier'
  ]
}

但这些仍然不够。您可能需要配置一些 Vue 规则以符合您的偏好。让我们了解下一节可能要配置的一些默认 Vue 密钥规则。

For more information about this eslint-plugin-vue plugin, visit https://eslint.vuejs.org/. For Vue directives, please visit https://vuejs.org/v2/api/Directives, and for the Vue style guide, please visit https://vuejs.org/v2/style-guide/.

配置 Vue 规则

在本书中,我们只想覆盖四个默认的 Vue 规则。您只需在中的'rules'选项中添加首选规则。eslintrc.js文件,就像我们在上一节中为eslint-plugin-prettier插件所做的一样。让我们按照以下步骤进行操作:

  1. vue/v-on-style规则配置为“longform”,如下所示:
// .eslintrc.js
'rules': {
  'vue/v-on-style': ['error', 'longform']
}

vue/v-on-style规则对v-on指令样式强制执行shorthandlongform。默认设置为shorthand,例如:

<template>
  <!-- ✓ GOOD -->
  <div @click="foo"/>

  <!-- ✗ BAD -->
  <div v-on:click="foo"/>
</template>

但在本书中,longform是首选,如下例所示:

<template>
  <!-- ✓ GOOD -->
  <div v-on:click="foo"/>

  <!-- ✗ BAD -->
  <div @click="foo"/>
</template>

For more information about this rule, visit https://eslint.vuejs.org/rules/v-on-style.htmlvue-v-on-style.

  1. vue/html-self-closing规则配置为允许空白元素上的自动关闭标志,如下所示:
// .eslintrc.js
'rules': {
  'vue/html-self-closing': ['error', {
    'html': {
      'void': 'always'
    }
  }]
}

void 元素是在任何情况下都不允许包含内容的 HTML 元素,例如<br><hr><img><input><link><meta>。在编写 XHTML 时,必须自行关闭这些元素,例如<br/><img src="..." />。在本书中,我们希望允许这种情况,即使在 HTML5 中,/字符被认为是可选的。

根据vue/html-self-closing规则,您将由于自动关闭这些无效元素而获得错误,即使它旨在强制 HTML 元素中的自动关闭符号。这相当令人困惑,对吗?在 Vue.js 模板中,对于没有内容的元素,我们可以使用以下两种样式之一:

根据该规则,第一个选项将被拒绝,如下例所示:

<template>
  <!-- ✓ GOOD -->
  <MyComponent/>

  <!-- ✗ BAD -->
  <MyComponent></MyComponent>
</template>

但是,它也拒绝自动关闭的空心元素:

<template>
  <!-- ✓ GOOD -->
  <img src="...">

  <!-- ✗ BAD -->
  <img src="..." />
</template>

换句话说,在 Vue 规则中,无效元素不允许有自动关闭符号。因此,html.void选项的值默认设置为'never'。因此,如果您想在这些空白元素上允许自动关闭符号,如本书中所述,则将该值设置为'always'

For more information about this rule, visit https://eslint.vuejs.org/rules/html-self-closing.htmlvue-html-self-closing.

  1. vue/max-attributes-per-line规则配置为关闭此规则,如下所示:
// .eslintrc.js
'rules': {
  'vue/max-attributes-per-line': 'off'
}

vue/max-attributes-per-line规则旨在每行强制一个属性。默认情况下,当两个属性之间有一个换行符时,会将其视为两个属性之间的换行符。以下是此规则下的外观示例:

<template>
  <!-- ✓ GOOD -->
  <MyComponent lorem="1"/>
  <MyComponent
    lorem="1"
    ipsum="2"
  />
  <MyComponent
    lorem="1"
    ipsum="2"
    dolor="3"
  />

  <!-- ✗ BAD -->
  <MyComponent lorem="1" ipsum="2"/>
  <MyComponent
    lorem="1" ipsum="2"
  />
  <MyComponent
    lorem="1" ipsum="2"
    dolor="3"
  />
</template>

然而,这条规则与 Prettier 相冲突。我们应该让更漂亮的人来处理这样的案件,这就是为什么我们要取消这条规则。

For more information about this rule, visit https://eslint.vuejs.org/rules/max-attributes-per-line.htmlvue-max-attributes-per-line.

  1. 配置eslint/space-before-function-paren规则:
// .eslintrc.js
'rules': {
  'space-before-function-paren': ['error', 'always']
}

eslint/space-before-function-paren规则的目的是在函数声明的括号前加上空格。添加空间是 ESLint 的默认行为,也是 StandardJS 中定义的规则。请参见以下示例:

function message (text) { ... } // ✓ ok
function message(text) { ... } // ✗ avoid

message(function (text) { ... }) // ✓ ok
message(function(text) { ... }) // ✗ avoid

但是,根据上述规则,使用 Prettier 时会出现如下错误:

/middleware/auth.js
  1:24 error Delete · prettier/prettier

我们将忽略来自 Prettier 的错误,因为我们希望遵循 Vue 中的规则。但目前,Prettier 在中还没有禁用该功能的选项 https://prettier.io/docs/en/options.html 。如果您碰巧因为美观而删除了该空间,您可以在此 Vue 规则下通过将值设置为'always'将其添加回去。

For more information about this rule, visit https://eslint.org/docs/rules/space-before-function-paren and https://standardjs.com/rules.html.

  1. 由于 ESLint 默认只针对.js文件,因此在 ESLint 命令中包含带有--ext选项的.vue扩展名(或 glob 模式),以便在终端上使用前面的配置运行 ESLint:
$ eslint --ext .js,.vue src
$ eslint "src/**/*.{js,vue}"

您还可以使用scripts选项中的自定义命令和package.json文件中的.gitignore运行它,如下所示:

// package.json
"scripts": {
  "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
  "lint-fix": "eslint --fix --ext .js,.vue --ignore-path 
   .gitignore ."
}

// .gitignore
node_modules
build
nuxt.config.js
prettier.config.js

在对所有 JavaScript 和 Vue 文件进行 lint 时,ESLint 将忽略前面.gitignore代码段中定义的文件。通过 webpack 在热加载时删除文件是个好主意。只要将以下代码段添加到 Nuxt 配置文件中,即可在保存代码时运行 ESLint:

// nuxt.config.js
...
build: {
 extend(config, ctx) {
    if (ctx.isDev && ctx.isClient) {
      config.module.rules.push({
        enforce: "pre",
        test: /\.(js|vue)$/,
        loader: "eslint-loader",
        exclude: /(node_modules)/
      })
    }
  }
}

You can find an example that uses this plugin with ESLint in /chapter-14/eslint-plugin-vue/integrate/ in our GitHub repository.

正如您在本节和前几节中所看到的,在单个配置文件中混合使用 ESLint 和 Prettier 可能会有问题。你所遇到的麻烦可能不值得让他们“作为一个团队”一起工作。为什么不尝试在不耦合它们的情况下单独运行它们呢?让我们在下一节中了解如何为 Nuxt 应用执行此操作。

在 Nuxt 应用中分别运行 ESLint 和 Prettier

ESLint 和 Prettier 之间冲突的另一个可能解决方案,特别是在space-before-function-paren上,是根本不集成它们,而是分别运行它们来格式化和 lint 我们的代码。让我们通过以下步骤来实现这一点:

  1. package.json文件中分别为 Prettier 和 ESLint 创建脚本,如下所示:
// package.json
"scripts": {
"prettier": "prettier --check \"
 {components,layouts,pages,store,middleware,plugins}/**/*.{vue,js}
   \"", "prettier-fix": "prettier --write 
   {components,layouts,pages,store,middleware,plugins}
    /**/*.{vue,js}\"", "lint": "eslint --ext .js,.vue 
    --ignore-path .gitignore .",
   "lint-fix": "eslint --fix --ext .js,.vue --ignore-path
     .gitignore ."
}

所以现在我们可以完全忘记我们工作流中的eslint-plugin-prettiereslint-config-prettier配置。我们仍然保留了eslint-plugin-vue和我们在本章中已经配置的规则,但是从.eslintrc.js文件中完全删除了 Prettier:

// .eslintrc.js
module.exports = {
  //...
  'extends': [
    'standard',
    'plugin:vue/recommended',
    // 'prettier' // <- removed this.
  ]
}
  1. 当我们要分析代码时,首先运行 Prettier,然后运行 ESLint:
$ npm run prettier
$ npm run lint
  1. 同样,当我们想要修复格式和 lint 代码时,首先运行 Prettier,然后运行 ESLint:
$ npm run prettier-fix
$ npm run lint-fix

您可以看到,此解决方案通过这种方式使我们的工作流程越来越清晰。不再有冲突——这是轻而易举的事。含糖的

You can find an example that runs ESLint and Prettier separately in /chapter-14/eslint-plugin-vue/separate/ in our GitHub repository.

做得好。您已经完成了本章的第一个主要部分。我们希望您将开始或已经开始为您的 Vue 和 Nuxt 应用编写漂亮且可读的代码,并利用这些惊人的格式化器和 linter。随着您在本书中的 Nuxt 学习接近尾声,我们将在下一节向您介绍如何部署 Nuxt 应用。所以继续阅读。

部署 Nuxt 应用

除了代码筛选和格式化之外,应用部署也是 web 开发工作流程的一部分。我们需要将应用远程部署到服务器或主机上,以便公众可以公开访问应用。Nuxt 附带内置命令,我们可以使用这些命令部署应用。详情如下:

  • nuxt
  • nuxt build
  • nuxt start
  • nuxt generate

nuxt命令是您现在熟悉的在终端上使用的命令:

$ npm run dev

如果您在使用create-nuxt-app脚手架工具安装项目时打开 Nuxt 生成的package.json文件,您可以看到这些命令在"scripts"代码段中进行了预配置,如下所示:

// package.json
"scripts": {
  "dev": "nuxt",
  "build": "nuxt build",
  "start": "nuxt start",
  "generate": "nuxt generate"
}

您可以使用以下 Node.js 命令行在终端上启动命令:

$ npm run <command>

nuxt命令用于在localhost:3000上的开发服务器上进行热重新加载的开发,其他命令用于生产部署。让我们来看看如何在下一节中使用它们部署 Nuxt 应用。

You can also use common arguments such as --help with any of these commands. If you want to find out more, please visit https://nuxtjs.org/guide/commandslist-of-commands.

部署 Nuxt universal 服务器端渲染应用

我们希望通过阅读前面的所有章节,您知道您一直在开发 Nuxt universal服务器端渲染SSR应用。SSR 应用是在服务器端呈现应用内容的应用。这种应用需要一个特定的服务器来运行你的应用,比如 Node.js 和 Apache 服务器,而像你用 Nuxt 创建的通用 SSR 应用在服务器端和客户端都运行。这种应用也需要特定的服务器。Nuxt universal SSR 应用只需在终端上使用两个命令即可部署。让我们来看看如何在下列步骤中做到这一点:

  1. 通过 npm 启动nuxt build命令,使用 webpack 构建应用,并缩小 JavaScript 和 CSS:
$ npm run build

您应该获得以下生成结果:

> [your-app-name]@[your-app-name] start /var/path/to/your/app
> nuxt build
ℹ Production build
ℹ Bundling for server and client side
ℹ Target: server 
✓ Builder initialized
✓ Nuxt files generated
...
...
  1. 通过 npm 启动nuxt start命令,在生产模式下启动服务器:
$ npm run start

您应该获得以下启动状态:

> [your-app-name]@[your-app-name] start /var/path/to/your/app
> nuxt start

Nuxt.js @ v2.14.0

> Environment: production
> Rendering: server-side
> Target: server

Memory usage: 28.8 MB (RSS: 88.6 MB)

这就是部署 Nuxt universal SSR 应用所需的全部内容——只有两个命令行。这是小菜一碟,不是吗?但是,如果您没有 Node.js 服务器来托管您的应用,或者出于任何原因您只想将应用部署为静态站点,则可以从 Nuxt universal SSR 应用生成它。让我们在下一节中了解如何实现这一点。

部署 Nuxt 静态生成(预渲染)应用

为了从 Nuxt universal SSR 应用生成 Nuxt 静态生成的应用,我们将使用在本练习的前几章中创建的示例网站。您可以在我们的 GitHub 存储库的/chapter-14/deployment/sample-website/中找到此示例。因此,让我们通过以下步骤开始破解:

  1. 确保您在package.json文件中有以下"generate"运行脚本,如下所示:
"scripts": {
  "generate": "nuxt generate"
} 
  1. 将 Nuxt 配置文件中的target项目更改为static
// nuxt.config.js
export default {
  target: 'static'
}
  1. 通过在 Nuxt 配置文件中配置generate选项生成 404 页面:
// nuxt.config.js
export default {
  generate: {
    fallback: true
  }
}

Nuxt 不会生成自定义 404 页面,也不会生成默认页面。如果您想在静态应用中包含此页面,可以在配置文件的generate选项中设置fallback: true

  1. 通过 npm 启动nuxt generate命令,构建应用并为每条路线生成 HTML 文件:
$ npm run generate

Nuxt 有一个爬虫程序,可以扫描链接并自动为您生成动态路由及其异步内容(使用asyncDatafetch方法呈现的数据)。因此,您应该按照以下方式获取应用的每条路径:

ℹ Generating output directory: dist/
ℹ Generating pages with full static mode
✓ Generated route "/contact"
✓ Generated route "/work-nested"
✓ Generated route "/about"
✓ Generated route "/work"
✓ Generated route "/"
✓ Generated route "/work-nested/work-sample-4"
✓ Generated route "/work-nested/work-sample-1"
✓ Generated route "/work-nested/work-sample-3"
✓ Generated route "/work-nested/work-sample-2"
✓ Generated route "/work/work-sample-1"
✓ Generated route "/work/work-sample-4"
✓ Generated route "/work/work-sample-2"
✓ Generated route "/work/work-sample-3"
✓ Client-side fallback created: 404.html
i Ready to run nuxt serve or deploy dist/ directory 

Note that you will still need to use generate.routes for generating routes that the crawler cannot detect.

  1. 如果你查看你的项目根目录,你会发现一个由 Nuxt 生成的/dist/文件夹,里面有你将应用部署到静态托管服务器所需的一切。但在此之前,您可以在终端上使用nuxt serve命令从/dist/目录测试生产静态应用:
$ npm run start

您应该在终端上获得以下输出:

Nuxt.js @ v2.14.0 

> Environment: production
> Rendering: server-side
> Target: static
Listening: http://localhost:3000/

ℹ Serving static application from dist/ 
  1. 现在,您可以将浏览器指向localhost:3000并看到该应用正在像 SSR 一样运行,但实际上,它是一个静态生成的应用。

我们将在下一章回到这个配置,部署 Nuxt单页应用SPA应用。您可以看到,这种类型的部署只需要做一点工作,完全值得,因为“静态”部署应用有很多好处,例如您可以将静态文件托管在静态托管服务器上,这比 Node.js 服务器相对便宜。我们将在下一章向您展示如何在这种服务器上为静态站点提供服务,就像GitHub 页面一样。尽管“静态”部署 Nuxt universal SSR 应用有好处,但您必须考虑以下注意事项:

  • 提供给asyncDatafetch方法的 Nuxt 上下文将丢失 Node.js 中的 HTTPreqres对象。
  • nuxtServerInit操作在商店中不可用。

因此,如果您有一个 Nuxt 应用严重依赖前面列表中的这些项目,那么将 Nuxt universal SSR 应用生成为静态文件可能不是一个好主意,因为它们是服务器端功能。但是,我们可以用客户端 cookies 来模拟客户端的nuxtServerInit操作,我们也将在下一章中向您展示。但现在,让我们转到下一节,了解您可以选择哪种托管服务器来托管 Nuxt 应用。

If you want to find out more about the generate property/option and other options, such as the fallback and routes options, that you can configure with this property, please visit https://nuxtjs.org/api/configuration-generate.

在虚拟专用服务器上托管 Nuxt universal SSR 应用

在托管 Node.js 应用时,虚拟专用服务器VPS)和专用服务器是更好的选择,因为您可以完全自由地为应用设置 Node.js 环境。每当 Node.js 发布新版本时,您也应该更新您的环境。只有使用 VPS 服务器,您才能随时升级和调整您的环境。

如果您正在寻找 Linux 服务器,则 Linode 或 Vultr 等 VPS 提供商提供价格合理的 VPS 托管服务,并将从头开始安装所需的基础设施。这些 VPS 提供商给你的是一个空的虚拟机,带有你喜欢的 Linux 发行版,例如 Ubuntu。构建所需基础设施的过程与安装 Node.js、MongoDB、MySQL 等的过程相同,而您的本地计算机上刚刚安装了 Linux 发行版。有关这些 VPS 提供商的更多信息,请访问以下链接:

在您将 Node.js 环境和基础设施设置好以满足您的需求后,您可以将您的 Nuxt 应用上传到此类主机上,然后通过这些主机提供商提供的Secure ShellSSH功能在您的终端上非常轻松地构建和启动应用:

$ npm run build
$ npm run start

共享主机服务器呢?让我们来看看下一节你要选择的内容。

在共享托管服务器上托管 Nuxt universal SSR 应用

请记住,并非所有主机都是 Node.js 友好的,与 PHP 的共享托管服务器相比,Node.js 的共享托管服务器相对较少。但所有共享托管服务器都是一样的——您可以做的事情通常受到严格限制,您必须遵守提供商设置的严格规则。您可以查看以下共享托管服务器提供商:

例如,在共享托管服务器中,在 Recreal hosting 中,很可能无法运行 Nuxt 命令来启动应用。相反,您需要向服务器提供一个应用启动文件,该文件必须被称为app.js并放置在您的项目根目录中。

如果您想要回收主机,您可以在使用他们的测试环境 https://stateu.org/ 看看它对你有什么作用。但请记住,高级设置是不可能的。好消息是 Nuxt 提供了一个 Node.js 模块nuxt-start,可以在这样的共享托管服务器上以生产模式启动 Nuxt 应用。因此,让我们通过以下步骤了解如何:

  1. 通过 npm 本地安装nuxt-start
$ npm i nuxt-start
  1. 使用以下代码在项目根目录中创建一个app.js文件以启动 Nuxt 应用:
// app.js
const { Nuxt } = require('nuxt-start')
const config = require('./nuxt.config.js')

const nuxt = new Nuxt(config)
const { host, port } = nuxt.options.server

nuxt.listen(port, host)

或者,你可以使用 Express 或膝关节炎来启动 NUXT 应用。以下示例假定您正在使用 Express:

// app.js
const express = require('express')
const { Nuxt } = require('nuxt')
const app = express()

let config = require('./nuxt.config.js')
const nuxt = new Nuxt(config)
const { host, port } = nuxt.options.server

app.use(nuxt.render)
app.listen(port, host)

在这段代码中,我们导入了expressnuxt模块以及nuxt.config.js文件,然后使用 Nuxt app 作为中间件。如果你使用膝关节炎,这是一样的,你只需要使用 Nuxt 作为中间件。

  1. 将 Nuxt 应用上载到包含此app.js文件的服务器,并按照主机的说明通过 npm 安装应用依赖项,然后运行app.js启动应用。

这就是你需要做的。这些共享主机服务器存在一些限制。在这些服务器中,您对 Node.js 环境的控制较少。但是,如果遵循服务器提供商设置的严格规则,您可以启动并运行您的通用 SSR Nuxt 应用。

You can find the preceding sample code and others in /chapter-14/deployment/shared-hosting/reclaimhosting.com/ in our GitHub repository for hosting the Nuxt universal SSR app at Reclaim Hosting.

For more information about nuxt-start, please visit https://www.npmjs.com/package/nuxt-start.

您可以看到它并不完美,也有其局限性,但如果您正在寻找共享主机,它是合理的。如果这不适合您,那么最后一个选项是使用静态站点托管服务器,我们将在下一节中看到。

在静态站点托管服务器上托管 Nuxt 静态生成的应用

使用此选项,您将不得不丢失 Nuxt 的服务器端。但好消息是,有许多流行的主机可以托管静态生成的 Nuxt 应用,您可以在几乎任何主机上快速在线提供服务。让我们通过以下步骤了解如何:

  1. 在 Nuxt 配置文件中将server更改为static作为目标,如下所示:
// nuxt.config.js
export default {
  target: 'static'
}
  1. 通过 npm 本地启动nuxt generate命令,为您的 Nuxt 应用生成静态文件:
$ npm run generate
  1. 将 Nuxt 生成的/dist/文件夹中的所有内容上传到主机。

以下列表详细说明了您可以从中选择的主机。Nuxt 站点上详细记录了它们的部署过程。您应该在查看 Nuxt 常见问题解答 https://nuxtjs.org/faq 要查看部署示例并了解如何将静态生成的 Nuxt 应用部署到这些特定主机:

我们将在下一章指导您在 GitHub 页面上部署 Nuxt SPA 应用。但就目前而言,本章关于格式化、linting 和部署 Nuxt universal SSR 应用的内容到此结束。让我们总结一下您在本章学到的知识。

**# 总结

做得好。你已经走了这么远。这是一段相当长的旅程。在本章中,我们介绍了 JavaScript linter 和格式化器,特别是用于 Nuxt 应用和一般 JavaScript 应用的 ESLint、Prettier 和 StandardJS。您已经了解了如何根据自己的需要和偏好安装和配置它们。我们还介绍了用于部署 Nuxt 应用的 Nuxt 命令以及可用于托管 Nuxt 应用的选项,无论是通用 SSR 应用还是静态生成的站点。

在下一章中,我们将学习如何使用 Nuxt 创建 SPA 并将其部署到 GitHub 页面。您将看到传统水疗与 Nuxt 水疗之间的细微差别(我们称之为Nuxt 水疗。我们将指导您完成在 Nuxt 中设置 SPA 开发环境的过程,重构您在前几章中创建的 universal SSR Nuxt authentication app,并将其转换为 Nuxt SPA 和静态生成的 Nuxt SPA。最后,您将学习将静态生成的 SPA 部署到 GitHub 页面。所以继续阅读。**