node.jsamazon-web-servicesexpressaws-sdkjavascript-import

import statements in statically served JS files, NodeJS with expressJS


I am trying to create a NodeJS app that hosts a webpage. This app will be hosted on AWS, and I will need to interact with other AWS services via button clicks on the webpage. My idea was to write a simple html file containing the page layout and a button. I then wrote a js file and attached it via script tags to said html file, the purpose of which is to add advanced functionality to the button. However when I tried to import the AWS sdk in the js file, I keep getting errors like:

Failed to resolve module specifier "@aws-sdk/client-s3"

"GET http://localhost:8080/js/@aws-sdk/client-s3/ net::ERR_ABORTED 404 (Not Found)".

Here is the directory layout of my project:

NodeJS 18 running the file app.js:

// Imports
import path, { join } from "path";
import express from "express";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const port = 8080;

const staticPath = join(__dirname, "public");
app.use(express.static(staticPath));

app.get("/", (req, res) => {
  res.send("test");
});

app.listen(port, () => console.info(`App listening on port ${port}`));

As you can see my current implementation is using statically served files in the /public directory. This works fine from what I can tell to simply use html, css, and js(built-in stuff only)

The problem files are upload.html and upload.js. Within upload.html I have the script tags written like this:

<script type="module" src="../js/upload.js"></script>

Within upload.js I am attempting to import the module like this:

import { S3Client } from "@aws-sdk/client-s3";

Just the message above gives the error:

Uncaught TypeError: Failed to resolve module specifier "@aws-sdk/client-s3". Relative references must start with either "/", "./", or "../".

When I try adding these path prefixes as listed and in various combinations to try to point the import command to the package location or to the root directory or anything else really, I get this error(path after localhost:8080 changes depending on the path in the import command):

GET http://localhost:8080/@aws-sdk/client-s3 net::ERR_ABORTED 404 (Not Found)

My assumption is that there is some issue with me trying to import these packages within my statically served JS files. I'm not sure how to proceed from here even after much googling. Perhaps my approach to the project structure is at fault or maybe I am just missing something simple. I'll be happy to provide any additional details as needed!


Solution

  • In order to use a module like this in the browser you will need to bundle it using a bundler such as Webpack, esbuild, parcel or rollup. This will then create a file you can import using a <script type="module"/> tag.

    Or use a handy online too such as this.

    AWS SDK Webpack instructions.

    I do want to bring up something that you might be aware of but perhaps not - and that is the security of your app. Do not put any access/secret keys in this code. Depending on what you are doing with S3 there are a few ways to get/put data securely.