Search code examples
typescriptwebpackvisual-studio-codecreate-react-appsource-maps

How do I debug a local typescript module used by an app created from create-react-app


I am creating a web app which uses express for backend(webapp/server) and React for frontend(webapp/client) (see below for project structure). I created my react app using create-react-app. I needed a common module that is used by both server and client. So I created a local module named "common" and used "npm link" to make it available to my client and server

The common folder has a class in /src and upon building it I am getting the compiled js,types and source map in /dist folder.

My Project structure

webapp
|
|--common
   |--src
      |--Service.ts
   |--dist
      |--Service.js
      |--Service.d.ts
      |--Service.js.map
|
|--client
   |--src
      |--App.ts
|--server

App.ts

import {Service} from "common"
...
var _service:Service = new Service();
_service.doStuff();
...

I had no problems importing the service, building and running the react app.

Problem

The problem is that when I try to debug the service from the react app, I am getting the compiled Service.js instead of the original Service.ts.

Debugging is working as expected on the server side code.

I think the source of the issue is that create-react-app uses webpack to build the app, and when is resolves module dependencies, it is ignoring the original source maps and added the .js files in its final bundle (main.chunk.js and main.chunk.js.map)

Actual

main.chunk.js.map --> has path to common/dist/Service.js

Expected

main.chunk.js.map --> has path to common/src/Service.ts

Solution

  • I figured out how to debug through my react app.

    The key is not to use the built js files in the react app, but to reference the ts files themselves in the react project. I finally used react-app-rewired to reconfigure my webpack config for the react project. two things had to be done.

    • Added an alias for the common module in tsconfig
    {
      "compilerOptions": {
       ...
        "paths": {
          "@common": ["my-common-module/src/index.ts"]
        }
      }
    }
    

    Updated webpack config with following changes (using config-overrides.js for react-app-rewired)

    • Used awesome-typescript-loader to load the said ts files
    • Removed ModuleScopePlugin to import common module from outside the /src directory
    • added alias so that webpack can know what @common alias is for

    The final config-overrides file should look something like this:

    /* config-overrides.js */
    const rewireAliases = require("react-app-rewire-aliases");
    const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
    
    var path = require("path");
    
    module.exports = function override(config, env) {
      config.module.rules.push({
        test: /\.ts$/,
        use: ["awesome-typescript-loader"],
        enforce: "pre"
      });
    
      config.resolve.plugins = config.resolve.plugins.filter(plugin => !(plugin instanceof ModuleScopePlugin));
    
      config = rewireAliases.aliasesOptions({
        "@common": path.resolve(
          __dirname,
          `node_modules/my-common-module/src/index.ts`
        )
      })(config, env);
    
      return config;
    };