Problems with loading external JS files in Angular dev server while production build works fine

I’m developing a simple Angular application that requires some external JavaScript files. It seems that these files are loading perfectly when I build the app for production, but I’m running into issues with the development server.

Current setup:

  • Angular CLI version: 20.0.1
  • Initiated the project using ng new myapp --routing
  • Placed a file at public/scripts/helper.js with the following contents:
export const APP_NAME = "myapp";
export function displayMessage() {
  alert("This is a message from the external script.");
}

In my index.html file:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>MyApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
  <script type="module" src="scripts/helper.js"></script>
  <script type="module">
    import { displayMessage } from "/scripts/helper.js";
    displayMessage();
  </script>
</body>
</html>

Issue:
When I execute npm run build and serve the output from the dist folder, everything functions correctly, and the alert appears without any errors in the console.

However, when I run ng serve, the console throws a vite error:

[vite] Internal server error: Failed to resolve import "/scripts/helper.js" from "/index.html?html-proxy&index=0.js". Does the file exist?

I am aiming to use an external framework that demands this format. How should I appropriately manage external JS files while in Angular development mode?

Quick fix: add your script to the assets array in angular.json instead of the public folder. Vite’s dev server doesn’t like module imports from public, but assets work fine. Just move helper.js to src/assets/scripts/ and update the path - should work right away.

Had this exact problem when upgrading Angular versions. Vite handles module imports differently than webpack - files in the public folder work for direct HTTP requests, but Vite won’t resolve ES module imports from there during dev.

Here’s what fixed it: keep your external script in public, but change how you import it. Skip the ES6 imports in index.html and create a small TypeScript service that dynamically loads the script with import(). You can handle the loading in your Angular component and catch errors properly. Dynamic imports work the same in dev and production, so no build config changes needed.

This is a common issue with Angular’s development server due to the way Vite handles file serving compared to production builds. The problem arises because the development server does not recognize paths from the public directory by default.

To resolve this, you have a couple of options. One approach is to migrate your helper.js to the src/assets folder. Once in that location, update your index.html to load it as assets/helper.js. This method ensures that Angular’s development server processes the file correctly. Another option is to adjust the angular.json to include the public/scripts directory in your assets under the serve configuration, although the first option is generally simpler and more effective.

This topic was automatically closed 6 hours after the last reply. New replies are no longer allowed.