I used creat-react-app
to initialize some code which I want to share between native and web. In my package.json
I have two separate commands for starting for each platform using react-scripts-ts
and react-native-scripts-ts
:
package.json
...,
"scripts": {
"tsc": "tsc",
"clean": "rimraf artifacts",
"build": "npm run clean && npm run tsc --",
"start-web": "npm run build && react-scripts-ts start",
"start-native": "npm run build && react-native-scripts start",
},
...
(a detailed description on how to do this can be found here https://medium.com/@yannickdot/write-once-run-anywhere-with-create-react-native-app-and-react-native-web-ad40db63eed0)
This great and I can use react-native
components on both platforms. The problem I have is when I try to use external packages such as react-routing
.
I include both react-router-native
and react-router-dom
in my package.json
. I am trying to achieve what is described in this article (https://medium.com/@yannickdot/hi-jared-2650fbb2eda1) but using typescript not JS, giving me:
routing.native.tsx
export {
NativeRouter as Router, // Rename
Switch,
Route,
Link
} from 'react-router-native'
routing.web.tsx
export {
BrowserRouter as Router,
Switch,
Route,
Link
} from 'react-router-dom'
However, contrary as described in the article, when using typescript, it is not automatically recognized which file should be included. I get the simple error:
src/App.tsx:10:26 - error TS2307: Cannot find module './routing'.
10 import Router from "./routing";
Which makes sense because when I look at the output of the compiler, no module routing
exists:
artifacts
| App.js
| routing
| routing.native.js
| routing.web.js
How can I tell the typescript compiler to include all *.native.tsx
files when running the start-native
command and all *.web.tsx
files when running the start-web
commmand?
Ideally, this should be possible at compile-time, passing additional parameters into the typescript compiler, which override the tsconfig.json
. Example:
tsc --exclude="./**/*.native.tsx"
I know this can be done with a hacked solution, e.g. by writing a script to copy the entire source, deleting all unwanted files, keeping the correct ones, and compiling that copied source folder, but I want to know if there is a more neat way to do this.
Thanks in advance!
A possible solution without using external tools :
see this question on Stackoverflow
export default function getPlatform(): string {
if (typeof document != 'undefined') {
// I'm on the web!
return 'web';
}
else if (typeof navigator != 'undefined' && navigator.product == 'ReactNative') {
// I'm in react-native
return 'native';
}
else {
// I'm in node js
return 'node';
}
}
import getPlatfrom from '../getPlatform';
const platform = getPlatfrom();
const routing = platform === 'web' ? require('./routing.web') : require('./routing.native');
export const {Router, Switch, Route, Link} = routing;
import { Route } from './routing/index';
You may add an interface IRouting
and some type casting in routing/index
, so that you don't lose type safety and autocompletion ...