Webpack is unable to resolve non-relative paths created by the TypeScript compiler

I am currently working with a tsconfig.json configuration for a package that is utilized by other packages, which we will refer to as packageA:

{
  "compilerOptions": {
    "baseUrl": ".",
    "checkJs": false,
    "declaration": true,
    "downlevelIteration": true,
    "esModuleInterop": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "module": "commonjs",
    "moduleResolution": "node",
    "target": "es5"
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx"
  ],
  "exclude": [
    "./tests",
    "./dist",
    "src/**/*.test.ts",
    "src/**/*.test.tsx"
  ]
}

packageA contains non-relative paths, such as:

import { T } from 'src/components/Translations';

During transpilation using tsc, this path is converted to:

var Translations_1 = require("src/components/Translations")
.

An issue arises when compiling another package (packageB) using webpack that depends on packageA

In packageA's package.json, I have specified the main file like this:

  "main": "dist/index.js",
  "types": "dist/index.d.ts"

The index.ts of packageA contains exports like this:

export * from 'src/selectors/ui';

which transpiles to:

__exportStar(require('src/selectors/ui'), exports);

When compiling packageB, that has packageA as a dependency.

import { selector } from 'packageA
;

This results in loading

node_modules/packageA/dist/index.js

The error emitted by ts-loader is:

