Typescript including different files depending on compilation command - reactjs

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 :
1. Create a function to check the platform running
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';
}
}
2. Create routing/index.ts
import getPlatfrom from '../getPlatform';
const platform = getPlatfrom();
const routing = platform === 'web' ? require('./routing.web') : require('./routing.native');
export const {Router, Switch, Route, Link} = routing;
3. Use the 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 ...

Related

Vite error with optimized info should be defined when use GLTFLoader in React(ThreeJS)

I use vite to build one react environment. When I import GLTFLoader from the module, and vite commandline mentioned that:
Vite Error, /node_modules/.vite/deps/three_examples_jsm_loaders_GLTFLoader.js?v=9d4ee121 optimized info should be defined
Here's my code:
import * as Three from "three"
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
[...]
const gltfLoader = new GLTFLoader()
gltfLoader.setPath('public/')
gltfLoader.load('000.hdr', gltf => {
gltf.scene.scale.set(0.2,0.2,0.2)
scenes.add(gltf.scene)
})
Here's the error message:
For others in the future, YMMV: deleting node_modules and pnpm-lock.yaml solved the issue.
Already solve this question.
When the commandline mentioned vite error, just need to close dev-server, then reload. Vite would clean the cache tmp files in .vite.
this is usually caused by lockfiles or node_modules/.cache/vite (or maybe in your case node_modules/.vite)

ERROR TS6054: File '~lib/#tensorflow/tfjs-node.ts' not found

I'm trying to use AssemblyScript to build a WebAssembly inference engine for a TensorFlow.js model that I have.
I started with essentially the quickstart AssemblyScript app (which works great) and then simply added #tensorflow/tfjs to my dependencies:
$ npm install --save #tensorflow/tfjs
and added an import to assembly/index.ts:
import * as tf from "#tensorflow/tfjs";
Full code here on Github
This results in an error when I build it:
$ npm run asbuild
> test-assemblyscript#1.0.0 asbuild
> npm run asbuild:untouched && npm run asbuild:optimized
> test-assemblyscript#1.0.0 asbuild:untouched
> asc assembly/index.ts --target debug
ERROR TS6054: File '~lib/#tensorflow/tfjs.ts' not found.
import * as tf from "#tensorflow/tfjs";
~~~~~~~~~~~~~~~~~~
in assembly/index.ts(1,21)
FAILURE 1 parse error(s)
Am I misunderstanding the import syntax? I am puzzled why it would be looking in ~lib for this versus node_modules.
If you are sure the module you are trying to import is assemblyscript files, you can import with something like this ./node_modules/#tenderflow/tfjs.
I am not sure if #tensorflow has assembly files built, but I did that on assemblyscript-json for assemblyscript#0.19.8 (0.25.2 doesn't have that problem).
For example
assemblyscript-json has exported assemblyscript files from its package, so I can do this (ref)
import { JSON } from './node_modules/assemblyscript-json/assembly';
export function formatJsonString(jsonString: string): string {
const jsonObj: JSON.Obj = <JSON.Obj>JSON.parse(jsonString);
return jsonObj.stringify();
}

Problems using Netlify to host Gatsby built site

