microsoft / vscode-react-native

VSCode extension for React Native - supports debugging and editor integration
https://marketplace.visualstudio.com/items?itemName=vsmobile.vscode-react-native
Other
2.63k stars 267 forks source link

How to properly use this extension with TypeScript #402

Closed galvesribeiro closed 7 years ago

galvesribeiro commented 7 years ago

I'm looking to use react-native for an app we are building and since we already use VSCode for ReactJS web apps, we want to use for our react-native apps as well.

This extension works perfectly with a new app created with react-native init myApp which is in JS. Debug works, build works, I just have to press F5 and I'm all set.

However, we are struggling on get it to work with TypeScript. We found this post http://www.reactnative.tools/tutorials/2016/09/20/reactnative-ts/ but here are the problems:

  1. The whole perfect F5 experience is gone with this message: [Error] "Could not debug. Unable to set up communication with VSCode react-native extension. Is this a react-native project, and have you made sure that the react-native npm package is installed at the root?"
  2. It uses old typings. I want to use TS 2.0+
  3. I have to have at least 3 terminals open to have the app running on the simulator! Terrible!
  4. The only debuggable way is to use chrome dev tools. We want to use VSCode debugger from this extension.
  5. The extension become useless since I can't use VSCode to debug the application.
  6. Not to mention it doesn't even build! CompileC /Users/guto/dev/samples/ReactNativeTS/ios/build/Build/Intermediates/RCTWebSocket.build/Debug-iphonesimulator/RCTWebSocket.build/Objects-normal/x86_64/RCTSRWebSocket.o RCTSRWebSocket.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler

So, I ask you guys, how can I have the same awesome F5 experience as I have with this awesome extension but instead of using JS, use TypeScript?

Thank you, really appreciate any help.

Best regards, Gutemberg

vladimir-kotikov commented 7 years ago

Thank you for reporting, @galvesribeiro!

The thing with combination of React Native and Typescript is that it requires some additional configuration work to be done before debugging will work. "ReactNativeTS" repository from aforementioned article is a good starter point, but it's a bit outdated and still has some configuration issues, specifically with mapping breakpoints from typescript sources to compiled code.

I believe that most of your issues is due to that, so I have crafted an updated version of the app that includes some tweaks and has support for typescript debugging out of the box (you could just clone it, do npm i, open in VSCode and debug):

Here is the list of what has been updated:

  1. RN dependency upgraded to 0.41.2 (latest)
  2. Typescript upgraded to 2.1.x
  3. @types/react-native is used instead of typings
  4. Updated tsconfig and babelrc to handle source maps correctly
  5. Added build task and made it running before starting debugging

Could you please try it out and let me know if it works for you.

galvesribeiro commented 7 years ago

@vladimir-kotikov thanks for the prompt reply.

I just cloned, npm install and F5 on VSCode... same problem

[Error] "Could not debug. Unable to set up communication with VSCode react-native extension. Is this a react-native project, and have you made sure that the react-native npm package is installed at the root?" 😞

vladimir-kotikov commented 7 years ago

(Updated) @galvesribeiro, that's odd. Is react-native properly installed? What happens when you run react-native -v in the cloned directory? Also, when you open the project can you see .react directory created inside of .vscode?

galvesribeiro commented 7 years ago

@vladimir-kotikov

GUTO-MAC-MINI:reactnativets guto$ react-native -v
react-native-cli: 2.0.1
react-native: 0.41.2
vladimir-kotikov commented 7 years ago

@galvesribeiro, what about .react directory inside of .vscode? Can you see it?

Could you please also try adding the following lines to workspace settings:

{
  "react-native-tools": {
    "showInternalLogs": true,
    "logLevel": "Trace"
  }
}

and then restart vscode and check "React-Native" output channel?

galvesribeiro commented 7 years ago

@vladimir-kotikov ok, after close and open VSCode multiple times I was able to run and attach the debugger.

However, I noticed that it is kind of unstable. Sometimes we see the red screen on the simulator. Then we click somewhere and it get back. I'll try to simulate the problem and report back.

There is also a warning throwing all the time: (node:86146) DeprecationWarning: 'GLOBAL' is deprecated, use 'global'

Also, I've enabled the Hot/LiveReload in the dev menu but it doesn't work. In fact, if I reload the page the changes aren't caught. Looks like the TS isn't being compiled... Any ideas?

vladimir-kotikov commented 7 years ago

Hmm... I don't know yet why this red box might appear, so I would appreciate if you add more details when you see it next time. As for other your points:

galvesribeiro commented 7 years ago

@vladimir-kotikov I tried to change the "build": "tsc" to "build": "tsc --watch" no lucky... It hangs on the build phase.

Since the watch task never return, it hangs and the process don't move forward:

> react-native-ts@0.0.3 prebuild /Users/guto/dev/samples/reactnativets
> rm -rf build
> react-native-ts@0.0.3 build /Users/guto/dev/samples/reactnativets
> tsc --watch
9:00:27 AM - Compilation complete. Watching for file changes.
galvesribeiro commented 7 years ago

even if I run tsc --watch in an external terminal it still doesn't work...

vladimir-kotikov commented 7 years ago

Ok, here is what worked for me:

  1. Add "watch": "tsc -p . --watch" to scripts section in package.json

  2. Add the following task to .vscode/tasks.json:

    {
        "isBackground": true,
        "taskName": "watch",
        "problemMatcher": "$tsc-watch"
    }
  3. Update launch.json to run watch task instead of build

