30
loading...
This website collects cookies to deliver better user experience
import { firestore, storage } from "firebase-admin"
import * as fs from 'fs'
// We're just initializing the project.
import { initAdminProject } from ". /helper"
initAdminProject()
const BUCKET_NAME = 'YOUR_BUCKET_NAME'
const CREATE_INITIAL_DATA = false
const main = async () => {
const db = firestore()
const timestamp = Date.now()
if (CREATE_INITIAL_DATA) {
// create 100 data items
await Promise.all([. .Array(100)].map((_, i) => {
return db.doc(`bundles/data_${i}`).set({
body: `${i}`.repeat(1000).slice(0, 1000),
Timestamp: firestore.Timestamp.fromMillis(timestamp + i * 100)
}))
})))
}
// Read the data from the firestore and create a Data Bundle
const snapshots = await db.collection('bundles').orderBy('timestamp', 'asc').get()
const bundleID = timestamp.toString()
const buffer = await db.bundle(bundleID).add('bundles-query', snapshots).build()
// write them out locally for upload
const bundledFilePath = `. /${timestamp}.txt`.
fs.writeFileSync(bundledFilePath, buffer)
// Upload the file to GCS
const destination = `firestore-data-bundles/bundles.txt`
await storage().bucket(BUCKET_NAME).upload(bundledFilePath, { destination, public: true, metadata: { cacheControl: `public, max-age=60` } })
console.log(`uploaded to https://storage.googleapis.com/${BUCKET_NAME}/${destination}`)
process.exit(0)
}
main()
db.bundle(bundleID).add('bundles-query', snapshots).build()
part creates the Bundle. db.bundle()
returns the BundleBuilder
and add
adds to it. In this case, we will only add one QuerySnapshot
, but you can call .add()
as many times as you want, and you can also pass a DocumentSnapshot
. I didn't see any indication of how much you can pack in, but considering that the client will be downloading it, I'd say a few MB is the upper limit.bundleID
is once set to timestamp, but the role of this ID seems to be used to determine if the Bundle has already been retrieved by the client or not. This ID is used to determine if the bundle has already been retrieved by the client.The ID of the bundle. When loaded on clients, client SDKs use this ID and the timestamp associated with the bundle to tell if it has been loaded already. If not specified, a random identifier will be used.
import axios from "axios"
import { initClientProject } from ". /helper"
const app = initClientProject()
const BUNDLE_URL = 'UPLOADED_BUNDLE_URL'
const main = async () => {
const db = app.firestore()
const now = Date.now()
// Get Bundle data from GCS and load it
const response = await axios.get(BUNDLE_URL)
await db.loadBundle(response.data)
// retrieve from the loaded Bundle data
const query = await db.namedQuery('bundles-query')
const snaps = await query!.get({ source: 'cache' })
console.log(`${(Date.now() - now) / 1000}s`)
process.exit(0)
}
main()
loadBundle
, the Data Bundle will be expanded as a local cache of the device as well. We dare to use the namedQuery
method to load it, but you can also load the loaded Bundle with db.collection('bundles').orderBy('timestamp', 'asc').get({ source: 'cache' })
. The reason why we use source: 'cache'
is because we wanted to make sure to read from the unpacked cache. You may want to change this to suit your logic.exceeded transfered data (GB) x $0.14
to the above.While the developer benefits from the cost savings, the biggest beneficiary is the user. Studies have repeatedly shown that speedy Studies have repeatedly shown that speedy pages mean happier users.