skip to Main Content

I have a simple web page made up of vanilla html, css and js files.

I’d like to be able to use the import { moment } from "moment" syntax in my js files but when I add npm to my proejct, install moment wiht npm install and use that syntax when I run my app using live-server I get an error:

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

2

Answers


  1. The error you’re seeing is because the import syntax you’re trying to use is part of ES6 modules, which is not supported in all browsers and environments. When you’re working with a simple web page and not using a build tool like Webpack or Babel, you’ll need to include Moment.js through a <script> tag in your HTML file.

    Here’s how you can do it:

    1. First, include the Moment.js library in your HTML file. You can use a CDN link for this. Here are a couple of options:
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment-with-locales.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/moment.min.js"></script>
    

    You can include either of these in the <head> section of your HTML file.

    1. Once you’ve included Moment.js, you can use it in your JavaScript code without the import statement. Here’s an example:
    <!DOCTYPE html>
    <html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"></script>
    </head>
    <body>
        <button type="button" onclick="clickHandler()">Get Today!</button>
        <script>
            function clickHandler() {
                alert(moment().format('dddd, Do MMM YYYY, h:mm:ss A'));
            }
        </script>
    </body>
    </html>
    

    In this example, when you click the "Get Today!" button, it will show an alert with the current date and time, formatted with Moment.js.

    If you want to use ES6 import syntax, you would need to set up a build process with a tool like Webpack or Babel, or use a server-side environment like Node.js

    Login or Signup to reply.
  2. Yes, it’s possible. Browsers support native ES6 modules for more than 6 years. Here is an example configuration for Express, but it should work with all serious web servers.

    index.html:

    <!DOCTYPE html>
    <html>
    <head>
      <script type="importmap">
        {
          "imports": {
            "moment": "/moment"
          }
        }
      </script>
    
      <script type="module" src="/app.js"></script>
    </head>
    <body>
      <h1>Moment</h1>
      <div></div>
    </body>
    </html>
    

    app.js:

    import moment from 'moment';
    let x = new moment();
    document.querySelector('div').textContent = x;
    

    index.js:

    import express from 'express';
    const app = express();
    import { dirname } from 'node:path';
    import { fileURLToPath } from 'node:url';
    
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = dirname(__filename);
    
    app.get('/', (req, res) => {
      res.sendFile(__dirname + '/index.html');
    });
    
    app.get('/app.js', (req, res) => {
      res.set('Content-Type', 'application/javascript');
      res.sendFile(__dirname + '/app.js');
    });
    
    app.get('/moment', (req, res) => {
      res.set('Content-Type', 'application/javascript');
      res.sendFile(__dirname + '/node_modules/moment/dist/moment.js');
    });
    
    app.listen(8080, () => {
      console.log('Server running...');
    });
    

    package.json:

    {
      "name": "example",
      "scripts": {
        "start": "node index.js"
      },
      "dependencies": {
        "express": "^4.18.2",
        "moment": "^2.29.4"
      },
      "type": "module",
      "devDependencies": {
        "@types/express": "^4.17.21"
      }
    }
    

    I’ve used an import map to allow import moment from 'moment'; without relative paths. You have to configure your web server to point to the Moment JavaScript code.

    If the web server doesn’t support a rewrite (as I used for Moment), you have to use the full path in the import map.

    Here you can find out more about native ES6 modules: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search