Author Archives: admin

React Native Animations – Info compilation

[Fuente: https://facebook.github.io/react-native/docs/animations]

[Fuente: https://scotch.io/@rakshitkrsoral/the-beginners-guide-to-using-react-native-animated-api]

[Fuente: https://www.raizlabs.com/dev/2018/03/react-native-animations-part1/]

Animations

Animations are very important to create a great user experience. Stationary objects must overcome inertia as they start moving. Objects in motion have momentum and rarely come to a stop immediately. Animations allow you to convey physically believable motion in your interface.

React Native provides two complementary animation systems:

  • Animated for granular and interactive control of specific values,
  • LayoutAnimation for animated global layout transactions.

Animated API

The Animated API is designed to make it very easy to concisely express a wide variety of interesting animation and interaction patterns in a very performant way. Animated focuses on declarative relationships between inputs and outputs, with configurable transforms in between, and simple start/stop methods to control time-based animation execution.

Animated exports four animatable component types: ViewTextImage, and ScrollView, but you can also create your own using Animated.createAnimatedComponent().

For example, a container view that fades in when it is mounted may look like this:

import React from 'react';
import { Animated, Text, View } from 'react-native';

class FadeInView extends React.Component {
  state = {
    fadeAnim: new Animated.Value(0),  // Initial value for opacity: 0
  }

  componentDidMount() {
    Animated.timing(                  // Animate over time
      this.state.fadeAnim,            // The animated value to drive
      {
        toValue: 1,                   // Animate to opacity: 1 (opaque)
        duration: 10000,              // Make it take a while
      }
    ).start();                        // Starts the animation
  }

  render() {
    let { fadeAnim } = this.state;

    return (
      <Animated.View                 // Special animatable View
        style={{
          ...this.props.style,
          opacity: fadeAnim,         // Bind opacity to animated value
        }}
      >
        {this.props.children}
      </Animated.View>
    );
  }
}

// You can then use your `FadeInView` in place of a `View` in your components:
export default class App extends React.Component {
  render() {
    return (
      <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
        <FadeInView style={{width: 250, height: 50, backgroundColor: 'powderblue'}}>
          <Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>Fading in</Text>
        </FadeInView>
      </View>
    )
  }
}

Let’s break down what’s happening here. In the FadeInView constructor, a new Animated.Value called fadeAnim is initialized as part of state. The opacity property on the View is mapped to this animated value. Behind the scenes, the numeric value is extracted and used to set opacity.

When the component mounts, the opacity is set to 0. Then, an easing animation is started on the fadeAnimanimated value, which will update all of its dependent mappings (in this case, just the opacity) on each frame as the value animates to the final value of 1.

This is done in an optimized way that is faster than calling setState and re-rendering.
Because the entire configuration is declarative, we will be able to implement further optimizations that serialize the configuration and runs the animation on a high-priority thread.

Configuring animations

Animations are heavily configurable. Custom and predefined easing functions, delays, durations, decay factors, spring constants, and more can all be tweaked depending on the type of animation.

Animated provides several animation types, the most commonly used one being Animated.timing(). It supports animating a value over time using one of various predefined easing functions, or you can use your own. Easing functions are typically used in animation to convey gradual acceleration and deceleration of objects.

By default, timing will use a easeInOut curve that conveys gradual acceleration to full speed and concludes by gradually decelerating to a stop. You can specify a different easing function by passing a easing parameter. Custom duration or even a delay before the animation starts is also supported.

For example, if we want to create a 2-second long animation of an object that slightly backs up before moving to its final position:

Animated.timing(this.state.xPosition, {
  toValue: 100,
  easing: Easing.back(),
  duration: 2000,
}).start();

Take a look at the Configuring animations section of the Animated API reference to learn more about all the config parameters supported by the built-in animations.

Composing animations

Animations can be combined and played in sequence or in parallel. Sequential animations can play immediately after the previous animation has finished, or they can start after a specified delay. The Animated API provides several methods, such as sequence() and delay(), each of which simply take an array of animations to execute and automatically calls start()/stop() as needed.

For example, the following animation coasts to a stop, then it springs back while twirling in parallel:

Animated.sequence([
  // decay, then spring to start and twirl
  Animated.decay(position, {
    // coast to a stop
    velocity: {x: gestureState.vx, y: gestureState.vy}, // velocity from gesture release
    deceleration: 0.997,
  }),
  Animated.parallel([
    // after decay, in parallel:
    Animated.spring(position, {
      toValue: {x: 0, y: 0}, // return to start
    }),
    Animated.timing(twirl, {
      // and twirl
      toValue: 360,
    }),
  ]),
]).start(); // start the sequence group

If one animation is stopped or interrupted, then all other animations in the group are also stopped. Animated.parallel has a stopTogether option that can be set to false to disable this.

You can find a full list of composition methods in the Composing animations section of the Animated API reference.

Combining animated values

You can combine two animated values via addition, multiplication, division, or modulo to make a new animated value.

There are some cases where an animated value needs to invert another animated value for calculation. An example is inverting a scale (2x –> 0.5x):

const a = new Animated.Value(1);
const b = Animated.divide(1, a);

Animated.spring(a, {
  toValue: 2,
}).start();

Animation Drivers

Drivers are nodes in the graph that change Animated Values every frame. These are things like Animated.Timing, which drives a value over time, or Animated.Decay, which reduces a value every frame. We can connect an Animated.Event to an onScroll event: this drives a value as the user scrolls. We can start or stop a Driver, and connect it to other Animated Values or Drivers. When the driver updates each frame, its new value propagates down through the graph, updating its child Animation Drivers or Animated Values and eventually updating view properties.

Animated.decay(this.valueToAnimate, {
   velocity: 2.0,
   deceleration: 0.9
}).start();

In the decay animation above, our Animated Value starts at a velocity, and slows over time.

Define how the animated value will change over time

All animated values can be defined w.r.t change in time using Animated.timingmethod. Animated.timing has 3 common parameters that you can set:

  • Decay – starts with an initial velocity and gradually slows to a stop
  • Duration – starts the animation after a certain duration
  • Easing – To understand how easing functions work, you can prefer reading docs. On the surface level, these are the functions that allows developers to implement physically believable motion in React Native animations. By default, a typical easing function is linear, but if you want to override it to make something like Easing.sin(t) or Easing.bezier(x1, y1, x2, y2), you can add the line “import { ‘Easing’ } from ‘react-native'”

In the following example, I am fading animation over 200 ms.

Animated.timing(this.state.opacity, {toValue: 0, duration: 200})

Using Native Animations in Animated API

Changing an animation driver (like Animated.value, Animated.Timing or Animated.Spring) to use native animations is as easy as adding the property useNativeDriver: true. The same goes for an Animated.Event:

Animated.event( [{ ... }], { useNativeDriver: true } )

Note: – Always use Native Animations wherever possible in your React Native app.

Transform Operations

We convert Animated Values to new Animated Values through Transform operations.

Animated.add() , Animated.multiply() or Animated.interpolate() are examples of Transforms. We can run a Transform on any other node in the Animated graph: an animated value (new Animated.Value(42)).interpolate(...), or another transform: animatedPosition.interpolate(...).interpolate(...).

In one of our apps, we show a large illustration in the navbar, and minimize it as the screen scrolls. This gives the user more space to be productive. To do this, we pass the scroll distance (an Animated Value) as a prop on the NavBar component. The NavBar interpolates the scroll distance into a position or opacity, fading itself out and moving it up and off the screen.

ewewe
we
we
we
we
we
we

Publishing a NativeScript Android App in Google Play

[Fuente: https://developer.android.com/studio/publish/app-signing#signing-manually]

Compilar y firmar tu aplicación desde la línea de comandos

No necesitas Android Studio para firmar tu aplicación. Puedes hacerlo desde la línea de comandos con la herramienta apksigner, o bien configurar Gradle para que se encargue de ello durante la compilación. En cualquier caso, debes generar primero una clave privada usando keytool. Por ejemplo:

keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias

Nota: keytool se encuentra en el directorio bin/ de tu JDK. Para encontrar tu JDK desde Android Studio, selecciona File > Project Structure y luego haz clic en SDK Location. Con esto, verás la ubicación del JDK.

En este ejemplo se te solicitan contraseñas para el keystore y la clave, y para otorgar los campos de nombre distinguido de tu clave. Luego, se genera el keystore como un archivo llamado my-release-key.jks, que se guarda en el directorio actual (puedes moverlo cuando lo desees). El keystore contiene una clave única válida por 10 000 días.

Ahora puedes compilar un APK sin firma y firmarlo manualmente o configurar Gradle para que firme tu APK.

Compilar un APK sin firma y firmarlo manualmente

  1. Abre una línea de comandos, dirígete a la raíz del directorio de tu proyecto, desde Android Studio, y selecciona View > Tool Windows > Terminal. Luego invoca la tarea assembleRelease:
    gradlew assembleRelease

    De esta forma, se creará un APK con el nombre module_name-unsigned.apk en project_name/module_name/build/outputs/apk/. En este punto, el APK no está firmado ni alineado; no puede instalarse hasta que se firme con tu clave privada.

  2. Alinea el APK sin firma usando zipalign:
    zipalign -v -p 4 my-app-unsigned.apk my-app-unsigned-aligned.apk
    

    zipalign garantiza que todos los datos descomprimidos comiencen con una alineación de bytes en particular relacionada con el comienzo del archivo, lo que reduce el consumo de memoria RAM de una aplicación.

  3. Firma tu APK con tu clave privada usando apksigner:
    apksigner sign --ks my-release-key.jks --out my-app-release.apk my-app-unsigned-aligned.apk
    

    En este ejemplo se genera el APK firmado en my-app-release.apk una vez que se firma con una clave privada y un certificado, que se almacenan en un único archivo de keystore: my-release-key.jks.

    La herramienta apksigner admite otras opciones de firmas, incluidas la firma de un archivo APK con archivos de clave y certificado privados separados y la firma de un APK con varios firmantes. Para obtener información detallada, consulta la referencia de apksigner.

    Nota: Para usar la herramienta apksigner, debes tener instalada la revisión 24.0.3 o revisiones posteriores de Android SDK Build Tools. Puedes actualizar este paquete con SDK Manager.

  4. Verifica que tu APK esté firmado.
    apksigner verify my-app-release.apk
    

Configurar Gradle para que firme tu APK

  1. Abre el archivo build.gradle de nivel de módulo y agrega el bloque signingConfigs {} con entradas para storeFilestorePasswordkeyAlias y keyPassword, y luego pasa ese objeto a la propiedad signingConfig en tu tipo de compilación. Por ejemplo:
    android {
        ...
        defaultConfig { ... }
        signingConfigs {
            release {
                storeFile file("my-release-key.jks")
                storePassword "password"
                keyAlias "my-alias"
                keyPassword "password"
            }
        }
        buildTypes {
            release {
                signingConfig signingConfigs.release
                ...
            }
        }
    }

    Debido a que Gradle lee las rutas de acceso relativas a build.gradle, el ejemplo anterior funciona únicamente si my-release-key.jks está en el mismo directorio que el archivo build.gradle.

    Nota: En este caso, el keystore y la contraseña de clave pueden verse directamente en el archivo build.gradle. Para una mayor seguridad, debes quitar la información de firmas de tu archivo de compilación.

  2. Abre una línea de comandos en el directorio raíz de tu proyecto e invoca la tarea assembleRelease:
    gradlew assembleRelease

De esta forma, se creará un APK con el nombre module_name-release.apk en project_name/module_name/build/outputs/apk/. Este archivo APK se firma con la clave privada especificada en tu archivo build.gradle y se alinea con zipalign.

Ahora que ya configuraste la compilación de lanzamiento con tu clave de firma, la tarea “install” estará disponible para ese tipo de compilación. Por lo tanto, podrás compilar, alinear e instalar el APK de lanzamiento en un emulador o dispositivo con la tarea installRelease.

Un APK firmado con tu clave privada está listo para la distribución, pero antes debes leer más información sobre cómo publicar tu aplicación y revisar la lista de comprobación de lanzamiento para Google Play.

[Fuente: https://docs.nativescript.org/tooling/publishing/publishing-android-apps]

Overview

Tip: Instead of the CLI, use NativeScript Sidekick for easy app store publishing to both the iOS App Store and Google Play. Sidekick also offers starter kits, plugin management, and cloud-based builds for iOS and Android.

You can publish a NativeScript app in Google Play the same way you would release a purely native Android app.

  1. Make sure that you have a .keystore file to sign your app with. For more information, see How to create a .keystore file?
  2. Build your project in release mode by running the following command:
    tns build android --release --key-store-path <path-to-your-keystore> --key-store-password <your-key-store-password> --key-store-alias <your-alias-name> --key-store-alias-password <your-alias-password>
    

    Note: At the end of <path-to-your-keystore> you should also add the exact name of your keystore.

Example(Windows): tns build android --release --key-store-path C:\keystore\Telerik.keystore --key-store-password sample_password --key-store-alias Telerik --key-store-alias-password sample_password .

Example(Mac): tns build android --release --key-store-path ~/Desktop/keystore/Telerik.keystore --key-store-password sample_password --key-store-alias Telerik --key-store-alias-password sample_password .

  1. Obtain the release .apk located at <app_name>/platforms/android/app/build/outputs/apk/<app_name>-release.apk.
  2. Publish your Android app by uploading the .apk file to the Google Developer Console. For more information, see How to publish an Android app?

Application Id and Package Name

Both Package Name, and Application Id, are unique identifiers, provided by you for your app.

  • Package Name is used to identify resources such as the R.
  • Application Id is used to identify your app on devices and at the Google Play.

In the NativeScript framework, both are set to the applicationId in app.gradle. The NativeScript CLI build system will set them as the package attribute in the generated project in platforms/android/src/main/AndroidManifest.xml. In the app/App_Resources/Android/AndroidManifest.xml it will use a placeholder: package="__PACKAGE__". Do not modify the package attribute there.

NOTE: To edit the Package Name and the Application Id, modify the package.jsonof your app and set the nativescript.id key. You may need to delete platforms/android and rebuild using the CLI command tns prepare android.

Read more about “ApplicationId versus PackageName”.

App name

This is the display name for your app. It is purely cosmetic but highly important. For example, it appears under the app icon. The value can be stored in the app/App_Resources/Android/values/strings.xml file

<resources>
    <string name="app_name">MyAppName</string>
    <string name="title_activity_kimera">MyAppName</string>
</resources>

By default (or if the project lacks the values above) your application name is generated with the create command (e.g. tns create testApp will have app name testApp)

You can check out more information about the elements you can define in the AndroidManifest.xml here.

App icons

App icons are defined similar to the app name. The icon name is defined in the app/App_Resources/Android/AndroidManifest.xml file, as an android:icon="@drawable/icon"attribute, on the <application> element.

The actual .PNG icons stay at the Android resources in app/App_Resource/Android/<DPI>/icon.png, DPIs:

DIRECTORY DPI SCREEN SIZE
drawable-ldpi 120 Low density screen 36px x 36px
drawable-mdpi 160 Medium density screen 48px x 48px
drawable-hdpi 240 High density screen 72px x 72px
drawable-xhdpi 320 Extra-high density screen 96px x 96px
drawable-xxhdpi 480 Extra-extra-high density screen 144px x 144px
drawable-xxxhdpi 640 Extra-extra-extra-high density screen 192px x 192px

Note: NativeScript supports adaptive icons on Android 8 and above (API 26+). No code changes are required – follow the Android guidelines for creating adaptive icons for your application.

Launch screen

Android has no built-in mechanism to provide launch screen image. Here is a documentation article that describes how to implement a launch screen in the NativeScript framework.

Certificates

Debug certificate

These are automatically generated by the Android SDK tools for you.

In debug mode, you sign your app with a debug certificate. This certificate has a private key with a known password. The process is handled by the Android tooling.

You can read more at “Signing in Debug Mode”.

Release certificate

The release certificate for Android is created by you; it does not have to be signed by a certificate authority. It is easier to create a release certificate for Android than it is for iOS. You should, however, be more careful with your certificate.

A few pitfalls are:

  • You create the certificate only once. If you lose it, you will not be able to publish any updates to your app, because you must always sign all versions of your app with the same key.
  • If your certificate expires, you will not be able to renew it. Ensure long validity when creating a new certificate (for 20+ years).
  • If a third party obtains your private key, that party could sign and distribute apps that maliciously replace your authentic apps or corrupt them.

You can generate a private key for a release certificate using the keytool.

keytool -genkey -v -keystore <my-release-key>.keystore -alias <alias_name> -keyalg RSA -keysize 2048 -validity 10000

This will run an interactive session collecting information about your name, organization and most importantly — keystore and alias passwords.

Google Play Developer Console

You will need a developer account and you will need to log into the Google Play Developer Console.

Go to the All applications section and click the + Add new application button.

  • You will get prompted to provide the app title
  • You can then proceed with the store listings.
  • You can fill in app description, screenshots and so on.
  • You can also submit an APK. Read about how to obtain an APK from a NativeScript app.

Builds

Build versioning

We have already explained how the Application Id is set in your project, how icons are added to your app and how you can set the display name.

Before the build, you need to set two important things: the versionCode and the android:versionName.

When a build is uploaded, its versionCode should be larger than previous builds. A new build with a higher versionCode is considered an upgrade to builds that have a lower versionCode. The versionCode is an integer so you should carefully consider a strategy for versioning.

Both values are stored in app/App_Resources/Android/AndroidManifest.xml.

NOTE: android:versionName is a string value, which is used to represent the application version to the user whereas android:versionCode, which is integer value showing version of the application code relative to the other versions. You can read more about “Versioning Your Applications”.

In the app/App_Resources/Android/AndroidManifest.xml, the versionCode and versionName appear as:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.nativescript.name"
      android:versionCode="2"
      android:versionName="1.1">
      ...

Build signed release APK

You can perform a full build and produce a signed APK using the NativeScript CLI:

tns build android --release --key-store-path <path-to-your-keystore> --key-store-password <your-key-store-password> --key-store-alias <your-alias-name> --key-store-alias-password <your-alias-password> --copy-to <apk-location>.apk

You can then use the produced <apk-location>.apk for upload to Google Play.

APKs with ABI splits

If you want to reduce the apk sizes you can check how to achieve this in Android ABI Split article.

Submit with the Google Play Developer Console

To submit your app to the Google Play Developer Console:

  1. Log into the Google Play Developer Console.
  2. Select your application and go to the APK section.
  3. Choose ProductionBeta or Alpha stage and click the Upload new APK.
  4. Select the APK produced by the CLI.

You can read more about these stages at “Set up alpha/beta tests”.

Once you upload your APK, it will go through a review. When approved, you can move it to production to make it available on Google Play.

Submission automation

Some tools allow the submission process to be automated – MIT Licensed one: fastlane. You can also hack your own scripts around the Google Play Developer API.

Publish

Once you successfully upload your APK, and it passes Google review, you will be able to move your APK to production, and it will go live on Google Play.

React Native Internals

[ Fuente:

https://www.reactnative.guide/3-react-native-internals/3.1-react-native-internals.html

]

React Native Internals

React Native is a framework which allows developers to build native apps using Javascript. Wait! Cordova already does that and it has been around for quite a while. Why would anyone want to use RN?

The primary difference between RN and Cordova based apps is that Cordova based apps run inside a webview while RN apps render using native views. RN apps have direct access to all the Native APIs and views offered by the underlying mobile OS. Thus, RN apps have the same feel and performance as that of a native application.

At first, it is easy to assume that React Native might be compiling JS code into respective native code directly. But this would be really hard to achieve since Java and Objective C are strongly typed languages while Javascript is not! Instead, RN does something much more clever. Essentially, React Native can be considered as a set of React components, where each component represents the corresponding native views and components. For example, a native TextInput will have a corresponding RN component which can be directly imported into the JS code and used like any other React component. Hence, the developer will be writing the code just like for any other React web app but the output will be a native application.

Ok! This looks like black magic 🙄.

To understand this, let us take a look at the architecture and how React Native works internally.

Architecture 🤖

Both iOS and Android have a similar architecture with subtle differences.

If we consider the big picture, there are three parts to the RN platform:

  1. Native Code/Modules: Most of the native code in case of iOS is written in Objective C or Swift, while in the case of Android it is written in Java. But for writing our React Native app, we would hardly ever need to write native code for iOS or Android.

  2. Javascript VM: The JS Virtual Machine that runs all our JavaScript code. On iOS/Android simulators and devices React Native uses JavaScriptCore, which is the JavaScript engine that powers Safari. JavaScriptCore is an open source JavaScript engine originally built for WebKit. In case of iOS, React Native uses the JavaScriptCore provided by the iOS platform. It was first introduced in iOS 7 along with OS X Mavericks.
    https://developer.apple.com/reference/javascriptcore.

    In case of Android, React Native bundles the JavaScriptCore along with the application. This increases the app size. Hence the Hello World application of RN would take around 3 to 4 megabytes for Android.

    In case of Chrome debugging mode, the JavaScript code runs within Chrome itself (instead of the JavaScriptCore on the device) and communicates with native code via WebSocket. Here, it will use the V8 engine. This allows us to see a lot of information on the Chrome debugging tools like network requests, console logs, etc. 😎

  3. React Native Bridge: React Native bridge is a C++/Java bridge which is responsible for communication between the native and Javascript thread. A custom protocol is used for message passing.

react native architecture diagram

In most cases, a developer would write the entire React Native application in Javascript. To run the application one of the following commands are issued via the CLI – react-native run-ios or react-native run-android.

At this point, React Native CLI would spawn a node packager/bundler that would bundle the JS code into a single main.bundle.js file. The packager can be considered as being similar to Webpack.

Now, whenever the React Native app is launched, the first item to be loaded is the native entry point. The Native thread spawns the JS VM thread which runs the bundled JS code. The JS code has all the business logic of the application. The Native thread now sends messages via the RN Bridge to start the JS application.

Now, the spawned Javascript thread starts issuing instructions to the native thread via the RN Bridge. The instructions include what views to load, what information is to be retrieved from the hardware, etc. For example, if the JS thread wants a view and text to be created it will batch the request into a single message and send it across to the Native thread to render them.

[ [2,3,[2,'Text',{...}]] [2,3,[3,'View',{...}]] ]

The native thread will perform these operations and send the result back to the JS assuring that the operations have been performed.

Note: To see the bridge messages on the console, just put the following snippet onto the index.<platform>.js file

import MessageQueue from 'react-native/Libraries/BatchedBridge/MessageQueue';
MessageQueue.spy(true);

Threading Model 🚧

When a React Native application is launched, it spawns up the following threading queues.

  1. Main thread (Native Queue) – This is the main thread which gets spawned as soon as the application launches. It loads the app and starts the JS thread to execute the Javascript code. The native thread also listens to the UI events like ‘press’, ‘touch’, etc. These events are then passed to the JS thread via the RN Bridge. Once the Javascript loads, the JS thread sends the information on what needs to be rendered onto the screen. This information is used by a shadow node thread to compute the layouts. The shadow thread is basically like a mathematical engine which finally decides on how to compute the view positions. These instructions are then passed back to the main thread to render the view.

  2. Javascript thread (JS Queue) – The Javascript Queue is the thread queue where main bundled JS thread runs. The JS thread runs all the business logic, i.e., the code we write in React Native.

  3. Custom Native Modules – Apart from the threads spawned by React Native, we can also spawn threads on the custom native modules we build to speed up the performance of the application. For example – Animations are handled in React Native by a separate native thread to offload the work from the JS thread.

Links: https://www.youtube.com/watch?v=0MlT74erp60

Development mode 🔨

When the app is run in DEV mode, the Javascript thread is spawned on the development machine. Even though the JS code is running on a more powerful machine as compared to a phone, you will soon notice that the performance is considerably lower as compared to when running in bundled mode or production mode. This is unavoidable because a lot more work is done in DEV mode at runtime to provide good warnings and error messages, such as validating propTypes and various other assertions. Furthermore, the latency of communication between the device and the JS thread also comes into play.

Link: https://www.youtube.com/watch?v=8N4f4h6SThc – RN android architecture

React native: Expo: How Expo Works

[ Fuente:

https://docs.expo.io/versions/v26.0.0/workflow/how-expo-works

]

How Expo Works

While it’s certainly not necessary to know any of this to use Expo, many engineers like to know how their tools work. We’ll walk through a few key concepts here, including:

  • Local development of your app
  • Publishing/deploying a production version of your app
  • How Expo manages changes to its SDK
  • Opening Expo apps offline

You can also browse the source, fork, hack on and contribute to the Expo tooling on github/@expo.

There are two pieces here: the Expo app and the Expo development tool (either XDE or exp CLI). We’ll just assume XDE here for simplicity of naming. When you open an app up in XDE, it spawns and manages two server processes in the background:

  • the Expo Development Server
  • and the React Native Packager Server.

Note: XDE also spawns a tunnel process, which allows devices outside of your LAN to access the the above servers without you needing to change your firewall settings. If you want to learn more, see ngrok.

Expo Development Server

This server is the endpoint that you hit first when you type the URL into the Expo app. Its purpose is to serve the Expo Manifest and provide a communication layer between the XDE UI and the Expo app on your phone or simulator.

The following is an example of a manifest being served through XDE. The first thing that you should notice is there are a lot of identical fields to app.json (see the Configuration with app.json section if you haven’t read it yet). These fields are taken directly from that file — this is how the Expo app accesses your configuration.

{
  "name":"My New Project",
  "description":"A starter template",
  "slug":"my-new-project",
  "sdkVersion":"18.0.0",
  "version":"1.0.0",
  "orientation":"portrait",
  "primaryColor":"#cccccc",
  "icon":"https://s3.amazonaws.com/exp-brand-assets/ExponentEmptyManifest_192.png",
  "notification":{
    "icon":"https://s3.amazonaws.com/exp-us-standard/placeholder-push-icon.png",
    "color":"#000000"
  },
  "loading":{
    "icon":"https://s3.amazonaws.com/exp-brand-assets/ExponentEmptyManifest_192.png"
  },
  "entryPoint": "node_modules/expo/AppEntry.js",
  "packagerOpts":{
    "hostType":"tunnel",
    "dev":false,
    "strict":false,
    "minify":false,
    "urlType":"exp",
    "urlRandomness":"2v-w3z",
    "lanType":"ip"
  },
  "xde":true,
  "developer":{
    "tool":"xde"
  },
  "bundleUrl":"http://packager.2v-w3z.notbrent.internal.exp.direct:80/apps/new-project-template/main.bundle?platform=ios&dev=false&strict=false&minify=false&hot=false&includeAssetFileHashes=true",
  "debuggerHost":"packager.2v-w3z.notbrent.internal.exp.direct:80",
  "mainModuleName":"main",
  "logUrl":"http://2v-w3z.notbrent.internal.exp.direct:80/logs"
}

Every field in the manifest is some configuration option that tells Expo what it needs to know to run your app. The app fetches the manifest first and uses it to show your app’s loading icon that you specified in app.json, then proceeds to fetch your app’s JavaScript at the given bundleUrl — this URL points to the React Native Packager Server.

In order to stream logs to XDE, the Expo SDK intercepts calls to console.logconsole.warn, etc. and posts them to the logUrl specified in the manifest. This endpoint is on the Expo Development Server.

If you use React Native without Expo, you would start the packager by running react-native start in your project directory. Expo starts this up for you and pipes STDOUT to XDE. This server has two purposes.

The first is to serve your app JavaScript compiled into a single file and translating any JavaScript code that you wrote which isn’t compatible with your phone’s JavaScript engine. JSX, for example, is not valid JavaScript — it is a language extension that makes working with React components more pleasant and it compiles down into plain function calls — so <HelloWorld /> would become React.createElement(HelloWorld, {}, null) (see JSX in Depth for more information). Other language features like async/await are not yet available in most engines and so they need to be compiled down into JavaScript code that will run on your phone’s JavaScript engine, JavaScriptCore.

The second purpose is to serve assets. When you include an image in your app, you will use syntax like <Image source={require('./assets/example.png')} />, unless you have already cached that asset you will see a request in the XDE logs like: <START> processing asset request my-proejct/assets/example@3x.png. Notice that it serves up the correct asset for your screen DPI, assuming that it exists.

 

When you publish an Expo app, we compile it into a JavaScript bundle with production flags enabled. That is, we minify the source and we tell the React Native packager to build in production mode (which in turn sets __DEV__ to false amongst other things). After compilation, we upload that bundle, along with any assets that it requires (see Assets) to CloudFront. We also upload your Manifest (including most of your app.jsonconfiguration) to our server. When publishing is complete, we’ll give you a URL to your app which you can send to anybody who has the Expo client.

Note: By default, all Expo projects are unlisted, which means that publishing does not make it publicly searchable or discoverable anywhere. It is up to you to share the link. You can change this setting in app.json.

As soon as the publish is complete, the new version of your code is available to all your existing users. They’ll download the updated version next time they open the app or refresh it, provided that they have a version of the Expo client that supports the sdkVersion specified in your app.json.

Updates are handled differently on iOS and Android. On Android, updates are downloaded in the background. This means that the first time a user opens your app after an update they will get the old version while the new version is downloaded in the background. The second time they open the app they’ll get the new version. On iOS, updates are downloaded synchronously, so users will get the new version the first time they open your app after an update.

Note: To package your app for deployment on the Apple App Store or Google Play Store, see Building Standalone Apps. Each time you update the SDK version you will need to rebuild your binary.

 

The sdkVersion of an Expo app indicates what version of the compiled ObjC/Java/C layer of Expo to use. Each sdkVersion roughly corresponds to a release of React Native plus the Expo libraries in the SDK section of these docs.

The Expo client app supports many versions of the Expo SDK, but an app can only use one at a time. This allows you to publish your app today and still have it work a year from now without any changes, even if we have completely revamped or removed an API your app depends on in a new version. This is possible because your app will always be running against the same compiled code as the day that you published it.

If you publish an update to your app with a new sdkVersion, if a user has yet to update to the latest Expo client then they will still be able to use the previous sdkVersion.

Note: It’s likely that eventually we will formulate a policy for how long we want to keep around sdkVersions and begin pruning very old versions of the sdk from the client, but until we do that, everything will remain backwards compatible.

 

The process is essentially the same as opening an Expo app in development, only now we hit an Expo server to get the manifest, and manifest points us to CloudFront to retrieve your app’s JavaScript.

 

The Expo client will automatically cache the most recent version of every app it has opened. When you try to open an Expo app, it will always try and fetch the latest version, but if that fails for whatever reason (including being totally offline) then it will load the most recent cached version.

If you build a standalone app with Expo, that standalone binary will also ship with a “pre-cached” version of your JavaScript so that it can cold launch the very first time with no internet. Continue reading for more information about standalone apps.

You can also package your Expo app into a standalone binary for submission to the Apple iTunes Store or Google Play.

Under the hood, it’s a modified version of the Expo client which is designed only to load a single URL (the one for your app) and which will never show the Expo home screen or brand. For more information, see Building Standalone Apps.

 

React Native : Building native releases

[Fuente:

https://facebook.github.io/react-native/docs/signed-apk-android.html

https://docs.expo.io/versions/v26.0.0/distribution/building-standalone-apps#content

https://docs.expo.io/versions/v26.0.0/expokit/detach#content

]

Contents

Generating Signed APK

Expo: Building standalone apps

Expo: Detach

Generating Signed APK

Android requires that all apps be digitally signed with a certificate before they can be installed, so to distribute your Android application via Google Play store, you’ll need to generate a signed release APK. The Signing Your Applications page on Android Developers documentation describes the topic in detail. This guide covers the process in brief, as well as lists the steps required to package the JavaScript bundle.

Generating a signing key

You can generate a private signing key using keytool. On Windows keytool must be run from C:\Program Files\Java\jdkx.x.x_x\bin.

$ keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

This command prompts you for passwords for the keystore and key, and to provide the Distinguished Name fields for your key. It then generates the keystore as a file called my-release-key.keystore.

The keystore contains a single key, valid for 10000 days. The alias is a name that you will use later when signing your app, so remember to take note of the alias.

Note: Remember to keep your keystore file private and never commit it to version control.

Setting up gradle variables

  1. Place the my-release-key.keystore file under the android/app directory in your project folder.
  2. Edit the file ~/.gradle/gradle.properties or android/gradle.properties and add the following (replace ***** with the correct keystore password, alias and key password),
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****

These are going to be global gradle variables, which we can later use in our gradle config to sign our app.

Note about saving the keystore: Once you publish the app on the Play Store, you will need to republish your app under a different package name (losing all downloads and ratings) if you want to change the signing key at any point. So backup your keystore and don’t forget the passwords.

Note about security: If you are not keen on storing your passwords in plaintext and you are running OSX, you can also store your credentials in the Keychain Access app. Then you can skip the two last rows in ~/.gradle/gradle.properties.

Adding signing config to your app’s gradle config

Edit the file android/app/build.gradle in your project folder and add the signing config,

...
android {
    ...
    defaultConfig { ... }
    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}
...

Generating the release APK

Simply run the following in a terminal:

$ cd android && ./gradlew assembleRelease

Gradle’s assembleRelease will bundle all the JavaScript needed to run your app into the APK. If you need to change the way the JavaScript bundle and/or drawable resources are bundled (e.g. if you changed the default file/folder names or the general structure of the project), have a look at android/app/build.gradle to see how you can update it to reflect these changes.

Note: Make sure gradle.properties does not include org.gradle.configureondemand=true as that will make release build skip bundling JS and assets into the APK.

The generated APK can be found under android/app/build/outputs/apk/app-release.apk, and is ready to be distributed.

Testing the release build of your app

Before uploading the release build to the Play Store, make sure you test it thoroughly. First uninstall any previous version of the app you already have installed. Install it on the device using:

$ react-native run-android --variant=release

Note that --variant=release is only available if you’ve set up signing as described above.

You can kill any running packager instances, all your framework and JavaScript code is bundled in the APK’s assets.

Split APKs by ABI to reduce file size

By default, the generated APK has the native code for both x86 and ARMv7a CPU architectures. This makes it easier to share APKs that run on almost all Android devices. However, this has the downside that there will be some unused native code on any device, leading to unnecessarily bigger APKs.

You can create an APK for each CPU by changing the following line in android/app/build.gradle:

- def enableSeparateBuildPerCPUArchitecture = false
+ def enableSeparateBuildPerCPUArchitecture = true

Upload both these files to markets which support device targetting, such as Google Play and Amazon AppStore and the users will automatically get the appropriate APK. If you want to upload to other markets such as APKFiles, which do not support multiple APKs for a single app, change the following line as well to create the default universal APK with binaries for both CPUs.

- universalApk false  // If true, also generate a universal APK
+ universalApk true  // If true, also generate a universal APK

Enabling Proguard to reduce the size of the APK (optional)

Proguard is a tool that can slightly reduce the size of the APK. It does this by stripping parts of the React Native Java bytecode (and its dependencies) that your app is not using.

IMPORTANT: Make sure to thoroughly test your app if you’ve enabled Proguard. Proguard often requires configuration specific to each native library you’re using. See app/proguard-rules.pro.

To enable Proguard, edit android/app/build.gradle:

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = true

React Native: Image snippets

Full width & height

import React, { Component } from 'react';
import { View, Image } from 'react-native';
import splashImage from '../assets/img/Marvel-Comics-Logo.png';

class Splash extends Component {
    render() {
        const { imageStyle, containerStyle } = styles;
        return (
            <View style={containerStyle}>
                    <Image
                        style={imageStyle}
                        source={splashImage}
                    />
            </View>
        );
    }
}

const styles = {
    containerStyle: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'stretch'
    },
    imageStyle: {
        flexGrow: 1,
        height: null,
        width: null,
        alignItems: 'center',
        justifyContent: 'center'
    }
};
export default Splash;

 

 

React Native: Generating Signed APK (Android)

[Fuente: https://facebook.github.io/react-native/docs/signed-apk-android.html]

Android requires that all apps be digitally signed with a certificate before they can be installed, so to distribute your Android application via Google Play store, you’ll need to generate a signed release APK. The Signing Your Applications page on Android Developers documentation describes the topic in detail. This guide covers the process in brief, as well as lists the steps required to package the JavaScript bundle.

Generating a signing key

You can generate a private signing key using keytool. On Windows keytool must be run from C:\Program Files\Java\jdkx.x.x_x\bin. In Mac usually is in system path:

$ keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

This command prompts you for passwords for the keystore and key, and to provide the Distinguished Name fields for your key. It then generates the keystore as a file called my-release-key.keystore.

The keystore contains a single key, valid for 10000 days. The alias is a name that you will use later when signing your app, so remember to take note of the alias.

Note: Remember to keep your keystore file private and never commit it to version control.

Setting up gradle variables

  1. Place the my-release-key.keystore file under the android/app directory in your project folder.
  2. Edit the file ~/.gradle/gradle.properties or android/gradle.properties and add the following (replace ***** with the correct keystore password, alias and key password),
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****

These are going to be global gradle variables, which we can later use in our gradle config to sign our app.

Note about saving the keystore: Once you publish the app on the Play Store, you will need to republish your app under a different package name (losing all downloads and ratings) if you want to change the signing key at any point. So backup your keystore and don’t forget the passwords.

Note about security: If you are not keen on storing your passwords in plaintext and you are running OSX, you can also store your credentials in the Keychain Access app. Then you can skip the two last rows in ~/.gradle/gradle.properties.

Adding signing config to your app’s gradle config

Edit the file android/app/build.gradle in your project folder and add the signing config,

...
android {
    ...
    defaultConfig { ... }
    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}
...

Generating the release APK

Simply run the following in a terminal:

$ cd android && ./gradlew assembleRelease

Gradle’s assembleRelease will bundle all the JavaScript needed to run your app into the APK. If you need to change the way the JavaScript bundle and/or drawable resources are bundled (e.g. if you changed the default file/folder names or the general structure of the project), have a look at android/app/build.gradle to see how you can update it to reflect these changes.

The generated APK can be found under android/app/build/outputs/apk/app-release.apk, and is ready to be distributed.

NOTE: We need to remove node_modules/**/*.bin folders to not to get error

Testing the release build of your app

Before uploading the release build to the Play Store, make sure you test it thoroughly. First uninstall any previous version of the app you already have installed. Install it on the device using:

$ react-native run-android --variant=release

Note that --variant=release is only available if you’ve set up signing as described above.

You can kill any running packager instances, all your framework and JavaScript code is bundled in the APK’s assets.

Angular 1.5 : A guide to build components

[Source: https://www.sitepoint.com/building-angular-1-5-components/]

In Angular 1, components are the mechanism which allows you to create your own custom HTML elements. This has been possible with Angular directives in the past, but components build on the various improvements that have been made to Angular and enforce best practices in how they are built and designed.

In this article, we’re going to dig into the design of components and how to put them to use inside of your applications. If you haven’t already started to use components in Angular 1, you can read about their syntax and design in one of our recent tutorials. My goal is to outline some best practices that will improve the quality of your application.

It should also be noted that many of the best practices of Angular 2 are brought into Angular 1 through the new components API, allowing you to build applications that are more easily refactored later. Angular 2 has influenced the way that we think about and design Angular 1 components, but there are still a number of distinct differences. Angular 1 is still a very powerful tool for building applications, so I believe it is worthwhile to invest in improving your applications with components even if you aren’t planning or ready to migrate to Angular 2.

What Makes a Good Component?

Components should be designed with a number of key characteristics in mind to make them a powerful building block for your application. We’ll dig into each of these in more detail, but here are the primary concepts components should adhere to.

  • Isolated – The logic of the component should be encapsulated to remain internal and private. This helps create less coupling between components.
  • Focused – Components should act as a single unit for one primary task, which makes them easy to reason about and often more reusable.
  • One-Way Binding – When possible, components should leverage one-way binding to reduce the load on the digest cycle.
  • Use Lifecycle Events – The lifecycle of a component starts with instanciation and ends with removal from the page. It is to best to hook into these events to maintain the component over time.
  • Well Defined API – Components should accept configuration as attributes in a consistent manner, so it is easy to know how to use them.
  • Emit Events – In order to communicate with other components, they should emit events with appropriate names and data.

Now let’s start by looking at why and how components should be isolated and encapsulated from the rest of the application.

Components Should Be Isolated

The evolution of Angular 1 capabilities has been to enable isolated and encapsulated components, and for good reason. Some of the early applications were highly coupled with the use of $scope and nested controllers. Originally Angular didn’t provide a solution, but now it does.

Good components do not expose their internal logic. Thanks to the way they are designed, this is pretty easy to accomplish. However, resist any temptation to abuse components by using $scope unless absolutely necessary, such as emitting/broadcasting events.

Components Should Be Focused

Components should take on a single role. This is important for testability, reusability, and simplicity. It is better to make additional components rather than overload a single one. This doesn’t mean you won’t have larger or more complex components, it simply means each component should remain focused on its primary job.

I’ve classified components into four primary groups based on their role in the application to help you think about how you design your components. There is no different syntax to build these different types of components — it is just important to consider the specific role a component takes.

These types are based on my 5+ years of Angular experience. You may choose to organize slightly differently, but the underlying concept is to ensure your components have a clear role.

App Components

There can be only one app component that acts like the root of your application. You can think of it like having only one component in the body of your web application, and all other logic is loaded through it.

<body>
  <app></app>
</body>

This is recommended primarily for Angular 2 design parity, so it will be easier to migrate some day should you wish. It also helps with testing by moving all of the the root content of your application into a single component, instead of having some of it in the index.html file. The app component also gives you a place to do app instantiation so you don’t have to do it in the app run method, enhancing testability and decreasing reliance upon $rootScope.

This component should be as simple as possible. It probably will contain just a template and not contain any bindings or a controller if possible. It does not replace ng-app or the need to bootstrap your application, however.

Routing Components

In the past, we’ve linked controllers and templates in a ui-router state (or ngRoute  route). Now it is possible to link a route directly to a component, so the component is still the place in which a controller and template are paired, but with the benefit of being also routable.

For example, with ui-router this is how we would link a template and controller.

$stateProvider.state('mystate', {
  url: '/',
  templateUrl: 'views/mystate.html',
  controller: MyStateController
});

Now, you can link a url directly to a component instead.

$stateProvider.state('mystate', {
  url: '/',
  component: 'mystate'
});

These components can bind data from the route params (such as an item id), and their role is to focus on setting up the route to load the other components needed. This seemingly minor change to defining routes is actually very important for Angular 2 migration capability, but also important in Angular 1.5 to better encapsulate a template and controller at the component level.

Angular 1 actually has two router modules, ngRoute and ngComponentRouter. Only ngComponentRouter supports components, but it is also deprecated. I think the best bet is to go with ui-router.

Stateful Components

Most of the unique components you’ll build for your application are stateful. This is where you’ll actually put your application business logic, make HTTP requests, handle forms, and other stateful tasks. These components are likely unique to your application, and they focus on maintaining data over visual presentation.

Imagine you have a controller that loads a user’s profile data to display, and has a corresponding template (not shown here) linked together in a directive. This snippet might be the most basic controller to accomplish the job.

.controller('ProfileCtrl', function ($scope, $http) {
  $http.get('/api/profile').then(function (data) {
    $scope.profile = data;
  });
})
.directive('profile', function() {
  return {
    templateUrl: 'views/profile.html',
    controller: 'ProfileCtrl'
  }
})

With components, you can design this better than before. Ideally, you would also use a service instead of $http directly in the controller.

.component('profile', {
  templateUrl: 'views/profile.html',
  controller: function($http) {
    var vm = this;
    // Called when component is ready, see below
    vm.$onInit = function() {
      $http.get('/api/profile').then(function (data) {
        vm.profile = data;
      });
    };
  }
})

Now you have a component that loads its own data, thus making it stateful. These types of components are similar to routing components, except they might be used without being linked to a single route.

Stateful components will use other (stateless) components to actually render out the UI. Also, you’ll still want to use services instead of putting data access logic directly in the controller.

Stateless Components

Stateless components are focused on rendering without managing business logic, and need not be unique to any particular application. For exampe most components that are used for UI elements (such as form controls, cards, etc) don’t also handle logic like loading data or saving a form. They are intended to be highly modular, reusable, and isolated.

A stateless component may not need a controller, if it just displays data or controls everything in the template. They will accept input from a stateful component. This example takes a value from the stateful component (the profile example above) and displays an avatar.

.component('avatar', {
  template: '<img ng-src="http://example.com/images/{{vm.username}}.png" />',
  bindings: {
    username: '<'
  },
  controllerAs: 'vm'
})

To use it, the stateful component would pass the username via the attribute like so <avatar username="vm.profile.username">.

Most libraries you use are a collection of stateless components (and perhaps services). They certainly can accept configuration to modify their behavior, but they are not meant to be in charge of logic outside of their own.

Components Should Use One-way Bindings

This is not a new feature with components, but it is often smart to leverage it with components. The intent of one-way bindings is to avoid loading more work into the digest cycle, which is a major factor in application performance. Data now flows into the component without having to look outside of it (which causes some of the coupling problems that exist today), and the component can simply render itself given that input. This design also lends itself to Angular 2, which helps with future migration.

In this example, the title property is only bound into the component once based on the initial value provided. If the title changes by some outside actor, it does not get reflected in the component. The syntax to denote a binding as one-way is to use the <symbol.

bindings: {
  title: '<'
}

The component will still update when the title property changes, and we’ll cover how to listen for changes to the title property. It is recommended to use one-way anytime you can.

Components Should Consider One-time Bindings

Angular also has the ability to bind data one-time, so you can optimize the digest cycle. Essentially, Angular will wait until the first value that is not undefined is provided into the binding, bind that value, and then (once all bindings have resolved) remove the associated watchers from the digest cycle. This means that particular binding will not add any processing time to the future digest loops.

This is done by putting :: in front of a binding expression. This only makes sense if you know that the input binding will not change over the lifecycle. In this example, if title is a one-way binding, it will continue to be updated inside of the component but the binding here will not update because we denoted it as one-time.

<h1>{{::title}}</h1>

Components Should Use Lifecycle Events

You probably noticed the $onInit function as a new capability. Components have a lifecycle with corresponding events that you should be using to help manage certain aspects of the component.

$onInit()

The first step in the component lifecycle is initialization. This event runs after the controller and bindings are initialized. You should almost always use this method to do component setup or initialization. It will ensure that all values are available to the component before running. If you were to access binding values in the controller directly there is no guarantee those values will be available to you.

controller: function() {
  var vm = this;
  console.log(vm.title); // May not yet be available!
  vm.$onInit = function() {
    console.log(vm.title); // Guaranteed to be available!
  }
}

The next step is linking any child elements from the template. When the component initializes, there is no guarantee it will have also rendered any children used inside of your template. This is important if you need to manipulate the DOM in any way. One important caveat is that templates that are loaded asynchronously might not have loaded by the time this event fires. You can always use a template caching solution to ensure that templates are always available.

controller: function() {
  var vm = this;
  vm.$postLink = function() {
    // Usually safe to do DOM manipulation
  }
}

$onChanges()

While the component is active, it may need to react to changes in input values. One-way bindings will still update your component, but we have a new $onChanges event binding to listen for when the inputs change.

For this sample, imagine there is a product title and description provided to a component. You can detect changes as demonstrated below. You are able to look at the object passed to the function, which has an object mapped to the available bindings with both the current and previous values.

bindings: {
  title: '<'
},
controller: function() {
  var vm = this;
  vm.$onChanges = function($event) {
    console.log($event.title.currentValue); // Get updated value
    console.log($event.title.previousValue); // Get previous value
  }
}

$onDestroy()

The final phase is the removal of the component from the page. This event runs right before the controller and its scope are destroyed. It is important to clean up anything that your component might have created or that holds memory, such as event listeners, watchers, or additional DOM elements.

controller: function() {
  var vm = this;
  vm.$onDestroy = function() {
    // Reset or remove any event listeners or watchers
  }
}

Components Should Have a Well Defined API

To configure and initialize a component with a set of data, a component should use bindings to accept these values. This is sometimes thought of as the component API, which is just a different way of describing the way a component accepts inputs.

The challenge here is to give bindings concise but clear names. Sometimes developers try to shorten names to be really succinct, but this is dangerous for the usage of the component. Imagine we have a component that accepts a stock symbol as input, which of these two are better?

bindings: {
  smb: '<',
  symbol: '<'
}

Hopefully you thought symbol was better. Sometimes developers also like to prefix components and bindings as a way to avoid name collisions. Prefixing the components is sensible, like md-toolbar is a Material toolbar, but prefixing all of the bindings gets verbose and should be avoided.

Components Should Emit Events

In order to communicate with other components, components should emit custom events. There are many examples of using a service and two-way data binding to sync data between components, but events are a better design choice. Events are far more efficient as a means to communicate with the page (and a foundational part of the JavaScript language and the way it works in Angular 2, which is not a coincidence).

Events in Angular can use either $emit (up the scope tree) or $broadcast (down the scope tree). Here is a quick example of events in action.

controller: function($scope, $rootScope) {
  var vm = this;
  vm.$onInit = function() {
    // Emits an event up to parents
    $scope.$emit('componentOnInit');
  };
  vm.$onDestroy = function() {
    // Emits an down child tree, from root
    $rootScope.$broadcast('componentOnDestroy');
  };
}

There are two primary situations where you will need to communicate between components: between components you know about, and components you don’t. To illustrate the difference, let’s imagine we have a set of components that help manage tabs on the page, and a toolbar that has a link to the corresponding help page.

<my-toolbar></my-toolbar>
<my-tabs>
  <my-tab title="Description"></my-tab>
  <my-tab title="Reviews"></my-tab>
  <my-tab title="Support"></my-tab>
</my-tabs>

In this situation, the my-tabs and my-tab components are likely aware of one another, because they work together to create a set of three different tabs. However, the my-toolbar component is outside of their awareness.

Whenever a different tab is selected (which would be an even on the my-tabcomponent instance), the my-tabs component needs to be aware so it can adjust the display of the tabs to show that instance. The my-tab component can emit an event up to the parent my-tabs component. This type of communication is like an internal communication between two components that work together to make a single capability (a tabbed interface).

However, what if my-toolbar wants to know what tab is currently selected so it can change the help button based on what is visible? The my-tab event will never reach my-toolbar because it is not a parent. So another option is to use the $rootScopeto emit the event down the entire component tree, which allows any component to listen and react. The potential downfall here is that your event now reaches every controller, and if another component uses the same event name you could trigger unintended effects.

Decide which of these approaches make sense for your use case, but anytime another component might need to know about an event you’ll likely want to use the second option to emit to the entire component tree.

Summary

Angular 1 applications can now be written with components, which changes the best practices and nature of how we write applications. This is for the better, but just simply using a component doesn’t necessarily make it better than what you had before. Here are the key things to keep in mind as you build your Angular 1 components.

  • Isolate your logic. Keep as much of the component logic internal and away from other aspects of the application to ensure consistency and quality.
  • Keep components simple and focused on a single role. They might be complex components, but the various tasks of a single component should be logically connected as a unit.
  • Use the lifecycle events. By hooking into the component lifecycle, you can ensure that data is ready at the right time and that you can clean up.
  • Use one-way and one-time bindings. When possible, one-way bindings are more efficient and promote good design, while one-time bindings can speed up your application. You can always use $onChanges lifecycle event to watch changes.
  • Use events for communication. Components can communicate using custom events, which is in line with how Angular 2 functions and a better design.
  • Have a well defined API. Ensure that your components are clearly named and easy to understand

 

Angular2 – Typescript

Introduction

TypeScript is a superset to JavaScript, which means, that it compiles into pure JavaScript in the end.

Why do we use it then? First, it provides ‘strong typing’ (that’s where the name comes from). This means that we can (and should) assign types to our variables and class members. These types won’t compile to JavaScript (as JS does not know types) but we will get compilation errors if we assign wrong types or make any other type-related errors. This is a HUGE help in the daily development work and should not be underestimated!

Second, TypeScript introduces some nice features, JS does not have out of the box (at least in the ES5 specification). This includes classes (‘class’ keyword), interfaces, generics and modules. Being able to use these constructs makes our code cleaner, easier to read and helps us avoid nasty errors. Especially in combination with the strong typing we are really able to write high quality code and track down errors quickly.

Where can I learn all the TypeScript fundamentals?

There are a lot of great resources out there which will get you started very quickly. The official documentation is not too bad to be honest, so you may give it a try: http://www.typescriptlang.org/Handbook

There’s also a course here on Udemy, though I have not tested it! https://www.udemy.com/typescript/

Can we mix TypeScript and JavaScript?

Yes, we can. No one is preventing us from not setting types, using ‘var’ instead of ‘let’ or using pure JavaScript libraries (i.e. libraries which don’t offer a TypeScript version/ implementation).

Can’t I use ‘normal’ JavaScript to write Angular 2 applications?

You can absolutely do that. But currently finding good documentation and examples on Angular 2 using plain JavaScript is extremely hard. And to be honest: TypeScript will be the standard ‘language’ to be used when developing Angular 2 applications. So I definitely recommend using TypeScript.

Using types

  • We can define type for variables. Example:

01-typing/typing.ts

// Declaring a variable with a type
// Using the 'let' keyword to create a variable ('const' would define an immutable constant)
let myString: string;
myString = 'This is a string';
  • If we try to assign a different type will get an error on the typescript compiler
// Declaring a variable with a type
// Using the 'let' keyword to create a variable ('const' would define an immutable constant)
let myString: string;
myString = 'This is a string';

// Try to assign a number to a string => Error
myString = 4;
> tsc typing
typing.ts(10,1): error TS2322: Type '4' is not assignable to type 'string'
  • Typescript can also infer types. So in this example will also get an error:
// TypeScript can also infer types
let anotherString = 'This is a string without :string'; // => Type 'string' was inferred from the assigned value

// This will still resolve in a compilation error
anotherString = 4;
  • WARNING: Infering the type doesnt work if we not assign a value in declaration
// TypeScript may only infer values when those values are assigned at the declaration
// This does not work:
let yetAnotherString;
yetAnotherString = 'This is a string';

// TypeScript does not know the type, therefore we don't get an error ... but no we're also ignoring TypeScripts strength: Typing
yetAnotherString = 5;
  • By default if we dont specify type in the declaration will get the type any.
let yetAnotherString: any;
  • Other basic types:
// Other basic types

let aString: string;
let aNumber: number;
let aBoolean: boolean;
let anArray: Array<string>; // This is a generic type => May only hold 'strings' in this case
let anything: any; // Any can be used if we don't know the actual type => Use it rarely!
// We also got void (=> nothing) and enums (a set of numeric values)
  • We can also create custom types.
  • Summary : Strong types your variables: prevent errors.

 

Classes

// Classes allow us to create 'blueprints' for objects
// In Angular 2 we use classes a lot. For example to create Components, Services, Directives, Pipes, ...

// How to create a class

class Car {
    engineName: string;
    gears: number;
    private speed: number;

    constructor(speed: number) {
        this.speed = speed || 0;
    }

    accelerate(): void {
        this.speed++;
    }

    throttle():void {
        this.speed--;
    }

    getSpeed():void {
        console.log(this.speed);
    }

    static numberOfWheels(): number {
        return 4;
    }
}

// Instantiate (create) an object from a class

let car = new Car(5);
car.accelerate();
car.getSpeed();

console.log(Car.numberOfWheels());

* In old Javascript we already got class but now with TS use of classes is easier.

  • We can define private properties accessible from outside. By default are public
  • Static methods for been called for the class not for the instance. Yo dont need to create an object to call it:
    console.log(Car.numberOfWheels());

 

Interfaces

// Interfaces allow us to create contracts other classes/ objects have to implement
// We can use them to define custom types without creating classes
// Interfaces ARE NOT compiled to JavaScript! It's just for checking/ validation done by our TypeScript compiler

// Example interface

interface User {
    username: string;
    password: string;
    confirmPassword?: string; // Optional property => Does not have to be implemented
}

let user:User;

// This value does not satisfy the interface => Compilation error
// user = { anything: 'anything', anynumber: 5};

// This value does satisfy the interface
user = {username: 'max', password: 'supersecret'};

// Interfaces can also contain functions (without the function body - as it only is a blueprint/ requirement)

interface CanDrive {
    accelerate(speed:number): void;
}

let car:CanDrive = {
    accelerate: function (speed:number) {
        // ...
    }
};

Generics

  • Generic types allow us to be flexible with typing.
// Generics are types which can hold/ use several types
// We're only touching the very basics here - you can go MUCH more into detail

// Consider the Array object

let numberArray: Array<number>; // This array will only accept numbers

// Try to initialize it with strings

// numberArray = ['test']; // => Error
numberArray = [1,2,3];

 

 

Wrap up & modules

// TypeScript is modular, we can divide our code up over several files
// In Angular 2 we then use  "import {} from ''" to access the code in these files

// We export a class, interface, variable, ... by adding 'export' keyword in front of it

export class ExportedClass {
    // This class is exported
}

Deep dive into TypeScript

How to learn TypeScript

Throughout this course we’re always using TypeScript and I am convinced that you’ll be able to learn it ‘on the fly’. But a little head start is never wrong.

What is TypeScript?

TypeScript is a superset to JavaScript, which means, that it compiles into pure JavaScript in the end. Why do we use it then?

First, it provides ‘strong typing’ (that’s where the name comes from). This means that we can (and should) assign types to our variables and class members. These types won’t compile to JavaScript (as JS does not know types) but we will get compilation errors if we assign wrong types or make any other type-related errors. This is a HUGE help in the daily development work and should not be underestimated!

Second, TypeScript introduces some nice features, JS does not have out of the box (at least in the ES5 specification). This includes classes (‘class’ keyword), interfaces, generics and modules. Being able to use these constructs makes our code cleaner, easier to read and helps us avoid nasty errors. Especially in combination with the strong typing we are really able to write high quality code and track down errors quickly.

Where can I learn all the TypeScript fundamentals?

There are a lot of great resources out there which will get you started very quickly.

The official documentation is not too bad to be honest, so you may give it a try: http://www.typescriptlang.org/Handbook

There’s also a course here on Udemy, though I have not tested it! https://www.udemy.com/typescript/

Can we mix TypeScript and JavaScript?

Yes, we can. No one is preventing us from not setting types, using ‘var’ instead of ‘let’ or using pure JavaScript libraries (i.e. libraries which don’t offer a TypeScript version/ implementation).

Can’t I use ‘normal’ JavaScript to write Angular 2 applications?

You can absolutely do that. But currently finding good documentation and examples on Angular 2 using plain JavaScript is extremely hard. And to be honest: TypeScript will be the standard ‘language’ to be used when developing Angular 2 applications. So I definitely recommend using TypeScript