The source map issue has been discussed in the React Native repo a fair bit. The RN packager seems to consume source maps with a custom Transformer see here. My question is, is it possible to set-up the VS Code Extension so that TypeScript source files can be used through the debugger (e.g. set breakpoints etc.)?
If this is possible, could you describe what source map settings need to be used (e.g. inline source maps etc..)?
I'm using 0.1.4 of the React Native Extension with VS code 1.1.1.
@joewood we don't currently have a solution for this, we'll need to spend some time looking at it. Currently the team is busy with some non-related work, we'll add this to our backlog and get back to it when we can.
Thanks for the response. It may be necessary to use a custom transformer for TypeScript. I'll keep investigating and post anything I find here.
Hi @hamiltonia
I've had some limited success in getting this to work. The approach I'm looking at is to replace the react-native transformer with a version that supplies the babel option inputSourceMap. I patched the transform.js file from RN's packager in two places, one to set the option for Babel and the other to read in the map file:
/**
* Copyright (c) 2015-present, Facebook, Inc.
*/
'use strict';
const babel = require('babel-core');
const externalHelpersPlugin = require('babel-plugin-external-helpers');
const fs = require('fs');
const makeHMRConfig = require('babel-preset-react-native/configs/hmr');
const resolvePlugins = require('babel-preset-react-native/lib/resolvePlugins');
const inlineRequiresPlugin = require('fbjs-scripts/babel-6/inline-requires');
const json5 = require('json5');
const path = require('path');
const getBabelRC = (function () {
let babelRC = null;
return function _getBabelRC(projectRoots) {
if (babelRC !== null) {
return babelRC;
}
babelRC = { plugins: [] }; // empty babelrc
let projectBabelRCPath;
if (projectRoots && projectRoots.length > 0) {
projectBabelRCPath = path.resolve(projectRoots[0], '.babelrc');
}
if (!projectBabelRCPath || !fs.existsSync(projectBabelRCPath)) {
babelRC = json5.parse(
fs.readFileSync(
path.resolve(__dirname, 'node_modules/react-native/packager/react-packager', 'rn-babelrc.json'))
);
// Require the babel-preset's listed in the default babel config
babelRC.presets = babelRC.presets.map((preset) => require('babel-preset-' + preset));
babelRC.plugins = resolvePlugins(babelRC.plugins);
}
return babelRC;
};
})();
/**
* Given a filename and options, build a Babel
* config object with the appropriate plugins.
*/
function buildBabelConfig(filename, options) {
const babelRC = getBabelRC(options.projectRoots);
const extraConfig = {
filename,
sourceFileName: filename,
// ADDED PATCH FOR INPUT SOURCE MAPS
inputSourceMap: options.inputSourceMap
};
let config = Object.assign({}, babelRC, extraConfig);
// Add extra plugins
const extraPlugins = [externalHelpersPlugin];
var inlineRequires = options.inlineRequires;
var blacklist = inlineRequires && inlineRequires.blacklist;
if (inlineRequires && !(blacklist && filename in blacklist)) {
extraPlugins.push(inlineRequiresPlugin);
}
config.plugins = extraPlugins.concat(config.plugins);
if (options.hot) {
const hmrConfig = makeHMRConfig(options, filename);
config = Object.assign({}, config, hmrConfig);
}
return Object.assign({}, babelRC, config);
}
function transform(src, filename, options) {
options = options || {};
const babelConfig = buildBabelConfig(filename, options);
const result = babel.transform(src, babelConfig);
return {
ast: result.ast,
code: result.code,
map: result.map,
filename: filename,
};
}
module.exports = function (data, callback) {
// ADDED PATCH FOR INPUT SOURCE MAPS
if (fs.existsSync(data.filename + ".map")) {
console.log("Adding Map for " + data.filename);
data.options = data.options || {};
data.options.inputSourceMap = JSON.parse(fs.readFileSync(data.filename + ".map").toString());
data.options.sourceMaps = true;
}
// END PATCH
let result;
try {
result = transform(data.sourceCode, data.filename, data.options);
} catch (e) {
callback(e);
return;
}
callback(null, result);
};
// export for use in jest
module.exports.transform = transform;
All this is doing is sending the mapfile data to babel if it exists as a .js.map file (bit of an assumption, but this is just for testing). I can use this transform with VSCode if I change the RN Native Extension's Packager.start function. I simply add the arguments for the command line:
.then(function () {
var args = ["--port", Packager.PORT,"--transformer","c:\\code\\app\\transform.js"];
var childEnvForDebugging = Object.assign({}, process.env, { REACT_DEBUGGER: "echo A debugger is not needed: " });
Note, there's a bug in RN where the transform module needs to specified with a full path.
This all seems to work OK, in that when I browse to look at the .map file in the browser the TypeScript source files are referenced correctly. However, the problem is that VSCode doesn't seem to be picking them up and loading the source files. Injecting a "debugger" statement just opens up the main bundle file. I've tried using sourceRoot and relative paths, but without success. So, it seems to be failing at the last step.
Any suggestions would be appreciated. Thanks.
FYI - I tried debugging in DevTools, but I see the error "Failed to Parse SourceMap". However, this error could be related to the Chrome 51 bug logged here: https://bugs.chromium.org/p/chromium/issues/detail?id=611328
So recently we cannot debug in typescript?
@joewood
Here is my post to explain how to deal with this debugger problem with typescript:
make_VSCode_debug_RN_TS.md
Also refer to these two issues
https://github.com/facebook/react-native/issues/393
https://github.com/facebook/react-native/issues/7083
I have make some progress on debugging typescript in vscode

Success! I'll write a post to explain how to debug typescript file with react native in vscode.

@joewood
Here is my post to explain how to debug ReactNative project in VSCode with typescript:
make_VSCode_debug_RN_TS.md
Thanks a lot for looking into that and providing a detailed explanation @frogcjn!
We've been a bit busy on other projects so we haven't had a chance to look over your PR closely yet, but we'll try to get to that soon. We definitely want to get this working.
Thanks to @frogcjn for his PR implementing this: https://github.com/Microsoft/vscode-react-native/pull/259
Support will be in the next release.
when will we see the next release?
Soonâ„¢
While you wait for the official release, you can check out this repo and build it yourself.
Thanks that's good enough for me. I'm way to deep down the wrong rabbit
hole already ;-)
On Aug 9, 2016 8:07 PM, "Jimmy Thomson" [email protected] wrote:
Soonâ„¢
While you wait for the official release, you can check out this repo and
build it yourself.—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/vscode-react-native/issues/240#issuecomment-238639358,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADgNBjffQiAqErR92LgPodAOFr9zpl8ks5qeMHVgaJpZM4Iqn0T
.
Thanks @joewood - this change is in the repo and will go out in the next release.
I'm still struggling to get breakpoints to light up in VS Code with TypeScript on a react-native project. I followed the instructions and set sourceMap to true in .babelrc.
Am I missing something?
@Flavien, what instructions are you referring to? Could you please describe exact steps you have tried?
Most helpful comment
when will we see the next release?