编辑页面

升级到 Sails v1.0

Sails v1.0 来了!请继续阅读以获取此版本中更改的高级概述,并了解您可能希望在应用中利用的一些新功能。

关于重大更改的说明

#

在开发此版本的 Sails 期间,我们做出的许多决策都优先考虑了更好的开发者体验而非向后兼容性。因此,升级到 Sails 1.0 将涉及处理比以前版本更多的重大更改。但是,完成后,您在 Sails 中使用的功能更有可能得到其作者和维护人员的充分理解并几乎每天都在使用。

有关 1.0 中许多重大更改背后的理念的更多信息,您可以阅读 Mike McNeil 的深入解释 此处

使用自动化工具升级现有应用

#

准备好将您现有的 v0.12.x Sails 应用升级到 1.0 版了吗?首先,我们建议您使用 Sails 1.0 升级工具,该工具将帮助完成一些最常见的迁移任务。要使用该工具,请首先使用 npm install -g sails@^1.0.0 在全局安装 Sails 1.0,然后运行 sails upgrade。工具运行后,它将为您创建一个报告,其中列出了需要手动升级的剩余项目。

手动升级现有应用

#

以下清单涵盖了最可能影响大多数应用的更改。

如果您的应用在遵循此清单后启动时仍然存在错误或警告,或者如果您看到意外情况,请返回此文档并查看页面下方。(可能适用涵盖各种应用组件的指南之一。)

我们做了很多工作来使升级过程尽可能无缝,尤其是在您在控制台上看到的错误和警告方面。但是,如果您遇到问题或对以下任何更改有任何疑问,请随时 访问 Sails 社区 Gitter 频道。(如果您的公司使用 Sails Flagship,您也可以 此处 直接与 Sails 核心团队聊天。)

tl;dr 清单:升级到 1.0 版时您必须执行的操作

#

升级工具尽其所能帮助解决其中一些项目,但它不会为您更改特定于应用的代码!

步骤 0:检查您的 Node 版本!
#

如果您的应用需要支持低于 v4 的 Node 版本,则您将无法升级到 Sails 1.0,因为 Sails 1.0 不再支持 Node v0.x。Sails 1.0 支持的 Node 最早版本是 Node 4.x。

步骤 1:安装钩子和更新依赖项
#

Sails v1 引入了 自定义构建。这意味着某些核心钩子现在作为应用的直接依赖项安装,使您可以更好地控制依赖项并使 npm install sails 运行速度大大加快。因此,您需要做的第一件事是安装您正在使用的核心钩子。(并且在您这样做的时候,请务必更新下面列表中提到的其他依赖项。)

步骤 2:更新配置
#

Sails v1 在应用配置方面提供了一些改进。例如,现在可以将 lodash 和 async 的自动安装自定义到任何版本,并且视图引擎配置语法现在与 Express v4+ 的语法一致。但是,配置方面最重大的变化与 Sails v1 中最令人兴奋的新功能之一相关:数据存储。为了确保您正确升级数据库和其他设置的配置,请务必仔细阅读以下步骤并应用必要的更改。

步骤 3:修改客户端代码以适应新的蓝图 API
#

除了扩展到包含一个新的端点之外,蓝图 API 还有一些细微但破坏性的更改,您可能需要对客户端代码进行更改。

步骤 4:采用 Waterline ORM 的新版本
#

Waterline ORM (v0.13) 的新版本引入了对 SQL 事务的完全支持、能够在结果集中包含或省略属性(也称为“投影”)、动态数据库连接以及对查询行为的更广泛的粒度控制。它还包括一个主要的稳定性和性能改进,这带来了一些使用方面的重大更改。以下要点涵盖了您在 Waterline 升级过程中可能遇到的最常见问题。

其他重大更改

#

以上升级指南提供了Sails贡献者在将不同应用从版本0.12升级到版本1.0时遇到的最常见的升级问题。但是,每个应用都不同,因此我们建议您也通读以下要点。并非所有讨论的更改都一定会应用于您的应用,但某些更改可能会应用。

数据库配置更改

#

嵌套创建和更新

#

模型配置更改

#
tl;dr
#

从您的模型中删除任何autoPKautoCreatedAtautoUpdatedAt属性,并将以下内容添加到您的config/models.js文件中

attributes: {
    createdAt: { type: 'number', autoCreatedAt: true, },
    updatedAt: { type: 'number', autoUpdatedAt: true, },
    id: { type: 'number', autoIncrement: true}, // <-- for SQL databases
    id: { type: 'string', columnName: '_id'}, // <-- for MongoDB
  }
不再支持autoPK顶级属性
#

此属性以前用于指示Waterline是否应创建id属性作为模型的主键。从Sails v1.0 / Waterline 0.13开始,Waterline将不再在后台创建任何属性。相反,必须显式定义id属性。还有一个新的顶级模型属性称为primaryKey,可以将其设置为应用作模型主键的属性的名称。此值默认为每个模型的id,因此通常您不必自己设置它。

