I'm trying to practice using date-fns library (not using React just simple HTML page) But when i'm trying to load it it's saying
TypeError: Failed to resolve module specifier "date-fns". Relative references must start with either "/", "./", or "../".
html.index:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transaction Dates</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
padding: 20px;
}
.transaction {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
}
.transaction span {
font-weight: bold;
}
</style>
</head>
<body>
<h1>Transaction Dates</h1>
<div id="transactions"></div>
<!-- Load date-fns library -->
<script src="https://cdn.jsdelivr.net/npm/date-fns@latest"></script>
<!-- Load our JavaScript file -->
<script src="script.js" type="module"></script>
</body>
</html>
script.js:
import { differenceInDays, differenceInHours } from 'date-fns';
const transactions = [
{ amount: 200, date: new Date('2024-07-16T21:31:17.178Z') },
{ amount: 455.23, date: new Date('2024-07-16T07:42:02.383Z') },
{ amount: -306.5, date: new Date('2024-07-15T09:15:04.904Z') },
{ amount: 25000, date: new Date('2024-07-14T10:17:24.185Z') },
{ amount: -642.21, date: new Date('2024-07-13T14:11:59.604Z') },
{ amount: -133.9, date: new Date('2024-07-12T17:01:17.194Z') },
{ amount: 79.97, date: new Date('2024-07-11T23:36:17.929Z') },
{ amount: 1300, date: new Date('2024-07-10T23:51:36.790Z') }
];
const container = document.getElementById('transactions');
function formatTransactionDate(date) {
const now = new Date();
const daysPassed = differenceInDays(now, date);
const hoursPassed = differenceInHours(now, date);
// Check if it's within the last 24 hours
if (daysPassed === 0 && hoursPassed < 24) {
return "Today";
} else if (daysPassed === 1) {
return "Yesterday";
} else {
return `${daysPassed} days ago`;
}
}
function displayTransactions() {
transactions.forEach(transaction => {
const formattedDate = formatTransactionDate(transaction.date);
const transactionElement = document.createElement('div');
transactionElement.classList.add('transaction');
transactionElement.innerHTML = `
<span>Amount:</span> ${transaction.amount.toFixed(2)}<br>
<span>Date:</span> ${formattedDate}<br>
`;
container.appendChild(transactionElement);
});
}
// Display transactions on page load
displayTransactions();
package.json :
{
"dependencies": {
"date-fns": "^3.6.0"
}
}
package-lock.json :
{
"name": "test dates",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"date-fns": "^3.6.0"
}
},
"node_modules/date-fns": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
}
}
}
What's the issue with that?
nothing helped, seeking for a help
It seems you confused a few things when working with various module formats.
In your HTML page, your reference date-fns
via jsdelivr.com
. When following the URL to the script, it returns a so called UMD
script, short for Universal Module Definition
which is not the same as a ES2015 module. The UMD module attaches a dateFns
namespace to the window
object. Therefor, change the line
import { differenceInDays, differenceInHours } from 'date-fns';
to
const { differenceInDays, differenceInHours } = window.dateFns;
and it should work.
Please note that I used
https://cdn.jsdelivr.net/npm/[email protected]/cdn.min.js
instead ofhttps://cdn.jsdelivr.net/npm/date-fns@latest
because SO does not accept the resource otherwise. However, both URLs point to the same file.
const { differenceInDays, differenceInHours } = window.dateFns;
const transactions = [
{ amount: 200, date: new Date('2024-07-16T21:31:17.178Z') },
{ amount: 455.23, date: new Date('2024-07-16T07:42:02.383Z') },
{ amount: -306.5, date: new Date('2024-07-15T09:15:04.904Z') },
{ amount: 25000, date: new Date('2024-07-14T10:17:24.185Z') },
{ amount: -642.21, date: new Date('2024-07-13T14:11:59.604Z') },
{ amount: -133.9, date: new Date('2024-07-12T17:01:17.194Z') },
{ amount: 79.97, date: new Date('2024-07-11T23:36:17.929Z') },
{ amount: 1300, date: new Date('2024-07-10T23:51:36.790Z') }
];
const container = document.getElementById('transactions');
function formatTransactionDate(date) {
const now = new Date();
const daysPassed = differenceInDays(now, date);
const hoursPassed = differenceInHours(now, date);
// Check if it's within the last 24 hours
if (daysPassed === 0 && hoursPassed < 24) {
return "Today";
} else if (daysPassed === 1) {
return "Yesterday";
} else {
return `${daysPassed} days ago`;
}
}
function displayTransactions() {
transactions.forEach(transaction => {
const formattedDate = formatTransactionDate(transaction.date);
const transactionElement = document.createElement('div');
transactionElement.classList.add('transaction');
transactionElement.innerHTML = `
<span>Amount:</span> ${transaction.amount.toFixed(2)}<br>
<span>Date:</span> ${formattedDate}<br>
`;
container.appendChild(transactionElement);
});
}
// Display transactions on page load
displayTransactions();
body {
font-family: Arial, sans-serif;
line-height: 1.6;
padding: 20px;
}
.transaction {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
}
.transaction span {
font-weight: bold;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/cdn.min.js"></script>
<h1>Transaction Dates</h1>
<div id="transactions"></div>
TL;DR explanation
ES2015 modules work differently in the browser than they do in Node. The rules for the browser are more strict, meaning you must provide a real URL to the resource. This is the reason for the
Failed to resolve module specifier "date-fns". Relative references must start with either "/", "./", or "../"
error you receive. The browser simply does not know where to look for the resource, because it does not "magically" know what date-fns
refers to.
In Node on the other hand, you can get away with using the NPM package key "date-fns", because node's resolution algorithm works the way it works: It looks into the local node_modules
folder and searches for a package that has the name date-fns
written into it's package.json
file and uses the package if it finds it.
If you feel that you want/need to read about the way Node works, have a look at the docs. Contrast that with MDN's documentation about JS modules usage in the browser.