I have a require statement in my script.
const packageJsonVersion = require('../package.json').version;
If I try and run the script I get an error saying I need to convert it to an import statement.
I changed the code to import { version as packageJsonVersion } from '../package.json' but when I run the script I get the following error.
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".json" for /home/alex/_code/connect/package.json
I'm not sure how to get around this.
It depends on what environment you're doing this in.
Right now, browsers don't natively support JSON modules (though it's coming).
If you're doing this with a bundler, you need to be sure to tell the bundler how to handle the .json extension.
If you're doing this in Node.js, you need the JSON module notation (assert {type: "json"}).
Separately, though, JSON modules won't support named exports (this is mentioned by both links above). You'll have to import the default and then use the version property on it:
import data from "../package.json" assert { type: "json" };
const packageJsonVersion = data.version;
Related
I'm trying to use the postal-mime JS library in a Chrome browser extension using Manifest V3. My extension spawns a service worker and I'm trying to use this library there. To import it, I tried both
const { PostalMime } = require("postal-mime");
and
import { PostalMime } from "postal-mime";
while my code looks like this:
const parser = new PostalMime();
parser.parse(result).then((email) => console.log(email));
The variable result contains a standard email message as a string that I'd like to parse.
In both cases, I get the following error:
Uncaught (in promise) TypeError: PostalMime is not a constructor
at sw.js:66:1
(anonymous) # sw.js:66
Promise.then (async)
(anonymous) # sw.js:61
What am I doing wrong?
Thank you for your help,
GTP
This is not a ES module so to import it in general you need to use webpack or browserify i.e. a build system for your extension. Luckily, in this case you can find a prebuilt js file on unpkg.com which you should download manually into the directory of your extension.
import './postal-mime.js'; // path and .js suffix are required for native import!
const PostalMime = postalMime.default;
const parser = new PostalMime();
parser.parse(result).then((email) => console.log(email));
Note that since postal-mime.js is not a native ES module we used a nameless import to let the library create its export in a global variable. To see the name of the variable (postalMime) look at the beginning of the file where you'll see exports.postalMime=. As for default it is an internal mechanism used by npm module implementation, which you can see in devtools console when you inspect postalMime object. Other libraries may use multiple named properties instead.
I ended up using the library emailjs-mime-parser. While not a real solution to the asked question and despite having fewer functionalities than postal-mime, at least I'm able to import it out of the box without thinkering with Webpack's config.
So... Lets say you have this library you want to post to NPM.
You convert it to a module type and use:
import {createRequire} from "module";
const require = createRequire(import.meta.url);
To implement require onto it. As you may know require can be used to read JSONs. So you try to read a json. Everything works fine when you test it onto a local machine. When you try linking it tho and you try to call that function it throws:
Error: Cannot find module 'something.json'
Is this an on going npm issue and if so how can i avoid it? Is there another way to read JSONs other than reading them as a txt file (which isn't very practical)?
According to MDN, import() is a function-like dynamic method. However, I found it not dynamic in my ts project.
Say I have an appleShare.json:
{
price: 123
}
And then, there's an index.ts:
console.log("update the price to 456...")
// manually modify the json file content making price 456
let currentPrice = await import("./appleShare.json").then(obj=obj.price)
console.log(currentPrice)
I ran index.ts directly in vs-code, the result in console:
update the price to 456...
123
I expect 456, but got 123. From my limited knowledge I guess there are two possible reasons:
I have a misunderstanding in import() and dynamic importing.
My understanding is right but vs-code compiled all the code to js before executing them. So, I will never get the newly modified price.
I want to ask, what's exactly the cause of the issue, and how to resolve it?
The "dynamic" import() has the following different behaviors from the regular import which is often referred to as the "static" import.
You can construct a module filename in code and can then load that module from the filename you built. You cannot dynamically build module filenames with the regular import. Filenames for the regular import must be statically specified so they are known by anyone who parses the file, but does not run the code in it. This static declaration enables code analysis for things like tree-shaking and bundling. The dynamic import cannot be used as effectively with features like that.
The import() can happen anywhere in your code (not only at the top of your module). The regular import cannot be just anywhere in your code. In this sense, it is "dynamically" loaded upon demand, not only at the beginning of the module.
A dynamic import() statement can be used to load an ESM module into a CommonJS module. The regular import statement cannot be used in a CommonJS Module at all.
Modules, even dynamically loaded ones are cached. Once they are loaded, subsequent import() statements using the same filename just load the module from the cache, they do not re-read the file. That's why your subsequent import() is not picking up the modified JSON.
If you want to re-read the file, then don't use import - use something like fs.promises.readFile() and then parse the JSON. This will read a fresh copy of the data each time you call it.
Hi i'm currently learning nodejs and I try to import a json file like this :
'use strict'
import data from 'users.json'
console.log(data)
Each time I get this error "Cannot find package 'users.json'"
But if I read the file with fs it worked so can you explain me how to do please
try :
import data from './users'
which is the es6 method of doing things or if you want an older syntax method you can try
const data = require('./users')
Okay so the explanation just is this, those fullstops and forward slash are used to indicate relative paths to the file the import is being called from, which means somethings you'd see something like for example ../file/help. The ./ means go up one directory ../ means go up two directories and so on. The name after the slash just tells your program the folder to go in to look for the file to import from so ./folder means go up one directory and enter into the folder directory and so on.
Almost forgot to mention, you should not import from a json file or a text file or any other file that does not have a .js extention(of which you do not actually have to specify) unless absolutely neccessary. To deal with files in node you have to use the fs library.
const fs =require('fs')
....
fs.readFile('./users.json','utf-8',(err,jsonString)=>{
const data = JSON.parse(jsonString);
//whatever other code you may fanacy
}
take a look at the fs module for a list of awesome features you can use to play with files
While the selected answer is correct, here's an explanation that I hope might add some clarity:
import MyModule from 'some-module'
is ES6 import syntax, as opposed to the older CommonJS syntax, which uses require.
CommonJS's require can be used to import files generally; ES6's import statement is more specific, and is generally used for importing js files which meet the criteria for being a module (having an export statement), or specific assets such as CSS sheets. Unlike require, it won't generally work for reading in files that are not modules.
You can't mix CommonJS require and ES6 import in the same file (at least not easily), so if you're using ES6 import and wish to read a file, do so with fs.readFileSync or a similar method. If the file is a json string, you'll need to parse it with JSON.parse().
If you want to use ES6 (NOT CommonJS) module system but want to use the Node.js version which is less than V18 (supports direct json import) then use the below approach.
import { createRequire } from "module";
const require = createRequire(import.meta.url); // construct the require method
const data = require("users.json"); // Now you can use require method in ES6
console.log(data)
Scenario
Whenever I run my application from index.html, referencing the main.js file, which has been compiled from Typescript using es6 as the target and ESNext as the module, I get this error within the browser:
Error
main.js:3 Uncaught SyntaxError: Unexpected token {
Main.ts
/// IMPORTS
//////////////////////////////////////////////////////////////////////
import { Player } from './classes/Player' <= Error Here!
import { printTable } from './helpers/Helpers'
/// MAIN COMMANDS
//////////////////////////////////////////////////////////////////////
let p1 = new Player('Bob', 'Hunter', 1, 10);
printTable(p1);
Concept
I appear to be importing my code improperly, and (for whatever reason) don't know why or can't figure it out. Everywhere I look, this is indicated as the method of importing exported code, classes, etc... When all code exists within a single file, all classes, interfaces, helpers, etc..., everything converts and runs dandy, except when I want to compartmentalize my code, and handle it this way.
Any guidance would surely be appreciate.
Cheers and thanks in advance!
Source Code
...and ESNext as the module, I get this error within the browser:
main.js:3 Uncaught SyntaxError: Unexpected token {
Your error here is that you are trying to use ES6 import syntax in a traditional script (<script src="index.js"></script>). Using ES6 import and export only works with modules, used in the browser with <script type="module" src="whatever"></script>.
Have you looked into using Webpack? It can automatically compile your TypeScript files into one JavaScript bundle that you can load into your HTML file with a single script tag.
For you to import in this way you are using, you must export the class reference directly, without being inside an object.
Examples:
(correct) export Player;
(wrong) export { Player }