Important note: Firebase private backups have changed since this blog post. Please see the updated details here.
.json
security_rules.txt
Today we’re excited to introduce version 1.0 of AngularFire. This new release focuses on enhancing two characteristics of AngularFire: stability and simplicity.
With a 1.0 release we will guarantee backwards-compatibility with all future 1.x.x releases. We would like to thank those who built amazing apps during the beta. Without your support and feedback AngularFire wouldn't be what it is today.
The goal of AngularFire is to remove the complexity of synchronizing collections. The 1.0 release removes the overlap between the Firebase SDK and the AngularFire library. AngularFire is now focused on on what it’s good at: synchronized bindings. We've removed the $firebase service in favor of two new services: $firebaseArray and $firebaseObject. Authentication through the $firebaseAuth service is already stable and remains unchanged.
$firebase
$firebaseArray
$firebaseObject
$firebaseAuth
The $firebase service added an unnecessary step to the synchronization process. The 1.0 release cuts right to the chase. If you need a synchronized array, inject the $firebaseArray service and pass it a reference:
app.controller("Ctrl", function($scope, $firebaseArray) { var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com"); $scope.items = $firebaseArray(ref); });
It's a similar process to use $firebaseObject to create a synchronized object:
app.controller("Ctrl", function($scope, $firebaseObject) { var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com"); $scope.obj = $firebaseObject(ref); });
These new services are functionally equivalent to the $asArray() and $asObject() methods present in AngularFire 0.9. For example, the 0.9 $firebase(ref).$asArray() method returns the same array as the 1.0 $firebaseArray(ref).
$asArray()
$asObject()
$firebase(ref).$asArray()
$firebaseArray(ref)
The 0.8 release introduced the $extendFactory() method on arrays and objects. This powerful method provided transformations on AngularFire to fit your own model's behavior. In the 1.0 release we've renamed it to $extend().
$extendFactory()
$extend()
script app.factory("ArrayWithSum", function($firebaseArray) { return $firebaseArray.$extend({ sum: function() { var total = 0; angular.forEach(this.$list, function(rec) { total += rec.x; }); return total; } }); });
You may notice that the new operator is now optional for $firebaseArray and $firebaseObject. However, when using $extend(), we must always use the new operator.
new
app.controller("ArrayCtrl", function($scope, ArrayWithSum) { var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com"); $scope.data = new ArrayWithSum(ref); });
We take pride in our documentation at Firebase. Now that AngularFire has hit 1.0, it deserves a guide with an expanded structure that mirrors our other SDKs. We’ve paved the way for continued updates to add relevant samples and sections.
Visit the new docs for a step-by-step development guide on mastering AngularFire.
For those of you who love require(), AngularFire 1.0 is the release for you. Angular 1.4 and AngularFire 1.0 now support CommonJS:
require()
var angular = require("angular"); var angularfire = require("../angularfire");
We are providing a migration guide to upgrade from previous versions. The migration guide can be found here.
We want to know what you think of the new features. Drop a comment below or send us any feedback on our Angular Google Group.
For more information check out the new in-depth guide. Or for a crash course, visit the AngularFire quickstart or try the five minute tutorial.
Ever wondered about the magic behind Firebase's push IDs? We get many questions from our developers about how our uniquely generated IDs work under the hood so I thought I’d explain them in more detail.
If you're not familiar with Firebase's push IDs, they are the chronological, 20-character unique IDs generated when you write lists of data to Firebase from any of our client libraries. Below is an example of some data stored in Firebase by push ID:
{ "messages": { "-JhLeOlGIEjaIOFHR0xd": "Hello there!", "-JhQ76OEK_848CkIFhAq": "Push IDs are pretty magical.", "-JhQ7APk0UtyRTFO9-TS": "Look a white rabbit!" } }
We created push IDs for collaborative, multi-user applications to handle situations where many clients are adding to a list at the same time. We needed IDs that could be generated client-side so that they wouldn't need to wait for a round-trip to the server. And we needed them to be unique so that many clients could append data to the same location at the same time without worrying about conflicts.
Push IDs are string identifiers that are generated client-side. They are a combination of a timestamp and some random bits. The timestamp ensures they are ordered chronologically, and the random bits ensure that each ID is unique, even if thousands of people are creating push IDs at the same time.
A push ID contains 120 bits of information. The first 48 bits are a timestamp, which both reduces the chance of collision and allows consecutively created push IDs to sort chronologically. The timestamp is followed by 72 bits of randomness, which ensures that even two people creating push IDs at the exact same millisecond are extremely unlikely to generate identical IDs. One caveat to the randomness is that in order to preserve chronological ordering if a client creates multiple push IDs in the same millisecond, we just 'increment' the random bits by one.
To turn our 120 bits of information (timestamp + randomness) into an ID that can be used as a Firebase key, we basically base64 encode it into ASCII characters, but we use a modified base64 alphabet that ensures the IDs will still sort correctly when ordered lexicographically (since Firebase keys are ordered lexicographically).
There's one caveat to the chronological ordering of push IDs. Since the timestamp is generated client-side, it's at the mercy of the client's local clock, which could be incorrect. We make an attempt to compensate for these ‘skewed’ clocks to some degree. When a Firebase client establishes a connection, the Firebase server sends an accurate timestamp to the client so it can use that to correct its incorrect clock when generating push IDs.
However, this correction only takes effect once the client has connected to Firebase, so if you generate a push ID before the client connects, we won't make an attempt to correct it. You could even generate two push IDs on the same client and the second push ID will be ordered before the first one if we started compensating for your clock between when you generated them.
To get guaranteed chronological ordering, you probably shouldn’t rely on push IDs but instead use our ServerValue.TIMESTAMP feature, which looks like this:
// Write some data with a timestamp ref.push({ foo: 'bar', date: Firebase.ServerValue.TIMESTAMP }); // Later, retrieve the data by ordered date ref.orderByChild('date').on('child_added', function(snapshot) { //Do something with ordered children });
// Write some data with a timestamp NSDictionary *data = @{ @"foo": @"bar", @"date": kFirebaseServerValueTimestamp }; [[ref childByAutoId] setValue: data]; //Later, retrieve the data by ordered date [[ref queryOrderedByChild:@"date"] observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) { //Do something with ordered children }];
// Write some data with a timestamp let data = [ "foo":"bar", "date":FirebaseServerValue.timestamp() ] ref.childByAutoId().setValue(data) //Later, retrieve the data by ordered date ref.queryOrderedByChild("date").observeEventType(.ChildAdded, withBlock: { snapshot in // Do something with ordered children })
// Write some data with a timestamp Map data = new HashMap(); data.put("foo", "bar"); data.put("date", ServerValue.TIMESTAMP); ref.push().setValue(data); //Later, retrieve the data by ordered date Query queryRef = ref.orderByChild(“date”); queryRef.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot snapshot) { // Do something with ordered children } //... });
This guarantees chronological ordering, since the ServerValue.TIMESTAMP will be resolved on the Firebase server to be an accurate timestamp.
We also get questions on whether developers can rely on push IDs to be unguessable by others, which can be important if you're trying to do security via unguessable Firebase paths. While push IDs are generally very hard to guess, if you’re relying on unguessable IDs you should generate them yourself using a more secure mechanism.
If you'd like to take a closer look at how push IDs work, we've published the code we use to generate them in a gist here.
Have other questions about push IDs that weren't answered here? Let us know in our google group or by mentioning @Firebase on Twitter, we'd love to hear your feedback!
It’s not every day you get to play with a beta programming language, so I was incredibly excited when Apple announced Swift at WWDC last year.
My first project at Firebase was becoming our resident Swift expert, and after a few weeks of digging into the language I presented an overview to the team. I recently updated the presentation and recorded it. If you’re new to Swift this video will give you a general overview and walk you through the core language features:
If you’re already familiar with Swift, our iOS Guide has everything you need to know to start building a realtime app with Swift and Firebase. You can also check out our Swift chat example app.
I’d love to hear what you think of the screencast, you can leave your feedback in the comments or find me on twitter at @fangedkat.
2014 was our best year yet at Firebase. We’ve grown from a community of 30,000 developers to over 130,000, introduced a static hosting service, reached one million concurrent devices connected to the Firebase servers, and joined the Google Cloud Platform team - and this is just a few of the things we’ve been up to! As we wrap up the year, we wanted to share the highlights with you and give you a preview of what’s coming in 2015.
First, however, we wanted to thank all of you. We have seen you use Firebase for incredible things this year we could not have imagined. Y Combinator, for example, is using Firebase to power its Hacker News API. Such diverse use cases pop up every week because our community of developers make Firebase a platform other developers want to use. You help each other on StackOverflow, share sample code on GitHub, and are generous with your time and feedback. We would not have come this far without you! I’m deeply grateful for your active engagement, and I speak on behalf of the rest of the team.
Technology startups are an uphill struggle, and we’ve been fortunate to reach a degree of adoption that is quite rare. You’ve helped us climb that hill and we plan to continue serving you in 2015 just as we have in past years.
Angular and Ember Support: We kicked off 2014 by attending the first ever AngularJS conference, ng-conf. We introduced Angular developers to Firebase and gave a talk on wiring up a backend for your Angular app using Firebase, which now has almost 30,000 views. A few months later we expanded our JavaScript framework support by releasing new bindings for Ember and sponsoring EmberConf.
Firebase Hosting: To provide a way for developers to build, deploy, and host their applications on Firebase, we launched Firebase Hosting in May. We were blown away by the response, and we’ve seen over 7,000 sites deployed on Firebase Hosting since it launched.
One Million Concurrents: There was quite a bit of celebration in the Firebase office when the total number of network connections to our servers reached one million for the first time. This means there are over one million users active on Firebase-powered apps at any given time.
Firebase + Google Cloud Platform: In October we joined the Google Cloud Platform team! As part of Google we’ll be able to dramatically scale Firebase and give our developers access to a powerful cloud infrastructure platform. Watch our videos from Google Cloud Platform Live to learn more.
Queries: After gathering feedback from many of you, we announced enhanced query support. Our new query features make it possible to order and retrieve data using a child key, by key name, or by priority.
Triggers: At Google Cloud Platform Live we demoed an upcoming feature that will make it easy to connect Firebase with external services. You’ll be able to use Triggers to submit a payment, send an SMS, or ping a server for logging and analytics - all without writing your own server-side code. Stay tuned for Triggers in 2015.
ng-conf and EmberConf: We’ll be at ng-conf and EmberConf in March. If you’ll be attending, stop by the Firebase booth to chat with the team and learn about our integrations with each framework.
Big things are coming in 2015. Follow us on Twitter and join our Google Group to stay up to date on the latest Firebase news. In the meantime, happy coding and have a wonderful new year!