Skip to main content

Command Palette

Search for a command to run...

How to make Angular CLI built app work from a subfolder

Updated
2 min read
M

I'm JS developer with 13 years of professional experience. I'm always happy to teach my craft.

Angular CLI, along with many boilerplate generating tools for other frameworks, insists on outputting the built code in a way that will work only on the top-level domain. I can't understand the reason for this, and definitively is not working well with quick&drity example apps you would like to show anywhere easily.

In this article, I'll show you how to make angular build code in a way that you can just drop on any level of subfolders & it will work.

The problem

After generating your application with:

$ npx -p @angular/cli ng new my-app

when you build your app with:

$ npm run build

you will get the dist/my-app/index.html file with:

<!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">
<link rel="stylesheet" href="styles.31d6cfe0d16ae931b73c.css"></head>
<body>
  <app-root></app-root>
<script src="runtime.97e25c2126edd0d76e43.js" defer></script><script src="polyfills.cb52f48ffd1aee6e8d09.js" defer></script><script src="main.f5cfb581cea2faefeeff.js" defer></script>

</body></html>

Although src="runtime... looks OK, and it seems it should be working in the browser, when we visit localhost/my-app/dist/my-app, we see nothing else but a white screen. That's because there is:

  <base href="/">

Which sets the context for all location references to the absolute location on our current domain. If you change it manually to <base href="./">, all should work fine - now the only thing is to set it in a way that will not require manual tweaks after every build.

The solution

There are 2 possible solutions - use the CLI parameter, or set the value in the angular.json file.

CLI parameter

angular build accepts --base-href param that allows us to override this value. Adding it manually every time would be a lot of a hassle, so the best to set it in the package.json:

{
  ...
  "scripts": {
    ...
    "build": "ng build --base-href='./'",
    ...
  }
  ...

Then, whenever we run npm run build, the value is set correctly.

Angulars json configuration

If the CLI param feels a bit hacky to you, you can set the value in the angular.json config:

{
  ...
  "projects": {
    "my-app": {
      ...
      "architect": {
        "build": {
          ...
          "options": {
            ...
            "baseHref": "./"
            }
  ...

I cannot find it in the official documentation, but it's working & it's recognized by angular.json validation.

Summary

In this article, we have seen how to set up Angular CLI generate app to work from a subfolder. With one or the other solution in place, your built app should look like:

Screenshot 2021-07-18 at 08-11-15 MyApp.png

W

it's working for me, thanks!

B

Thanks for the info.

This seems like it wont work if you have routes that are loaded directly though?

e.g. if a user clicks a link to your app like site.com/some-base-path/some/route/in/the/app The browser is going to try load runtime.js etc from site.com/some-base-path/some/route/in/the/runtime.js Whereas it actually sits at site.com/some-base-path/runtime.js

Any suggestions how to tackle that?

M

You are right, this will work only with routes with #/. You are looking for some server side rendering solution. I've never moved away from the routes with hashes: the applications I work on are not available for anonymous users and they don't need indexing by search engines.

1
V

Hey Bob Johnsonany luck finding solution? I've got the same issue

B

Vishakha Tak well, in my case i know the base path my app will be deployed behind, so i pretty much went with this but with /whatever instead of a relative link like ./

More from this blog

H

How to dev

164 posts

Articles about programming. JavaScript and general advice for beginners in the industry.