Encountering a 404 error when resolving TypeScript modules within the browser

I am currently working on a small example for a web app utilizing typescript. My main issue lies in importing a module.

I am seeking advice on why this is incorrect and what potential solutions I have to resolve it.

The specific problem I am facing is a 404 error in the index.js file when attempting to import the 'hello' module.

Below is the code snippet:

index.html

<!DOCTYPE html>
<html>
    <head>
        <title>Hello World</title>
    </head>
    <body>
        <p>Check the console log...</p>
    </body>

    <script type="module" src="/dist/index.js"></script>
</html>

index.ts

import { HelloWorld } from "./hello";

var helloWorld = new HelloWorld();

helloWorld.sayHello();

hello.ts

export class HelloWorld {
    constructor() {

    }

    sayHello() {
        console.log("Hello, world!");
    }
}

tsconfig.json

{
    "compilerOptions": {
      "target": "ES2015",
      "module": "ES2015",
      "lib": ["es2015", "dom"],
      "moduleResolution": "node",

      "allowJs": true,
      "checkJs": true,
      "sourceMap": true,
      "outDir": "./dist",
      "strict": true,
      "esModuleInterop": true,
      "experimentalDecorators": true,
      "forceConsistentCasingInFileNames": true
    }
  }

Running the above code through tsc results in the following output:

dist
    hello.js
    hello.js.map
    index.js
    index.js.map

Breakdown of the files generated:

hello.js

export class HelloWorld {
    constructor() {
    }
    sayHello() {
        console.log("Hello, world!");
    }
}
//# sourceMappingURL=hello.js.map

index.js

import { HelloWorld } from "./hello";
var helloWorld = new HelloWorld();
helloWorld.sayHello();
//# sourceMappingURL=index.js.map

By changing 'hello' to 'hello.js' in the index.ts, it resolves the issue. However, this approach doesn't feel right, especially considering there's no 'index.js' during development.

What is the proper way to address this problem to make it work smoothly in an ES2015 compatible browser like Chrome?

Do I need to implement something like requirejs?

Answer №2

One suggestion is to explore utilizing a module loader like SystemJS. The provided example demonstrates how you can achieve this functionality without altering your typescript imports.

The example above illustrates the following modifications:

index.html

Include a script reference for systemjs.

Utilize the systemjs import JavaScript syntax to load the index module without requiring an extension.

Add the script reference for importing a resolver (resolve.js) necessary for loading extensionless JavaScript files.

<!DOCTYPE html>
<html>

<head>
    <title>Hello World</title>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/6.3.1/system.min.js"
        integrity="sha256-15j2fw0zp8UuYXmubFHW7ScK/xr5NhxkxmJcp7T3Lrc=" crossorigin="anonymous"></script>
    <script src="./dist/systemjs-hooks/resolve.js"></script>
    <script>System.import("./dist/index")</script>

</head>

<body>
    <p>Check the console log...</p>
</body>

</html>

resolve.ts

Adapted from the systemjs example.

(function () {
    const endsWithFileExtension = /\/?\.[a-zA-Z]{2,}$/;
    const originalResolve = System.constructor.prototype.resolve;
    System.constructor.prototype.resolve = function () {
      // apply original resolve to ensure importmaps are resolved first
      const url = originalResolve.apply(this, arguments);
      // append .js file extension if url lacks a file extension
      return endsWithFileExtension.test(url) ? url : url + ".js";
    };
  })();

tsconfig.json

Update the module setting to system.

{
    "compilerOptions": {
      "target": "ES2015",
      "module": "system",
      "lib": ["es2015", "dom"],
      "moduleResolution": "node",

      "allowJs": true,
      "checkJs": true,
      "sourceMap": true,
      "outDir": "./dist",
      "strict": true,
      "esModuleInterop": true,
      "experimentalDecorators": true,
      "forceConsistentCasingInFileNames": true
    }
  }

index.js output

Observing the different output achieved by changing the module to system.

System.register(["./hello"], function (exports_1, context_1) {
    "use strict";
    var hello_1, helloWorld;
    var __moduleName = context_1 && context_1.id;
    return {
        setters: [
            function (hello_1_1) {
                hello_1 = hello_1_1;
            }
        ],
        execute: function () {
            helloWorld = new hello_1.HelloWorld();
            helloWorld.sayHello();
        }
    };
});

package.json

In order to utilize system in the resolve.ts, additional devDependencies must be included.

{
  "name": "foo",
  "version": "0.0.1",
  "description": "foo",
  "main": "index.js",
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/systemjs": "^6.1.0",
    "typescript": "^3.8.3"
  }
}

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

Using Angular: A guide to setting individual values for select dropdowns with form controls

I am working on a project that involves organizing food items into categories. Each item has a corresponding table entry, with a field indicating which category it belongs to. The category is represented by a Guid but displayed in a user-friendly format. C ...

Mastering the art of Interpolation and Binding in Ionic 3/Angular 4: A step-by-step

