Re-use codebase

by,

Shakthishree

Re-use code base

• With in an application

• Between applications which use same syntax

• Between applications that are implemented for different  platforms

Why ?

Mobile

 Web

Product

React Native

React web

Electron

Desktop

3X

Why ?

Mobile

 Web

Product

Desktop

Single code base

Requirement

Approach 1  - Re-use code base in desktop

import { app, BrowserWindow } from "electron";
import * as path from "path";
import { __DEV__ } from "./libs/electron-is-dev";

let mainWindow: Electron.BrowserWindow;

function createWindow() {
  mainWindow = new BrowserWindow({
    height: 600,
    titleBarStyle: "hiddenInset",
    width: 800,
    webPreferences: {
      devTools: __DEV__,
    },
  });

  
  const url = __DEV__ ? "http://localhost:3000" : `file://${path.join(__dirname, "../www/index.html")}`;
  mainWindow.loadURL(url);

  mainWindow.webContents.openDevTools();

  mainWindow.on("closed", () => {
    mainWindow = null;
  });
}

app.on("ready", createWindow);

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
  }
});

app.on("activate", () => {
  if (mainWindow === null) {
    createWindow();
  }
});

2X

Approach 1 - Libraries

• react-native-web

• react-native-primitives

• react-native-windows

• react-native-macos

Is this approach good enough?

Approach 2: Re-use React Native code in web

{
  "name": "@app/web",
  "version": "",
  "private": true,
  "homepage": ".",
  "dependencies": {
    "@app/mobile": "^0.0.1",
    "@types/jest": "24.0.16",
    "@types/node": "12.6.8",
    "@types/react": "16.8.24",
    "@types/react-dom": "16.8.5",
    "@types/react-native": "^0.60.2",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-native-web": "^0.11.5",
    "react-scripts": "3.0.1",
    "typescript": "3.5.3"
  },
  "devDependencies": {
    "babel-plugin-react-native-web": "^0.11.5",
    "react-app-rewired": "^2.1.3"
  },
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import registerServiceWorker from './registerServiceWorker';
import './index.css';

import App from '@app/mobile';

ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

Is this a reliable approach ?

Application Content

View

Application

Logic

Dependencies

application specific UI Components, UX

Store, Services, other application specific logic

Architecture

 

Software development principle

• How to Achieve DRY

• DRY Benefits

How to Achieve KIS

DRY and KIS

KIS Benefits

Architecture

{
  "name": "@app/mobile",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "react-native start"
  },
  "dependencies": {
    "@app/shared": "^0.0.1",
    "react-navigation": "^3.11.1",
    "@react-navigation/native": "^3.5.0",
    "react": "16.8.6",
    "react-native": "0.60.5",
    "react-native-gesture-handler": "^1.3.0",
    "react-native-reanimated": "^1.2.0"
  },
  "devDependencies": {
    "@babel/core": "^7.5.5",
    "@babel/runtime": "^7.5.5",
    "@types/react": "^16.8.24",
    "@types/react-native": "^0.60.2",
    "metro-react-native-babel-preset": "^0.56.0",
    "typescript": "^3.5.3"
  },
  "workspaces": {
    "nohoist": [
      "react-native",
      "react-native/**",
      "react-native-gesture-handler",
      "react-native-gesture-handler/**",
      "react-native-reanimated",
      "react-native-reanimated/**",
      "@react-navigation/native",
      "@react-navigation/native/**"
    ]
  }
}
import React from 'react';
import {
  StyleSheet,
  Text,
  View,
  TextInput,
  TouchableOpacity,
  Dimensions
} from 'react-native';
import {emailValidator, passwordValidator} from '@app/shared';


class Login extends React.Component{
 state = {
  email: undefined,
  password: undefined,
  formValid: false
 }
 
 setFormValidity = (formValid) => {
  this.setState({formValid})
 }

 onEmailChange = (email) => {
	this.setState({email}, () => emailValidator(() => this.setFormValidity(true), () =>  this.setFormValidit(false)))
 }

 onPasswordChange = (password) => {
 	this.setState({password}, () => passwordValidator(() => this.setFormValidity(true), () =>  this.setFormValidit(false)))
 }


 render(){
   return (
    <View style={styles.container}>
      <View style={styles.loginFormContainer}>
        <Text style={styles.title}>Login</Text>
        <TextInput placeholder="usernae" style={styles.textInput} onChangeText={this.onEmailChange}/>
        <TextInput
          placeholder="password"
          secureTextEntry
          style={styles.textInput}
          onChangeText={this.onPasswordChange}
        />
        <TouchableOpacity style={styles.loginButton}>
          <Text style={styles.login}>Login</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
 }
}
  

export default Login;

Why ?

When ?

Why ?

Disavantages ?

• Version maintainance

• Dependencies

• If you already have a stable app, restructuring app is an overload.

• Special requirements

Made with Slides.com