autoUpdatedAtautoCreatedAt模型设置现在是属性级属性
#

这些属性以前用于指示Waterline是否应为模型创建createdAtupdatedAt时间戳。从Sails v1.0 / Waterline 0.13开始,Waterline将不再在后台创建这些属性。相反,如果要使用它们,则必须显式定义createdAtupdatedAt属性。通过将autoCreatedAt: trueautoUpdatedAt: true添加到属性定义中,您可以指示Waterline在创建或更新记录时将该属性设置为当前时间戳。根据这些属性的类型,时间戳将采用以下两种格式之一生成

此外,对于任何属性,如果在Waterline条件的where子句中、作为新记录或在.update()查询中要设置的值中传递new Date(),则会根据属性的类型应用相同的规则。如果属性为type: 'json',则使用后一种方法。

.create().createEach().update().destroy()结果的更改

#

从Sails v1.0 / Waterline 0.13开始,.create().createEach().update().destroy()的默认结果已更改。

为了鼓励更好的性能和更轻松的可扩展性,.create()不再发送回已创建的记录。类似地,.createEach()不再发送回已创建记录的数组,.update()不再发送回已更新记录的数组,.destroy()不再发送回已销毁记录。相反,.exec()回调的第二个参数现在为undefined(或者如果您使用的是Promise,则为.then()的第一个参数)。

这通过删除不必要的find查询使您的应用程序更高效,并且可以利用.update().destroy()修改大型数据集中的许多不同记录,而不是回退到更低级的原生查询。

您仍然可以通过使用fetch方法指示适配器发送回单个查询的已创建或修改的记录。例如

Article.update({
  category: 'health-and-wellness',
  status: 'draft'
})
.set({
  status: 'live'
})
.fetch()
.exec(function(err, updatedRecords){
  //...
});

如果更改所有应用程序查询的前景看起来令人生畏,则您可以利用一个临时的便利功能。为了简化升级现有应用程序的过程,您可以告诉Sails/Waterline为应用程序的所有.create()/.createEach()/.update()/.destroy()查询获取已创建/更新/销毁的记录。只需编辑config/models.js中的应用程序范围模型设置

fetchRecordsOnUpdate: true,
fetchRecordsOnDestroy: true,
fetchRecordsOnCreate: true,
fetchRecordsOnCreateEach: true,

就是这样!但是,为了提高性能并使您的应用程序面向未来,您应该检查所有.create().createEach().update().destroy()调用,并在可能的情况下添加.fetch()。对这些模型设置的支持最终将在Sails v2中删除。

Waterline条件用法的更改

#
混合 where 子句的支持更改
#

不再支持包含混合 where 子句的查询条件字典。例如,不要使用

{
  username: 'santaclaus',
  limit: 4,
  select: ['beardLength', 'lat', 'long']
}

而应该使用

{
  where: { username: 'santaclaus' },
  limit: 4,
  select: ['beardLength', 'lat', 'long']
}

请注意,您仍然可以使用 { username: 'santaclaus' } 作为 { where: { username: 'santaclaus' } } 的简写,只是不能将其他顶级查询条件子句(如 limit)与约束条件(例如 username)混合使用。

对于使用 Waterline 的可链式延迟对象构建查询条件的地方,不用担心这个问题——它已经为您处理好了。

安全

#

使用 Sails 1.0 创建的新应用将包含一个 config/security.js 文件,而不是单独的 config/cors.jsconfig/csrf.js 文件。从早期版本迁移的应用可以保留其现有文件,只要它们执行以下升级

'POST /some-thing': { action: 'do-a-thing', csrf: false },
'GET /csrfToken': {
  action: 'security/grant-csrf-token',
  cors: {
    allowOrigins: ['http://foobar.com', 'https://owlhoot.com']
  }
}

视图

#

为了获得最大的灵活性,Consolidate 不再与 Sails 捆绑在一起。如果您使用除 EJS 之外的视图引擎,您可能需要将 Consolidate 作为应用的直接依赖项进行安装。然后,您可以像这样在 config/views.js 中配置视图引擎

extension: 'swig',
getRenderFn: function() {
  // Import `consolidate`.
  var cons = require('consolidate');
  // Return the rendering function for Swig.
  return cons.swig;
}

在 Sails 1.0 中,向视图引擎添加自定义配置变得更加容易

extension: 'swig',
getRenderFn: function() {
  // Import `consolidate`.
  var cons = require('consolidate');
  // Import `swig`.
  var swig = require('swig');
  // Configure `swig`.
  swig.setDefaults({tagControls: ['{?', '?}']});
  // Set the module that Consolidate uses for Swig.
  cons.requires.swig = swig;
  // Return the rendering function for Swig.
  return cons.swig;
}

