4

I'm new to TypeScript and I'm just trying to include a module that imports from a node module. I'm not using webpack or any other build tools as I'm trying to keep this as basic as possible to understand.

This is my structure:

/node_modules    -- contains node modules I want to import in main.ts
/scripts/ts/main.ts
/scripts/main.js -- the transpiled main.ts file
/index.html      -- includes the module script tag for scripts/main.js
/package.json
/tsconfig.json

This is my tsconfig.json:

{
    "compilerOptions": {
        "target": "ES6",
        "module": "ES2015",
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "outDir": "scripts",
        "moduleResolution": "Node",
        "experimentalDecorators": true
    },
    "$schema": "https://json.schemastore.org/tsconfig",
    "exclude": [],
    "include": [
        "scripts/ts/**/*"
    ]
}

My main.ts file has these imports:

import { css, html, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';

The main.ts file gets transpiled and main.js is loaded successfully. But I get this error:

Uncaught TypeError: Failed to resolve module specifier "lit". Relative references must start with either "/", "./", or "../".

The import statements are transpiled "as is". They look exactly the same in the transpiled file so I imagine the issue is that the module path is wrong: The browser does not know that "lit" is in "node_modules/lit" and when I manually change the path in the transpiled file to ../node_modules/lit/index.js then I get another error which is

Uncaught TypeError: Failed to resolve module specifier "@lit/reactive-element". Relative references must start with either "/", "./", or "../".

Which I imagine is a module imported down the heirarchy by other lit modules. Basically my import paths are not transpiled properly and I don't know what to do. Any help would be great!

frezq
  • 653
  • 8
  • 18
  • 1
    What does your `html` file look like? Does it just import from `scripts/main.js`? If so, I believe the problem is that Typescript doesn't deal with bundling your dependencies into a single file which is why this doesn't work. This is usually where webpack comes in. A similar question was already asked about avoiding webpack: https://stackoverflow.com/q/47818983/7133623 – cdimitroulas Jun 02 '21 at 17:37
  • Yeah it just does a ` – frezq Jun 02 '21 at 17:47
  • 1
    You're right - the problem is that the browser doesn't know about resolving imports to the node_modules folder. Probably you can write the node_modules path manually like in this answer: https://stackoverflow.com/a/52558858/7133623 – cdimitroulas Jun 02 '21 at 18:18
  • When I did that, I got `Uncaught TypeError: Failed to resolve module specifier "@lit/reactive-element". Relative references must start with either "/", "./", or "../".` I don't use `@lit/reactive-element` directly so this must have been an import lower down in the dependency graph. In any case you're right, I remember now that ES6 imports need to have an absolute or relative path - "plain node imports" simply don't work and these need to be translated somehow not only for my module but for every other module down the dependency graph. I really appreciate your time discussing this. – frezq Jun 03 '21 at 04:33
  • In the end I used webpack. Using a TypeScript compiler only simply wasn't enough and I'm learning now the need for the different components of this whole build process. The webpack bundle also looked like it included not only my module (even though that was the only thing I fed it) but all it's imports and I'm guessing all the dependencies of those imports as well. Took me only 10 hours to understand all this. – frezq Jun 03 '21 at 04:40
  • 1
    This is why I prefer working on the back-end :P All the front-end tooling has gotten quite complex! Glad you figured it out though. Webpack does indeed bundle everything you need including third party dependencies. It works through all the imports and picks the code which is used to add to the final bundle – cdimitroulas Jun 03 '21 at 09:30
  • Having the same problem but I am already using rollup – leonheess Oct 06 '21 at 00:11

1 Answers1

1

Thanks to @cdimitroulas for making me think about this.

ES6 imports need to have an absolute or relative path - "plain node imports" simply don't work and these paths need to be resolved somehow not only for the main module's imports but for every other module's imports down the dependency graph.

The Typescript compiler does not handle this and so the current setup was missing a tool that would resolve these paths (like web-dev-server) or bundle the modules and all their dependencies in one file (like webpack) thereby eliminating the need to resolve the paths.

frezq
  • 653
  • 8
  • 18