Themes in Nativescript with Webpack

IT-ROCKSTAR ROBIN VAN TIENHOVEN

Introduction

For the last couple of years I have been working with technologies such as Typescript, Angular(JS) and Cordova. These technologies combine quite well when creating a small and simple mobile app or converting a website to one. But there are instances where applications that are build with these technologies tend to get slow or where you rather use a native implementation of a feature instead of building it in TypeScript. Sure, you could write those features in native Android and iOS code and then integrate it into your Cordova project, but a large part of your application will still be running in a WebView. That forms a bottleneck which keeps your app from performing as well as native apps do.

A little while ago I came across NativeScript. It claims to deliver native performance, while allowing you to develop your application like a ‘normal’ web application. This is due to the nature of NativeScript, it compiles down to binaries. That’s worth a try isn’t it?!

One of the usecases I came across was creating a second theme. There are some libraries out there for supporting theme switching in NativeScript, but they are missing quite a lot of documentation when it comes to the combination of NativeScript and Webpack. So I decided to write my own blog about it.

The goal of our application

We are going to create a disco application, with which you can change the t5heme with the press of a button. That’s what I call an awesome app to bring to your next party!

The steps required to get a NativeScript development environment set up can be found here: Quick setup docs. Do note the tns doctor command. With this command NativeScript can determine (and install!) missing dependencies. That saves a whole lot of time setting up!

Our project’s global dependencies (npm i -g <package>):

  • @angular/cli --> Because our application is based on Angular
  • NativeScript --> Our code base
  • @nativescript/schematics --> The integration of NativeScript into the Angular-CLI

Getting started

To keep it simple we are going to start with a new application. In order to create a new application, we can run the following commands from the command prompt or Terminal:

ng new --collection=@nativescript/schematics my-personal-disco --style=scss
cd my-personal-disco
tns platform add android

Let’s break this down
The command ng new --collection=@nativescript/schematics my-personal-disco --style=scss consists of three parts:

  1. The first part --collection=@nativescript/schematics tells the Angular-CLI that we want to use NativeScript as the basis for our application.
  2. The second part my-personal-disco is our project name.
  3. The last part, --style=scss tells the CLI that we want to use SCSS for our styling.

We’ve also added the Android build platform with the command tns platform add android. You could also add the iOS build platform if you have access to a Mac.

The theme switcher library

Now with our base application setup we can start working on the theme switching. For this we need the nativescript-themes plugin. You can install this plugin by running the following command:

tns plugin add nativescript-themes@2.0.1

Although the name may look like the core NativeScript package @nativescript/theme, it is not the same! The core package only offers us a single theme for the whole application and no functionality to switch a theme on the fly. That would be a boring disco app!

 

Defining our themes

The next step is to add our theme style files. In these files we define our two themes that we want to use to create a disco effect, a yellow and a red theme (you can add more if you’d like).

Create a new file app/styles/themes/yellow.scss and add the following styling:

code

And create a app/styles/themes/red.scss for the red theme:


code

Wrapping the theme switcher

Next up is wrapping our theme switch library, so that we don’t expose it everywhere in our application (makes replacing the library easy).

In order to change the current theme, we need to tell the nativescript-themes plugin to use another theme. The best way to do this is to create a service around the plugin so that we don’t expose the dependency all over our project. Let’s call this the ThemeService.

Create a new service in app/theme/theme.service.ts:

code

This service holds the path to our theme files (more on this later) and the option to set a new theme. We have also added an enum with our supported themes, so that we can strictly type which themes we support in our application.

Using the theme service

Now that we have wrapped our theme switcher plugin and made it available throughout our whole application we can now start using it.
The next step is to edit our home page (the one page that the CLI gave us for free). Change the app/home/home.component.ts file to the following:  

code


The last step is adding a button so we can ‘start the party’. For this we must add the following code to app/home/home.component.htmlIn this component we inject the ThemeService and expose a method called startTheParty. Within this method we start an rxjs interval that will change the theme every 100ms. We change the theme in 3 separate steps to keep the code clean and easy to read.

code

Are we ready to party?

Nope not yet. There is one last thing we need to add in order to get theme switching working. If you would run the application right now (tns run android, be sure to connect your mobile phone to your PC or have an emulator setup) you will notice the button won’t have any effect. All of our code is in the right place and everything is working fine, but the problem is that the theme files are missing from our build folder. This means we cannot switch to any theme file, since they don’t exists.

If you would build the code (tns build android) and look in the build folder platforms/android/app/src/main/assets/app you will notice that our theme files are not there. This is because we are working with Webpack. Webpack only adds files to the build that are referenced in the source code. Since we are not referencing our theme files (and we don’t want to include them directly into our code, because then we won’t be able to swap them anymore) we need to tell webpack to also pack our theme files.

Head over to your webpack.config.js file and change the CopyWebpackPlugin configuration to the following:

code

Aslo add the following line to the top of the webpack file:

code

So, what is going on here? Let’s break it down
First we are telling the copy plugin to copy all theme files that have the .scss extension to our build folder assets/themes/ (this matches the THEME_PATH property in our ThemeService). The name ([name].css) will be replaced by the plugin with the original name.

The transform function uses node-sass to convert the scss styling into css, since scss cannot be used directly in the browser.

If we now run tns run android again and press the ‘Time to party!’ button, we can see that the application now changes the background every 100ms. By adding more theme files, we can make an even cooler disco app!

Conclusion

We have created a simple application in which we added a theme service for managing theme changes. We also added an interval to change our current theme every 100ms. To get this all working with webpack we told webpack where to find our theme files and where to place them in the build.

That’s it! You now have a working disco app you can use on your next party!

You can find the full project in my github.