 Welcome to one source to rule them all. We want it all. It's not uncommon that we, and the decision makers really, want it all. In a world of applications, we want both a web presence and a native mobile presence. What we don't want is to maintain competing parallel code bases. What this leads to is a tug of war between wanting to maintain only one source code versus our app having a home everywhere that our users are found. So who am I? Well, I'm a KiltWearing coder. My name is John Iswicky. I like to call myself your friendly neighborhood kilter coder. If I was on stage today, you'd be seeing my kilt, but right now, you'd show me this little tiny box. I'm a husband, a father, currently a mini farmer. I love Pathfinder, which is tabletop RPG, cooking, and the Disney parks, which I live in Florida, so it works out convenient for me. I'm also tech-leaded Disney streaming. I build software to help support the media processing for Disney+, but I'm also very passionate about native script, which is why I'm giving this talk today. We're gonna forge one source, and it's gonna be forged in JavaScript. You might notice some veiled references to a certain movie that involves some hobbits, a dwarf, an elf. You might notice parallels there. So what are we gonna do today? Well, we're gonna talk about what do we want. Then we're gonna go on to what is native script. Native script's gonna be the key here on how we're gonna get to this end goal of one source. We're gonna talk about how do we share code because we said that's what part of what we want is to share code, and then we're gonna look explicitly at Xplot, which is one of the solutions you can have for sharing code. So let's touch again on what do we want. So we want both a web and a native application. That is the goal of what we wanna get to here. And we want code reuse. If we make a really cool avatar selector, we wanna be able to use it on web and on native, and we wanna have that same experience for our users, especially if it's really cool. What we don't want is to have multiple separate projects. And sometimes as front end developers, we just wanna get to play with native without the overhead of learning another language. We wanna use the tools that we already have, and that's where native script comes into play. So what is native script? Native script is an open source framework designed to empower a JavaScript with native APIs. It allows you to choose the flavor that you already love. Do you wanna code in JavaScript? Maybe you like types in TypeScript. I know I do. Do you like your framework of Angular? Do you prefer to use Ionic or View or React or even Svelte? Guess what? All of these can be used with native script. So all of these can be used to develop a native application and using the JavaScript tools that you are used to using. Everything you need to find out about native script can be found on nativescript.org. That is your home to start with. So native script gives you native performance. It is very extensible. It's very easy to pull in new things in the native script to new native experiences. It allows you to develop with what you already know as we talk about all those things you can use. It's cross-platform. So it works for both Android and iOS. It is free and open source and it has a strong backing. Native script is actually an incubating project under the OpenJS Foundation, which means they are in the process of completing their onboarding to fully join the foundation. So it's got the backing here of OpenJS. Native script layer. So the way this works is, what we're gonna see here, we're gonna write our app logic in Angular. So the UI will have an HTML like syntax to generate that native UI and we'll style it with CSS. So how are we gonna share our code? So in Angular, a component has a TypeScript class, an HTML template, and a style sheet. In native script with Angular, you have a component that has a TypeScript class and an HTML like syntax template and a style sheet. I think you see where we're going here. So if all these things were the same, you could easily just have two HTML files and two style sheets in the same JavaScript code if everything was the same and they would be able to be able to reuse. We're gonna go steps beyond there because that's not quite what we want. So let's look at some of the fundamental lessons of good code sharing. So these are from the native script TSC, Technical Steering Committee. So a lot of words here to keep it brief. This is their first lesson learned. Really what this is, it's about making devs lives easier. Share now and easily and maintain and scale easily later. Number two is to use existing tooling. We don't wanna integrate with something new tooling just to be able to do this code sharing. We wanna use the tooling we already have. Number three, what this really boils down to is we don't wanna add new extensions or structures just for the sake of sharing. So we shouldn't have a new file extension we need just to be able to share. We're using HTML, it should be .html. We also wanna follow good standards for code organization. We don't wanna add extra layers just because it's what makes sharing work. Those extra layers are okay if they're going to be for the purposes of actually organizing our code in a way that makes sense. Number four, this really comes down to, it will boil down to, it's easy to identify and distribute separately. So it's easy to know shared code from non-shared code and it's easy to know what you're gonna do and how you're gonna separate and what's gonna be deployed if you're deploying your native app versus your web. And finally number five is to use fundamental JavaScript and TypeScript sharing approaches. So there are already inherently ways to do that in JavaScript and TypeScript so we should use those in our approach. So from this, there are some recommended solutions. The first one is Narwhal NX DevTools with native script NX. This is center round JavaScript and TypeScript which means it meets lessons one and five. It uses standard build tooling which means meets lesson two. There's no custom file extensions so meets lesson three. And NX splits into apps and libs to identify targets that consume shared code. So you have your apps for these or your individual applications for web and native. And then you have your libs for your shared code so that's lesson four. It's easy to tell what is shared and what's not. In general NX practices can have a little bit of a learning curve if you're not used to using them but once you do get over that everything else is just what you already need to know. Second is the one that we'll talk more about afterwards is Narwhal NX DevTools but with NStudio XPLAT. So this is center round JavaScript and TypeScript. They use a standard build tooling. There's no custom file extensions and because NX it's built on top of NX it uses that same splitting between apps and libs to identify the targets. So this meets all five real lessons. What it does is this builds on top of NX to scale across more paradigms and it provides an opinionated architecture provided by XPLAT to help avoid common pitfalls that are learned from cross-platform development. This is developed by NStudio has done a lot of development in NX and a lot of shared development. So these are opinionated as much as Angular is way to do it but for some of the common pitfalls they've learned in doing exactly what we want to do here today. This is why this is my method of choice that I use. Next, another option is yarn workspaces. So this is center round JavaScript and TypeScript. Uses standard build tooling and no custom file extensions. Unfortunately this doesn't meet lesson four. You can share in link dependencies but you're kind of on your own for organizational structure. There's no out of the box deployment and distribution for app targets versus shared code. This is more geared towards open source library management but if you're already using yarn workspaces this can be a good solution for you and your team. And the last recommended one is Lerna. So this is center on JavaScript and TypeScript. Uses standard build tooling no custom file extensions but again we're missing lesson four. This is a tool for managing JavaScript projects with multiple packages. Again you're on your own for organizational structure and there's no out of the box deployment distribution for app targets versus shared code. There's no more geared towards open source library management with no extra helpful tooling for workspace management but again if you're using Lerna already this could be a very good option for you. Let's talk through Xplot because it's what I use. Xplot is cross platform tools for NX workspaces. Xplot is an added value pack for NX to provide app generators and optional supporting architecture. It supports various platforms including NativeScript, Web, Ionic and also Electron. So first to get set up you're going to need to set up your NativeScript. So you can find anything you need to do here about docs.nativescript.org. We're not going to walk through all this. First you're going to have to have Node which means you might want NVM or your own manager of choice. You're going to need the NativeScript CLI to build NativeScript and then you're going to need your app environment. If you want to develop for Android you're going to need Android Studio and JDK if you're going to develop for Mac. For iOS you're going to need Xcode, for you exactly what to install, what commands to run so it's very, very good documentation on how to get set up and running. I can vouch that it's pretty easy to do because I had to recently reset up my new machine for this and it was no problem at all. Then you need to start with creating an NX workspace. You're going to use npx create NX workspace. This will set up your workspace with all the base structure that you need. NX creates you a suite of powerful and extendable dev tools to build an architect at scale. So I encourage you to, if you want to learn more about NX, check out Narwhal NRWL. This is their tools, they're a great company and you can learn more about this there. Next you need to have your CLIs and Xplats. So you're going to install your Narwhal CLI which is used for NX. You're going to need to install the Xplat package. You're going to need to add that to this app and then you're going to generate your app. NX Generate app is going to set up individual apps you're going to build within this. When we want to generate an app, you're going to give it an app name. You're going to select the type of app to add and then it's going to generate the code. You can see here you have different options. Electron, Express, Ionic, NativeScript, Nest, Node, React, Web. All types here that you're going to see when you want to generate an app. So there's many benefits of using Xplat. First you get a robust structure for code sharing. This also makes it easier to take advantage of deeper platform integration. So when you want to use your web camera you can easily integrate how you do it on native versus how you're going to do it on the web. It's also built to support large complex code bases with sharing. So this allows you to build those very large scales application that can have a lot of dependencies and different pieces with it and code share them very easily. So it's definitely built for working at scale. NX is designed to be using a Monorepo. So if you look here, here's how it's going to break it down. This is not a talk about whether to use or not use Monorepo. This is built design that you can easily have a Monorepo. If you don't want to have a Monorepo, you can still use this. But this is all about sharing code across the entire integration for reuse and a single set of dependencies. So we're going to add multiple apps. You can see here I've added a native script app called Hobbit Fitness Pal and a web app called Hobbit Fitness Pal and it also adds this end-to-end for testing for me. You end up with this powerful code sharing structure. You get the individual apps by types and this is going to be all your shared code. So you're going to have your two places. You can see your Libs. This is all the shared code. And then within that we'll see that you can have native script and web shared as folders. But then you also have your actual apps. So you could have something that's shared for web that can be used in multiple web apps if you're going with a Monorepo here. You doesn't have to just be one native app and one web app and shared code. This can share across multiple applications. So generating code with XPlot is where we have the XPlot options. So we're going to look here if we ran help with generating a service here. This is going to tell us what our options are. So you give it a name. You can whether you're going to target this into the feature section. You can target what project is going to be on. What platforms. You want to skip some extra formatting files. The dry run which is what we'll write. I'll show you some here to see how they come out. Skipping NX Cache which is to avoid rebuilding the same code again and again so you can use NX Cloud. So you can use NX Cloud to build your apps without needing to build them locally. And then obviously we ran the help command here to show us what options are available. So let's create a shared service here. If we're going to generate it, we have NX Generate and then we specify at nstudio slash angular service. This will generate a service using the nstudio XPlot generators. And if we call it, we're going to name a track to do a dry run. This will generate as you can see a service inside of Libs XPlot Core. So this is where your shared services will go. In your shared code base under XPlot and this is a core because it's a service it's going to be the single term. So we're going to do that and generate create our own service called track overview service for our fake application here. All it's going to do here is have a function that is going to get and return an observable of these track options which is just some mock data on our code that's going to return this data back. Let's look at something a little more complex and generate a component in XPlot. First we're going to look at using the platform flag. So here we're going to generate a component and we're going to use platform's web and native script with the flag of create base true. This is going to create a shared component for the platform web and for the platform native script and it's going to also create a base component that they're going to use. So we have Libs XPlot features where this base component lives. Then we're going to have in XPlot web and XPlot native script we're going to have a meal list component HTML and TypeScript. So this is going to generate them for the platform. So this is saying hey create me a component that is for the web and for native script that will share a base component. Next we're going to generate a component with the projects flag. Here we can specify that we want to create a component for the web Hobbit FitnessPal and the native script Hobbit FitnessPal projects for those actual apps. This will create in the apps web Hobbit FitnessPal and the apps native script Hobbit FitnessPal. It will create components and create their HTML and TypeScript files. You notice here we can't use the generate base component. There is no shared implementation but we can change that and we can have a lot out of the generators off the base. So here we have a home base component. This is our home component. It's always extending this base component. You see here we have a service that we're going to call. We're going to get those tracking overviews that we call. We're going to just put that into an observable that we're going to be able to use the async pipe on. Very very simple component. Very very simple TypeScript one called home base component. And then I created a home web component which extends the home base component. Nothing else to it. It doesn't need to do anything else. All it needs to do is get that data so we can display it. Displaying it is where it comes into place. So the home web component has its HTML file that we're going to see here our normal HTML and style with our Angular components here. So we see we have a component for the header padding. We have a paragraph with some text and then we have a part where we're going to loop through those tracking overviews with the async pipe and display something there and we're going to have a button at the bottom. Next we're going to create a native script home component. You notice it's the same as the web. We're expanding the base component and no other changes needed. The logic is the same. There's no different logic needed. All that this home component needs to do is get the data and display it. The displaying is different. So to display a native script we need to use native script template. So we said there's an HTML like syntax. So you can see here we have tags like we do in HTML but they have different needs. So one of the things you have to worry about a lot in native script development is the layout. So here you see we're using a doc layout to be able to doc something to the bottom and the top. Then we're going to use a grid layout for our button and we're going to put that at the bottom and then we're going to have a stack layout with the header and a label for the text that was our paragraph tag and then we're going to have a wrap layout which we're going to create labels for the other part. So this is generating a UI that's going to look almost exactly the same between the two of them is the goal here. They can be completely different they don't have to be anywhere close to the same. But we're generating something similar to the other one just in the different ways of doing it. Create the same experience. So getting things running is also quite easy. To run the web app you just run nx serve and give the name of the app you want to run. To run the native app again use nx run the name of the app and use colon which platform you run on iOS or Android and then it will bring that app up. So that's enough talking. Let's actually go ahead and see this in action. So you can see here we have two different apps up and running. We have our web app on the left and our mobile app on the right. You can see we have the same basic thing here. We have the name of the app, the text of ensuring you don't miss any important meals of the day because Hobbits eat a lot of times of the day so we need to make sure we are always eating our meals and tracking them so that we never miss. Because yes we had breakfast but did you have second breakfast? Did you have 11 Z's? Let's make sure of it. So what we're going to do is we're going to go here we have these are our two home components we created very similar and then we're going to go ahead and say okay we want to add. So if we want to add we've got to give the camera moment here to load and then we can put a picture up of what we had to eat give it a name and then capture the picture and then it'll tell us our meal is tracked remembered to stop before nightfall and we can go onward and it will track that meal. So that was using the code on the web to be able to access the web camera. On our native mobile app the way to access camera is different but if we go to track our app we have the same thing here we can add a name and then when we go to capture a meal that will go to access the camera unfortunately the iOS emulator doesn't allow me to access the camera right away so instead it acts the camera roll but you get that same prompt that you normally do of do you want to go to the camera do you want to have so we can go ahead and say we just pick a picture and then instead of putting that other message up there we can just use the dialogue native on the app and say hey pop me up a dialogue you know notification is going to say this is the message here's the okay message they click okay and then they can go ahead and route it back to the home so it's great because you can use those native integrations here but still have the shared code base of the same idea here we want to display these things we want to allow you to add a meal and have that meal has an image and it has text we can do a lot more with it we can make selections we can do other cool things here but this is just the basic idea of what we want to do here so how did we go about doing that so we had a we created a meal add base component which has this function to track a meal which knows how to call our track service with this meal object we're also going to give it access to the router server router for kind of that navigation that we saw so for the web when we're looking at this meal add we extend that meal add base component and for the web we do something a little different here so you can see here on the navigator we have navigator media devices and this is what we do to see that the camera is accessible and we're going to create these things to put the video in there so that preview that we saw here this is how we're going to get that there and I had already allowed the camera to be used but if the first time you come to this app it will actually prompt you do you want to allow the web camera and then I have this capture image function which basically is what's going to use that canvas native element to draw the image from the camera and then save it from there this is the process of how you can use your camera to take a picture on the web so this is my web way of let's take a picture from your web camera in order to save it for our meal now what this allows is then we can do the meal add component for the native script and here extend that same base meal that has that function to say track this meal but instead I can do it here with the native skip camera way and so we have this ability we have this requesting permissions to be able to use the camera to access the pictures and if we've already done that it will move along and otherwise you can have an error if they reject that okay you can't track a picture but you can just put the name in so you can handle it however you want to but the important part here is we have the same capture image function but instead this is going to call camera dot take picture which is going to give us back this and that's what's going to either you're selecting it from your files or you're going to take the picture from the camera and it's going to hand that back off to the service and then we're going to take that we're going to call that same track meal function so both of these have a text box that had the meal name that we captured and then takes this image and puts it with it and then we'll send that off to the track meal function that's from our base component and then here instead of the other one we show some text on the screen here we create some alert options and then we say dialogues dot alert to get that native alert so to look the way it is native on android and native on iOS to give you that what that alert should look like and pop up and then when they say okay there we're going to take it back to home which is where the router comes into play this gives you the basics to be able to create that one source so you can forge it now you have one source to rule them all one source to find them one source to bring them all and in the java script bind them so go forge your precious create your native app create your mobile app and combine that with your web app and share that code base you know this gives you that starting point of what you need to do and then it's up from there it's just up to your creativity on how you do this so many great things you can do there's other great talks here at the open js conference that are also on native script there's so many cool things you can do beyond this is just giving the basis this is giving you that framework and then you can just go and create from there and create your very cool angular web app that you want and your native script or you can also work in the script without anger remember all those other options are out there and allows you to work in what you are used to doing so as I said I am John as wiki you can find me online at Kilted code that is my twitter that's where you'll find me on github kiltedcode.github.io but this code will be available and the signs available on my twitter on the github you can find this code that I created up here and check it out and play with it yourself so thank you for your time