`Cannot find module: 'src/selectors/ui'.

The issue lies in the fact that the transpiled code from packageA looks like this:

__exportStar(require('src/selectors/ui'), exports);

However, the structure of the dist folder is different:

|
ui
|
translations

The src directory does not exist within the dist directory defined by the outDir in tsconfig.json

I attempted adding an alias in webpack as follows:

alias: {
  'webpack/hot/poll': require.resolve('webpack/hot/poll'),
  src: 'dist',
},

While this resolves the issue for packageA, it breaks the resolution for packageB which also has non-relative imports like:

import { App } from 'src/containers'

The problem here is that src is mapped to dist for every import, causing conflicts as seen in the webpack output:

aliased with mapping 'src': 'dist' to 'dist/containers/App'

Consequently, the error received is:

Cannot find module: 'src/containers/App'

Is there a way to map src to dist only for specific modules and not all imports?

All functionalities work seamlessly if packageA utilizes relative paths.

Answer №1

If you ever come across the issue of non-relative paths, one solution is to utilize the paths property as demonstrated below. By doing this, your require path when importing the component from

import { T } from 'src/components/Translations';
will be altered to
import { T } from 'components/Translations';
, which is my preferred method but can be adjusted as needed. For more information, refer to the TypeScript handbook: https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping

    {
        "compilerOptions": {
        "baseUrl": ".",
        "paths": {
               "*": ["src/*", "node_modules/*"]
        },
        "checkJs": false,
        "declaration": true,
        "downlevelIteration": true,
        "esModuleInterop": true,
        "outDir": "./dist",
        "rootDir": "./src",
        "module": "commonjs",
        "moduleResolution": "node",
        "target": "es5"
      },
      "include": [
        "src/**/*.ts",
        "src/**/*.tsx"
      ],
      "exclude": [
        "./tests",
        "./dist",
        "src/**/*.test.ts",
        "src/**/*.test.tsx",
        "moduleResolution": "node"
      ]
    }

Answer №2

For this situation, my recommendation would be to update the packageA which you are currently using as a library with https://www.npmjs.com/package/ttypescript. This will allow you to incorporate a plugin that can convert non-relative paths to relative paths during the build process. One such helpful plugin is available here: https://www.npmjs.com/package/typescript-transform-paths. After implementing this change, your tsconfig file should resemble the following:

"compilerOptions": {
  "baseUrl": ".",
  "outDir": "./dist",
  "paths": {
    "src/*": ["./src/*"]
  },
  "declaration": true,
  "plugins": [
    { "transform": "typescript-transform-paths" },
    { "transform": "typescript-transform-paths", "afterDeclarations": true }
  ]
},

Additionally, remember to modify your package build script from tsc to ttsc:

"scripts": {
  "build": "ttsc"
},

Answer №3

If you want to resolve absolute paths, one way is to include src in the resolved modules section of your webpack.config.js.

To get a broad understanding of how webpack handles module resolution, check out this detailed explanation here.

For more specific configuration details, refer to the information provided here.

const path = require('path');

module.exports = {
  //...
  resolve: {
    modules: [path.resolve(__dirname, 'src'), 'node_modules'],
  },
};
reso

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue: Invariant violation: Utilizing <Link> is restricted to within a <Router> (storybookjs)

While it functions properly with the normal react-scripts start, an error is thrown when attempting to view individual components through storybook as mentioned in the title. Here is the code: index.tsx import React from 'react'; import ReactD ...

Is it possible to subscribe to the @select() observable in my Angular Redux component and have the pattern automatically unsubscribe onDestroy?

In my Angular application with Redux, I am utilizing the @select() method to retrieve an object named 'sectionAll'. This object serves as the data source for a table that I am displaying, requiring me to pass it to the dataSource in the controlle ...

Steps to resolve the issue of MatCardComponent not being detected despite being imported within the module

I am encountering an issue with my Angular nrwl nx project that includes Bootstrap 5 and Angular Material. Within a library, I have a dashboard component where I import the MatCardModule. However, when trying to use it inside the DashboardComponent, I rece ...

Issue with Bot framework (v4) where prompting choice in carousel using HeroCards does not progress to the next step

Implementing HeroCards along with a prompt choice in a carousel is my current challenge. The user should be able to select options displayed as HeroCards, and upon clicking the button on a card, it should move to the next waterfall function. In the bot fr ...

Using TypeScript to style React components with the latest version of Material UI, version

Styled typography component accepts all the default typography props. When I include <ExtraProps> between styled() and the style, it also allows for extra props. const StyledTypography = styled(Typography)<ExtraProps>({}) My query is: when I r ...

Can npm scripts be evaluated within a JavaScript file in vue.js?

I have a configuration file within my vue.js project that utilizes webpack and npm. The file path is /plugins/http/GLOBAL_CONST.js const GLOBAL_CONST = {} GLOBAL_CONST.BASE_URL = "http://www.example.com/" // "http://localhost:3000/" GLOBAL_CONST.BASE ...

Can class properties be automatically generated based on its generic type?

Is it possible in TypeScript to automatically create a class with properties based on its generic type? For example: class CustomClass<T> { // Code to extract properties from T should go here } interface Characteristics { quality: string; pri ...

Error: Module not found '!raw-loader!@types/lodash/common/array.d.ts' or its type declarations are missing

I encountered a typescript error while building my NEXT JS application. The error message was: Type error: Cannot find module '!raw-loader!@types/lodash/common/array.d.ts' Below is the content of my tsConfig.json file: { "compilerOptions& ...

I'm trying to figure out how to access the array field of an object in TypeScript. It seems like the type 'unknown' is required to have a '[Symbol.iterator]()' method that returns an iterator

I'm currently tackling an issue with my helper function that updates a form field based on the fieldname. For example, if it's the name field, then form.name will be updated. If it's user[0].name, then the name at index 0 of form.users will ...

Competing in a fast-paced race with JavaScript promises to guarantee the completion of all

How can I retrieve the result of a Javascript Promise that resolves the fastest, while still allowing the other promises to continue running even after one has been resolved? See example below. // The 3 promises in question const fetchFromGoogle: Promise&l ...

develop-react-application web server to send CORS headers on response

In a unique scenario, I'm facing the challenge of needing to handle CORS headers from a server that is a create-react-app server hosting a react app. I have two react applications, app1 (port 3002) and app2 (port 3001), along with one backend (port 3 ...

Securing redirection in WebPart using Azure AD: Best practices

I've successfully created a Sharepoint Webpart with a straightforward goal: authenticate users on an external website embedded within Sharepoint. This external site utilizes Azure AD for user logins. However, my current implementation has a significa ...

Tips for adding a new element to an array based on its unique identifier during the mapping process

Currently, I am dealing with a UI table populated by a GET request. My goal is to enhance each row by adding a new value fetched from another GET request. However, I'm facing an issue where I can't execute a request within a map function... expo ...

Webpack 5 lacks compatibility with polyfills for Node.js

I'm facing a challenge with my npm package that is compatible with both Angular and Node.js environments. Recently, I began using the package in Angular v12 projects, but encountered errors like: BREAKING CHANGE: webpack < 5 used to include polyf ...

Applying Material UI class in React: Troubleshooting an error with your hook call

Recently, I have started using React and encountered an issue with a hook call. I understand the root cause of the problem but unsure how to resolve it without starting from scratch. Here is the snippet of the code: import { Fragment, PureComponent } from ...

Looping through an array using NgFor within an object

I've been working on pulling data from an API and displaying it on a webpage. Here is the JSON structure: {page: 1, results: Array(20), total_pages: 832, total_results: 16629} page: 1 results: Array(20) 0: adult: false backdrop_path: "/xDMIl84 ...

Document: include checksum in HTML

I have a set of three files. The file named loader.js is responsible for creating an iframe that loads another file called content.html, which in turn loads content.js. I have made loader.js publicly available so that other users can include it on their ow ...

Testing React components with React Testing Library and Effector (state manager) made easy

I am currently utilizing effector along with React Testing Library (RTL). While going through the RTL documentation, I came across an interesting article regarding the usage of customerRender, where we provide AllTheProviders as a wrapper for the render fu ...

Despite strongly typed manipulations, the type of a Typescript variable remains unchanged

Enhanced TS Playground Example Script type Base = { name: string } type ExtA = { address: string } type ExtB = { streetName: string; } function handler<T extends Base>(input: T): T {return input} /** how can I create a composite object? */ ...

Are there alternative methods for incorporating react-multi-carousel in a project utilizing NEXT.js and React/Typescript?

I installed the react-multi-carousel module and configured a simple carousel, but it's not functioning properly. The issue seems to be related to the absence of <li> tags. Here is the HTML that was rendered: <ul class="react-multi-caro ...