Issue
Context
I have these two TypeScript files:
// something.ts
let x = 3;
export default x;
// index.ts
import x from "./something";
console.log(x);
under these tsconfig.json
settings:
{
...
"target": "es2016",
...
// "module": "commonjs" /* <- commented out */
}
when I compile this into JavaScript, I get these two files (which is what I expect):
// something.js
let x = 3;
export default x;
// index.js
import x from "./something";
console.log(x);
Now, I've linked the index.js
file from my HTML file like so:
<script src="./dist/index.js"></script>
Problem
When I try opening this up using Live Server, I get this error in the console:
Uncaught SyntaxError: Cannot use import statement outside a module
So, how do I fix this?
What I've tried
- Adding back the
"module": "commonjs"
line in mytsconfig.json
file
This results in a different error message appearing in the console:
Uncaught ReferenceError: exports is not defined
As per this SO post, a suggested solution is to comment out the "module": "commonjs"
line, which essentially throws my situation into an infinite loop...
- Adding
"type": "module"
to the<script>
tag andpackage.json
From this SO post, a suggested solution is to add "type": "module"
to the <script>
tag:
<script type="module" src="./dist/index.js"></script>
but now I get this error message:
GET http://127.0.0.1:5501/dist/something net::ERR_ABORTED 404 (Not Found)
.
In the same post, another suggestion was to add "type": "module" to the package.json
file:
{
"type": "module",
"dependencies": {
"typescript": "^4.6.2"
}
}
and from what I've observed, this doesn't really do anything.
Solution
You are really really really close. In ESM (in browser) imports, you must provide the file name extension, so you need to do:
import something from "./something.js";
instead of simply
import something from "./something";
Your other code didn't work because the browser runs on, well... the browser. That means we're not in a NodeJS environment so modules don't work so magically. So, the caveats of ESM imports:
- You can't import npm packages
- All imports must be an absolute URL or start with
./
or/
- The browser doesn't automatically add a file extension; you'll have to specify yourself (e.g.
import something from "./something.js";
instead ofimport something from "./something";
) - You must specify
type="module"
in your HTML script tag to tell the browser that it's a module you're looking at - Please don't use this in production, because...
- If you have nested imports, the browser can't load them concurrently; they have to be loaded one by one
- It's not as fast (duh)
- The feature is quite new so isn't really enhanced that much
The real solution:
Use a bundler instead!!
Why?
A bundler (the most popular is perhaps Webpack) finds all the imports and exports in your code and combines it all into one file.
Why you should use a bundler:
- Everyone is using it
- It's the standard
- It's popular
- ...
- It enhances page performance
- You get other goodies like minification and whatnot
- You can import (some) npm packages
That doesn't mean we should never use in-browser imports. It's totally fine when you're using it in development, as it's easier to set up anyways. Vite, a popular development framework, takes advantage of this to improve the DX (developer experience) by removing the bundler wait time every time you re-run your code.
But again, don't use this in production.
I suggest you use a bundler since you have Node and TS set up anyways. It'll be easier in the long run...
Answered By - code
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.