Im getting this error
./node_modules/gatsby/cache-dir/gatsby-browser-entry.js
Module parse failed: Unexpected token (26:4)
You may need an appropriate loader to handle this file type.
|
| return (
| <React.Fragment>
| {finalData && render(finalData)}
| {!finalData && <div>Loading (StaticQuery)</div>}
gatsby-browswer-entry.js only has this inside of it:
import './src/styles/tailwind.css'
None of my .js files are failing to import the 'Link' component
Sometimes, depending on Gatsby's version and its dependencies, you need to import the component from gatsby-link rather than gatsby, so:
// import { Link } from "gatsby" // error
import Link from "gatsby-link" // not error
I had a similar issue, and was only exposed when running tests in cypress. I had used gatsby's navigate function in a non-jsx javascript helper file. I think the error is indicative of a bundling / webpack issue and you have to look at the stack trace to see the actual culprit file.

Importing self-created libraries in reactjs

I'm using React and ES6 using babel and webpack. I am very new to this ecosystem.
I am trying to import some common utility functions into my jsx file but react is unable to find the file
homepage.jsx
var pathToRoot = './../..';
import path from 'path';
import React from 'react';
import ReactDOM from 'react-dom';
var nextWrappedIndex = require(path.join(pathToRoot,'/lib/utils.js')).nextWrappedIndex;
//some react/JSX code
utils.js
var nextWrappedIndex = function(dataArray) {
//some plain js code
return newIndex;
}
exports.nextWrappedIndex = nextWrappedIndex;
Directory structure is as follows:
src
|--app.js
|--components
| |--homepage
| |--homepage.jsx
|
|--lib
| |--utils.js
I am on a windows 10 machine and was facing issues during compilation providing the path by any other means. Using path.join solved compilation issue but the browser while rendering throws this error
Uncaught Error: Cannot find module '../../lib/utils.js'.
How do I accomplish this?
Also, is this the best way to do it(if altogether it is way it is supposed to be done in such ecosystem)?
One of the best and easiest way I have found in such a setup is to use Webpack aliases.
Webpack aliases will simply associate an absolute path to a name that you can use to import the aliased module from anywhere. No need to count "../" anymore.
How to create an alias?
Let's imagine that your Webpack config is in the parent folder of your src folder.
You would add the following resolve section in your config.
const SRC_FOLDER = path.join(__dirname, 'src')
resolve: {
alias: {
'my-utils': path.join(SRC_FOLDER, 'lib', 'utils')
}
}
Now, anywhere in your app, in any of your modules or React component you can do the following:
import utils from 'my-utils'
class MyComponent extends React.component {
render () {
utils.doSomething()
}
}
Small note about this method. If you run unit tests with a tool like enzyme and you don't run the component tested through Webpack, you will need to use the babel-plugin-webpack-alias.
More info on Webpack website: Webpack aliases
I solved this by replacing
var nextWrappedIndex = require(path.join(pathToRoot,'/lib/utils.js')).nextWrappedIndex;
with
import nextWrappedIndex from './../../lib/utils.js';
I tried to reproduce your code and Webpack printed me the following error:
WARNING in ./app/components/homepage/homepage.jsx
Critical dependencies:
50:0-45 the request of a dependency is an expression
# ./app/components/homepage/homepage.jsx 50:0-45
It means that Webpack couldn't recognize your require() expression because it works only with static paths. So, it discourages the way you are doing.
If you would like to avoid long relative paths in your import, I'd recommend you to set up Webpack.
First, you can set up aliases per Amida's answer.
Also, you can set up an extra module root via resolve.modules to make webpack look into your src folder, when you are importing something absolute, like lib/utils.js

React-router issues using static-render-webpack-plugin

I just started working with React last week, and I'm having trouble following a tutorial for the static-render-webpack-plugin.
I've put the code online at GitHub if you want to take a closer look.
After following the tutorial and making a couple of changes (I added babel-core, I changed the js loader to babel-loader and the entry point url needed a small correction), when I try to run webpack -p to generate the static files I get the following error:
ERROR in ./src/entry.js
Module build failed: SyntaxError: .../src/entry.js: Unexpected token (10:2)
8 |
9 | const routes = (
> 10 | <Route path="/" handler={RootPage}>
| ^
I think it might have something to do with the changes made with the latest version of react-router. I'm using the latest version, but the syntax for the tutorial looks like it might have been written prior to v.1.0. For example, I think the part of the tutorial that says to add this to the src/entry.js file:
if (typeof document != 'undefined') {
Router.run(routes, path, (Root) => {
React.render(<Root/>, document);
});
}
probably needs to be rewritten to something like this (but I'm not sure if this is quite right):
if (typeof document != 'undefined') {
ReactDOM.render(routes, document);
}
There's obviously more going on though since I get the same error message when I try that rewritten snippet then run webpack-dev-server -- which is the only time it should hit that code. (Yes, I added import ReactDOM from 'react-dom'; to the top of the page and "react-dom": "^0.14.7", to the package.json.)
I am sure this part (also on src/entry.js) needs to be rewritten to match the latest react-router too but I'm not sure how:
export default function(path, props, callback) {
Router.run(routes, path, (Root) => {
const html = React.renderToString(<Root/>);
callback('<!doctype html>' + html);
});
}
Thanks in advance for any help or hints you can give.
Your code is breaking because Webpack doesn't know how to transpile the JSX to ES5. You've specified babel-loader as your loader for JS files in your webpack config, but unfortunately Babel 6 does not do anything out of the box, you need to include "plugins" that contain the rules for compiling different syntaxes down to ES5. In this case, you'll want the es2015 preset to support all ES6 syntax, and the react preset to support JSX. You're also missing the extract-text-webpack-plugin you are trying to import into your webpack config. Snag these through NPM:
npm i -D babel-preset-2015 babel-preset-react extract-text-webpack-plugin
Then, add the presets to your webpack.config.js file in the loaders section for js/jsx files:
{
test: /\.(js|jsx)?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
I forked your repo and made these changes and was able to get a bit further through the compilation process. It seems like there are module dependencies specific to your project you'll still need to resolve.

Resources