AS3
AS3

Reputation: 191

Can I use npm packges in a vanilla web page?

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 "../".

Upvotes: 0

Views: 220

Answers (1)

jabaa
jabaa

Reputation: 6789

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

Upvotes: 0

Related Questions