My goal is to retrieve data from my Parse Server where MongoDB is installed. Although I have successfully displayed the data in the console, I am facing issues interpolating them in the HTML template. Here is my search.ts file: import { localData } from ...

Waiting for asynchronous subscriptions with RxJS Subjects in TypeScript is essential for handling data streams efficiently

Imagine having two completely separate sections of code in two unrelated classes that are both listening to the same Observable from a service class. class MyService { private readonly subject = new Subject<any>(); public observe(): Observable&l ...

What is the best way to verify the presence of a value in an SQL column?

I need to check if a value exists in a column. If the value already exists, I do not want to insert it into the table. However, if it does not exist, then I want to add new data. Unfortunately, my attempted solution hasn't been successful. You can fi ...

What is the process for assigning custom constructor parameters to an Angular Service during its creation in an Angular Component?

I have been tasked with converting a Typescript class into an Angular 6 service: export class TestClass { customParam1; customParam2; constructor(customParam1, custom1Param2) { this.customParam1 = customParam1; this.customPara ...

Updating a component's value in Angular 6 when there is a change in the corresponding service

My objective sounds straightforward, but I am struggling to implement it: I want one of my components to automatically update when a variable in a service changes. To illustrate my issue, consider the following example: Imagine having a service that incr ...

What is the recommended default value for a file in useState when working with React and TypeScript?

Can anyone help me with initializing a file using useState in React Typescript? const [images, setImages] = useState<File>(); const [formData, setFormData] = useState({ image: File }); I'm facing an issue where the file is sho ...

No response was forthcoming

I have been trying to send a post request to my login endpoint, but I am not receiving any response. Despite thoroughly checking my code, I am unable to figure out why there is no response being sent back. My backend is built using Express in TypeScript. B ...

Is there a more efficient approach to creating a Typescript XML parser that does not rely on PropTypes?

I'm currently designing the architecture for a web application that will require the consumption of SOAP APIs in hundreds, if not thousands, of instances. These implementations will be developed by 200-300 different developers over a span of several y ...

Generate a div element dynamically upon the click of a button that is also generated dynamically

Putting in the effort to improve my Angular skills. I've found Stack Overflow to be extremely helpful in putting together my first app. The service used by my app is located in collectable.service.ts: export class CollectableService { private col ...

Tips for sorting multiple rows based on the primary column in MUI DataGrid ReactJS

https://i.stack.imgur.com/T9ODr.png Is there a way to utilize Material UI DataGrid to build a table that matches the structure displayed in the linked image? I have successfully created a basic table with DataGrid, but I'm struggling to add multiple ...

What is the best way to showcase a firebase "row" containing two columns within an Ionic 2 application?

Currently in the process of developing an app to keep track of assignments using Ionic 2/Typescript and Firebase as the backend database. The main page displays a list of assignments retrieved from the database. Creating a new assignment requires the user ...

Sharing information between components in Angular through service communication

In my Angular 4 project, there is a functionality where upon clicking on one of the 'groups', its tile should be added to a list of 'favourites' which is represented as an array. To implement this feature, I utilized a BehaviorSubject. ...

Avoiding the stacking of event listeners in React onClick when removing and re-adding the same listener

Is it possible to remove and add the same event listener in an onClick React event? The goal is to have an event listener added to the parent element when the target element is clicked, and then removed on the next click to prevent stacking. One issue tha ...

Troubleshooting Issue with Angular Library: Live Reload Feature Not Functioning

In setting up my Angular workspace, I have 3 libraries and one application (with more to be added in the future). This is how the TypeScript paths are configured: "paths": { "@lib/a/*": [ "projects/libs/a/*", ...

The TypeScript, NextJS project is encountering an issue where it is unable to read the property 'cwd' due to a TypeError

I've noticed this particular error popping up frequently online, but it's not quite matching the issue I'm facing. Every time I execute yarn dev, I encounter the following error: next-dev.js?53bc:89 Error was not caught TypeError: Cannot re ...

List of property names transformed into actual properties

I have a collection of functions stored as key-value pairs that can be utilized by a "processor". const fns = { foo: () => ({ some: "data", for: "foo" }), bar: () => ({ and: "data", for: "bar" }), baz: () => ({ baz: "also", is: "here" }), }; ...

Toggle Button in Angular upon Form Changes

I am currently working on a bug that involves preventing users from saving data if they have not entered any information in the form. The form structure is as follows: private buildAddressPopupForm() { this.form = this.fb.group({ roles: [''], ...

Is there a way to implement retry functionality with a delay in RxJs without resorting to the outdated retryWhen method?

I'd like to implement a retry mechanism for an observable chain with a delay of 2 seconds. While researching, I found some solutions using retryWhen. However, it appears that retryWhen is deprecated and I prefer not to use it. The retry with delay s ...

Is it possible for me to move props object deconstruction into a separate module?

Here is my scenario: I have two React components that share 90% of the same props data, but display different HTML structures. I would like to avoid duplicating variable declarations in both component files. Is there a way to extract the common props des ...