请注意,对布局的内置支持 仍然适用于默认的 EJS 视图,但 Sails 1.0 不包含对其他视图引擎(例如 Handlebars 或 Ractive)的布局支持。

资源型发布/订阅

#

代替已移除的方法,您应该使用新的 .publish() 方法,或低级别的 sails.sockets 方法。请记住,与 .message() 不同,.publish() 不会将您的数据包装在一个包含记录 ID 的信封中,因此——如果很重要——您需要自己将 ID 作为数据的一部分包含在内。例如,在 Sails v0.12.x 中,User.message(123, {owl: 'hoot'}) 将导致以下通知广播给客户端

{
  verb: 'messaged',
  id: 123,
  data: {
    owl: 'hoot'
  }
}

相反,在 Sails v1.0 中,User.publish(123, {owl: 'hoot'}) 将简单地广播

{
  owl: 'hoot'
}

替换自定义蓝图

#

默认情况下,不再可以将文件添加到 api/blueprints/ 中,并将其自动用作所有模型的蓝图操作。但是,可以通过安装 sails-hook-custom-blueprints 轻松复制此行为。

Express 4

#

Sails 1.0 将内部 Express 服务器从版本 3 更新到版本 4(感谢 @josebaseba 的出色工作)。此更改主要与 Sails 框架的可维护性有关,并且应该对您的应用透明。但是,有一些差异值得注意

customMiddleware: function(app) {
  var passport = require('passport');
  app.use(passport.initialize());
  app.use(passport.session());
}

为以下内容

var passport = require('passport');
middleware: {
  passportInit: passport.initialize(),
  passportSession: passport.session()
},

确保将 passportInitpassportSession 插入到 config/http.js 中的 middleware.order 数组中。

响应方法

#

i18n

#

Sails 1.0 从使用 i18n 切换到更轻量级的 i18n-2 模块。绝大多数用户应该不会在他们的应用中看到任何区别。但是,如果您正在使用 sails.config.i18n.updateFiles 选项,请注意此选项不再受支持;相反,区域设置文件将在开发模式下始终更新,在生产模式下永远不会更新。如果这是一个问题,或者您错过了 i18n 模块中的某些其他功能,您可以安装 sails-hook-i18n 以恢复到 Sails 1.0 之前的功能。

如果您的 0.12 应用由于使用了 i18n 功能而在升级期间遇到问题,请参阅 #4343 获取更多故障排除技巧。

WebSockets

#

所有使用 websockets 的 Sails 1.0 项目都必须安装最新的 sails-hook-sockets 依赖项(npm install --save sails-hook-sockets)。此版本的 sails-hook-sockets 在几个方面与以前的版本不同

Grunt

#

以前是 Sails 核心一部分的 Grunt 任务管理功能现已移至单独的 sails-hook-grunt 模块。现有应用只需 npm install --save sails-hook-grunt 即可继续使用 Grunt。但是,通过修改应用的 Gruntfile.js,您可以利用 sails-hook-grunt 包含所有以前必须在项目级别安装的 grunt-contrib 模块这一事实。新的 Gruntfile.js 包含

module.exports = function(grunt) {

  var loadGruntTasks = require('sails-hook-grunt/accessible/load-grunt-tasks');

  // Load Grunt task configurations (from `tasks/config/`) and Grunt
  // task registrations (from `tasks/register/`).
  loadGruntTasks(__dirname, grunt);

};

假设您没有自定义应用中的 Gruntfile,您可以将 Gruntfile.js 替换为此代码,然后安全地运行

npm uninstall --save grunt-contrib-clean
npm uninstall --save grunt-contrib-coffee
npm uninstall --save grunt-contrib-concat
npm uninstall --save grunt-contrib-copy
npm uninstall --save grunt-contrib-cssmin
npm uninstall --save grunt-contrib-jst
npm uninstall --save grunt-contrib-less
npm uninstall --save grunt-contrib-uglify
npm uninstall --save grunt-contrib-watch
npm uninstall --save grunt-sails-linker
npm uninstall --save grunt-sync
npm uninstall --save grunt-cli

以从项目中移除这些依赖项。

故障排除

#
启动时仍然显示 v0.12?
#

确保您已在项目中本地安装了 sails,并且您正在使用 v1 版本的命令行工具。

要全局安装 v1.0,请运行 npm install sails@^1.0.0 -g。要为特定 Sails 应用安装它,请 cd 到该应用的目录中,然后运行 npm install sails@^1.0.0 --save。(本地安装后,请务必也安装必要的 hook——见上文。)

需要升级帮助?

如果您的公司有预算,请考虑购买 旗舰支持。这是支持您每天使用的开源工具持续发展的好方法。它还为您提供了一条与 Sails 核心团队联系的额外途径。

升级