After changing any source you should see a spinner (right before "React Native Packager: started") that disappears shortly after that which indicates that watch task has compiled your change. Right after that if you open "React-native" output channel, you should see something like

Bundling `index.ios.js`
  Updating 1 module in place, done
vladimir-kotikov commented 7 years ago

I also added these changes to the example so you can just check out the new version at vladimir-kotikov/reactnativets

galvesribeiro commented 7 years ago

It isn't happening here @vladimir-kotikov... I removed the repo, re-cloned, npm i and run from vscode.

  1. The spinner appear as you mentioned
  2. The Android simulator show Hot reloading... in a Toast
  3. The log show:
    Bundling `index.android.js`
    No module changed.
  4. Nothing change on the application

If I ask for reload (r twice) then I have the changes applied...

What is wrong? :(

galvesribeiro commented 7 years ago

Also, the debugger isn't able to evaluate vaiables:

screen shot 2017-02-21 at 15 33 32

Look at the values in the debugger console:

this.state.counter is undefined counter is 1 where counter is nothing more than this.state.counter + 1 so it is defined.

MSLaguana commented 7 years ago

This may be a result of the compilation from your original source to the bundle. Could you please open up .vscode/.react/index.android.bundle and search for your code? I suspect that the line const counter = this.state.counter + 1; is actually being compiled to something like var counter = _this.state.counter + 1;, where this is replaced by _this. If so, then you would be able to access _this.state.counter but not this.state.counter in the debugger. In fact, if you expand the Closure entries in the variables panel, you may even find the _this in there.

Unfortunately there isn't much that we can do about this behavior since there isn't any mapping from your source-code variables to the compiled-code variables.

galvesribeiro commented 7 years ago

@MSLaguana this is what being generated:

_this.onPress=function(){
var counter=_this.state.counter+1;
if(counter<_this.props.max){
return _this.setState({counter:counter});
}

Yes, it is accessible thru _this and appear on Closure. However, I though it is the purpose of souceMaps to handle those maps...

Anyway, understood the case, but I still can't see why the live/hot reload doesn't work...

panarasi commented 7 years ago

@vladimir-kotikov Can you send a PR of your changes to my original repo, so that folks who read the documentation have the latest updates? 

Also, can you explain the commit about removing sm-transformer ? I was using that to ensure that source maps created using typescripts were available during debugging.

Also, I was using the Attach Packager command to debug, FWIW.

vladimir-kotikov commented 7 years ago

@galvesribeiro, i can see that HMR doesn't work when you changing the onPress handler's code, however it does work for changes e.g. inside of render (e.g. JSX template). I believe this is due to template implementation, specifically because onPress is defined as a class' field rather than prototype's property.

@panarasi, yeah, will do. As for sm-transformer removal, our users discovered another approach that makes babel to take ts->js mappings into account and include them into final bundle map (see https://github.com/Microsoft/vscode-react-native/issues/328#issuecomment-275660678 for details). Though this approach is not documented, I think that it's easier to follow and doesn't require running separate packager instance which allows us to nicely integrate it into VSCode debugging experience.

galvesribeiro commented 7 years ago

@vladimir-kotikov You are right... It works if I change something on render.

I believe this is due to template implementation, specifically because onPress is defined as a class' field rather than prototype's property.

I don't know what you mean... The javascript react-native init-based project, just work... The problem here is between TS and the extension :(

vladimir-kotikov commented 7 years ago

@galvesribeiro, check out this: https://github.com/panarasi/ReactNativeTS/pull/1/commits/a6c82de48e97a84c14d16e1d173d6ca4b39d4e70 - it should help you enable HMR in onPress

galvesribeiro commented 7 years ago

Yeah, it worked... I just think it is weird... I have another ReactJS (no react-native) applications using typescript and the methods are declared with lambdas just like that and it work pretty fine with regular debugger on VSCode...

elaffey commented 7 years ago

I am using Haul and ts-loader to try and get debugging with this extension working. The .bundle and .bundle.map files seem to be generated fine and put into the .vscode/.react folder. However, when I attach to packager, breakpoints are labelled as unverified due to a possible source map error and the app will stay on a white screen. I can see and step through the tsx files in the chrome debugger however I cannot do the same in vscode.

vladimir-kotikov commented 7 years ago

@EamonnLaffey, thanks for letting us know. I would appreciate if you could file a separate issue and maybe attach a sample project so we can take a look at your TS configuration. Thanks.

elaffey commented 7 years ago

@vladimir-kotikov Sure I have created the issue here: https://github.com/Microsoft/vscode-react-native/issues/469

And put up a sample project here: https://github.com/EamonnLaffey/tshaulreactnative

Thanks!

lukewlms commented 7 years ago

@vladimir-kotikov TS debugging with React Native is broken till the relevant React Native issue is resolved, correct? It doesn't appear to me there are any current viable workarounds.

vladimir-kotikov commented 7 years ago

@lukecwilliams responded here

vladimir-kotikov commented 7 years ago

Closing this issue as the things around typescript debugging have changed a lot.

Namely, react-native packager doesn't respect inlined sourcemaps in source files anymore, react-native-sm-transformer also doesn't seem to be working with react-native >=0.43. To solve this problem we introduced own sourcemap processing that will merge any existing sourcemaps in js files into bundle, so breakpoints are now working out-of-the box with typescript (see #461)