Appearance
离线
¥Offline
Who maintains the package
- Jam
这是个什么包?
¥What is this package?
离线访问是一种让你的 Meteor 应用具有离线功能并使其感觉即时的简单方法。其主要功能如下:
¥Offline is an easy way to give your Meteor app offline capabilities and make it feel instant. Its key features are:
离线访问 – 将 Minimongo 数据保存在 IndexedDB 中,以便离线访问,并在重新连接时立即重新加载。
¥Offline access – Saves Minimongo data in IndexedDB for offline access and instant reloading when reconnected.
自动同步 – 重新连接后自动同步离线操作。
¥Automatic syncing – Syncs offline actions automatically once reconnected.
跨标签同步 – 离线时在多个标签页之间保持更改同步。
¥Cross-Tab syncing – Keeps changes in sync across multiple tabs while offline.
无缝同步 – 重新连接时与服务器同步数据。
¥Seamless reconciliation – Reconciles data with the server when reconnected.
如何下载?
¥How to download it?
将软件包添加到你的应用
¥Add the package to your app
bash
meteor add jam:offline
来源
¥Sources
如何使用?
¥How to use it?
保持数据离线
¥Keeping data offline
默认情况下,所有使用 Offline.config 全局默认值的集合都将保留离线数据,无需任何配置。要更改特定集合保留的数据,请在客户端和服务器端导入的文件中为该集合定义 .keep
。
¥By default, offline data will be kept for all collections using the global defaults in Offline.config without any configuration needed. To change the data that is kept for a specific collection, define .keep
for the collection in a file that's imported on both client and server.
如果你不想保留所有集合,请务必配置 keepAll: false
。有关更多详细信息,请参阅 配置。
¥If you don't want all collections to be kept, be sure to configure keepAll: false
. See Configuring for more details.
.keep
接受 filter
、sort
和 limit
选项,与 .find
类似。例如:
¥.keep
accepts a filter
, and sort
and limit
options much like a .find
. For example:
js
const Todos = new Mongo.Collection('todos');
Todos.keep({ $or: [ { isPrivate: { $ne: true } }, { owner: Meteor.userId() } ]}, { limit: 200 }) // this will override any global defaults
如果你对应该保留的内容有特定的限制,例如像上面示例中那样对文档的权限,这些限制应该包含在 .keep
过滤器中。请注意,当用户重新上线时,此过滤器将用于与服务器进行协调。通常,建议你仅在绝对需要时使用 .keep
过滤器。
¥If you have specific restrictions on what should be kept, e.g. permissions to a document like in the example above, these should be included in the .keep
filter. Be aware that when the user comes back online, this filter will be used to reconcile with the server. In general, it's recommended that you only use the .keep
filter where absolutely needed.
Note
:如果需要,你可以在 .keep
过滤器中使用 Meteor.userId()
。
¥Note
: You can use Meteor.userId()
in your .keep
filter if needed.
清除特定集合的离线数据
¥Clearing offline data for a specific collection
如果你需要清除特定集合的离线数据,请调用 clear
:
¥If you ever need to clear offline data for a specific collection, call clear
:
js
Todos.clear();
清除所有离线数据
¥Clearing all offline data
如果你需要彻底清除所有离线数据,可以使用 clearAll
:
¥If you ever need to completely clear all offline data, you can use clearAll
:
js
import { clearAll } from 'meteor/jam:offline';
clearAll();
离线时排队方法
¥Queuing methods when offline
当用户离线时,你可以使用 queueMethod
将他们执行的任何操作排队,以便在他们重新上线时重放:
¥When a user is offline, you can queue any actions they take for replay when they come back online using queueMethod
:
js
import { queueMethod } from 'meteor/jam:offline';
if (!Meteor.status().connected) { // check that the user is offline
queueMethod(name, arg1, arg2...) // the arguments should be the same form that you'd use for Meteor.callAsync
}
其中 name 是方法的名称,参数是该方法所需的参数。你仍然需要在离线状态下调用该方法,并且建议你将 Meteor.applyAsync 与选项 noRetry: true
一起使用,以避免使用 Meteor 的内置重试机制,因为我们将单独处理重放。为了使其按预期工作,你调用的方法应该是同构的,以便客户端可以使用它们。
¥where name is the method's name and the arguments are what the method expects. You'll still want to call the method when offline and it's recommended that you use Meteor.applyAsync with the option noRetry: true
to avoid using Meteor's built-in retry mechanism since we'll be handling replay separately. For this to work as intended, the methods that you call should be isomorphic so that they're availble to the client.
Note
:如果你使用的是 jam:method,系统会自动为你处理重放的排队方法。🎉
¥Note
: If you're using jam:method, queuing methods for replay is handled automatically for you. 🎉
Note
:当将涉及 insert
的方法排队到集合中时,请确保该方法返回新文档的 _id
。通过这样做,你可以确保在离线状态下对文档进行的任何后续更改都能得到正确处理。
¥Note
: When queuing methods than involve an insert
to a collection, make sure the method returns the new document's _id
. By doing this, you ensure that any subsequent changes made to the document while still offline are handled correctly.
自动同步
¥Auto syncing
默认情况下,当用户重新上线时,该包会自动同步。这包括:
¥By default, the package auto syncs when the user comes back online. This includes:
重放队列方法
¥Replaying queued methods
由于与配置的
filter
或集合的.keep
过滤器不匹配,移除不再属于该集合的每个离线数据¥Removing offline data for each collection that no longer belongs because it doesn't match the configured
filter
or the collection's.keep
filter
这种顺序重放同步策略的好处是,你方法中包含的任何业务逻辑都将得到尊重。例如,如果用户在离线状态下更改了文档,但失去了对该文档的权限,那么当他们重新上线时,尝试重放时,该权限将得到尊重。如果自动同步期间出现任何错误,它们将在 handleSyncErrors
函数中提供。你可以使用它来让用户知道他们的更改失败了。有关如何自定义此功能的更多详细信息,请参阅 配置。
¥The benefit of this sequential-replay syncing strategy is any business logic contained in your methods will be respected. For example, if a user makes changes to a document but loses permission to it while offline, when they come back online, that permission will be respected when the attempted replay occurs. If there are any errors during auto sync, they will be made available in the handleSyncErrors
function. You can use it to make your user aware that their changes failed. See Configuring for more details on how to customize this.
与服务器协调时,此包假定你将使用以下机制之一删除文档:
¥When reconciling with the server, this package assumes that you'll use one of the following mechanisms when removing documents:
archive
。使用此机制,当文档从其原始集合中删除时,它将被放置在archive
集合中。如果你的应用尚未采用归档机制,请查看 jam:archive 软件包以简化此操作。只需添加jam:archive
包,你无需进行任何其他配置。¥
archive
. With this mechanism, when a document is removed from its original collection, it's placed in anarchive
collection. If your app doesn't already employ an archive mechanism, check out the jam:archive package to make this easy. By simply adding thejam:archive
package, you won't need to do any further configuration.
否则,请务必查看 archive
配置选项。Note
:假设你的 archive
集合中的数据将包含根级别的原始文档数据,例如:
¥Otherwise, be sure to check out the archive
configuration options. Note
: it's assumed that the data in your archive
collection will include the original document data at the root level, e.g.:
js
{
_id, // auto-generated by Meteor as with other collection _ids
_collection, // the name of the collection, e.g. 'todos', that the doc belonged to originally
archivedAt, // the timestamp when the document was removed from its original collection and inserted into the archive
id, // the original doc _id renamed to prevent conflict with the auto-generated one above. when restored, it will be renamed back to _id automatically by this package
/*
...rest of original doc
*/
}
soft delete
。如果你的应用尚未采用软删除机制,请查看 jam:soft-delete 软件包以简化此操作。如果你使用deleted
以外的其他名称作为软删除的标志名称,请务必正确配置filter
。有关更多详细信息,请参阅 配置。¥
soft delete
. If your app doesn't already employ a soft delete mechanism, check out the jam:soft-delete package to make this easy. If you're using something other thandeleted
as the flag name for your soft deletes, be sure to configurefilter
appropriately. See Configuring for more details.
要了解自动同步何时进行,你可以使用 isSyncing()
,它是一个响应式变量。
¥To know when an auto sync is processing, you can use isSyncing()
which is a reactive variable.
js
import { isSyncing } from 'meteor/jam:offline';
isSyncing(); // you can wrap this in a Tracker.autorun to detect when it changes
如果你不想使用自动同步提供的行为,请务必配置 autoSync: false
。当 autoSync
为 false 时,Minimongo 在用户断开连接时的数据将保持离线状态,因此你仍然可以在重新连接时享受更快的重新加载速度,但你需要负责设计任何所需的同步逻辑。如果用户未刷新页面,并且短暂断开/重新连接,那么你仍然可以受益于 Meteor 内置的方法重试机制。但如果用户刷新或退出应用并稍后返回,则离线时执行的任何操作都将丢失。
¥If you prefer not to have the behavior provided by auto sync, be sure to configure autoSync: false
. When autoSync
is false, Minimongo data from when the user disconnects will be kept offline so you still benefit from faster reloads on reconnects but you'll be responsible for designing any syncing logic needed. If the user hasn't refreshed the page and has a brief disconnect / reconnect, then you'll still benefit from Meteor's built-in retry mechanism for methods. But if they do refresh or exit the app and come back later, any actions performed while offline will be lost.
我认为如果能更好地支持自定义同步就更好了。如果你有任何想法,请告诉我。目前,我不确定哪些原语对你最有用。
¥I think it would be great to have better support for custom syncing. If you have ideas here, let me know. At this time, I'm not sure what primitives would be most useful for you.
配置(可选)
¥Configuring (optional)
如果你喜欢默认设置,则无需配置任何内容。但使用此包的方式有一定的灵活性。你可能需要特别注意 filter
和 handleSyncErrors
,以定制用户体验。
¥If you like the defaults, then you won't need to configure anything. But there is some flexibility in how you use this package. You may want to pay special attention to filter
and handleSyncErrors
to customize the experience for your users.
以下是全局默认值:
¥Here are the global defaults:
js
const config = {
filter: /** {} or { deleted: false } **/ // filter the documents to keep across all collections. if you're not using jam:archive or don't have the archive config below set, it will assume you're using soft deletes.
sort: { updatedAt: -1 }, // keep the most recent documents assuming you have an updatedAt on each doc. if you're using a different field name for timestamps, you'll want to change this.
limit: 100, // limit offline documents to a max of 100 for each collection
keepAll: true, // keep data for offline use for all collections using the global filter, sort, limit. to keep data for only certain collections, set this to false and then use collection.keep() for the collections you want to use offline.
autoSync: true, // auto sync changes made offline when the user comes back online
handleSyncErrors: async ({ replayErrors, keepErrors }) => {
if (replayErrors) console.error('replay', replayErrors); // if there are errors when the Meteor methods are replayed, they will be in array here with the name of the method, the method's args, and the error itself. you can use it to alert your user, logging purposes, etc.
if (keepErrors) { // when syncing, if you're using a .keep filter or you have a global filter in the config that isn't an empty object, and there are errors reconciling with the server, they will be in an array here with the name of the collection and the error itself. you can customize how you handle these. by default, we clear the offline database for the collection since it could have stale data and reload the page.
await Promise.allSettled(keepErrors.map(({ name }) => clear(name)));
console.error('keep', keepErrors)
}
return;
},
...(Archive && { // Archive is provided by jam:archive. if you're using a different archive mechanism, you'll need to configure these manually
archive: {
name: 'archives',
collectionKey: '_collection',
primaryIdKey: 'id',
timestampKey: 'archivedAt'
}
})
};
要更改全局默认值,请使用:
¥To change the global defaults, use:
js
// put this in a file that's imported on both the client and server
import { Offline } from 'meteor/jam:offline';
Offline.configure({
// ... change the defaults here ... //
});
添加 Service Worker
¥Adding a service worker
你可能还需要添加一个 Service Worker 来缓存你的 HTML、CSS 和 JavaScript,以便你的用户即使不小心点击了刷新,也可以继续离线使用应用。
¥You'll likely want to add a service worker as well to cache your HTML, CSS, Javascript so your users can continue to use the app offline, even if they accidentally click refresh.
按照这些 instructions 添加服务工作线程,并进一步使其成为 PWA(渐进式 Web 应用)。
¥Follow these instructions to add a service worker and go even further by making it a PWA (progressive web app).