I want to build an Angular 5 app once, and then publish it to different addresses, for example to:
- https://sub1.example.com/myapp1
- https://sub2.example.com/myapp2
- https://sub3.example.com/myapp3
By default, Angular will assume that all files are hosted in / so when i access index.html, it will load scripts such as https://sub1.example.com/vendor.bundle.js which will 404 because it's deploy to /myapp1/vendor.bundle.js (to make it slightly more complex, I'm actually loading the files from a CDN from a separate domain, but I don't think this affects the question):
Angular 5 allows me to run:
ng build --deploy-url "https://example.com/myapp1"
This will modify the inline.bundle.js and set the following:
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "https://example.com/myapp1";
This in turn will make sure that scripts are loaded from the proper path.
However, this is a compile time switch, and I want to configure this either at deploy-time or at runtime.
I've read various suggestions, such as:
- How do I set the deployUrl at runtime in Angular - This does not seem to work any more. The referenced variable __webpack_public_path__ does not exist anywhere in the code after I run ng build.
- Setting server url dynamically during runtime in AngularJs app using value
during-runtime-in-angularjs-app-using-value - This only applies to Angular .
My current workaround is to update the variable __webpack_require__.p at deploy-time, but this is extremly error-prone since this variable at this point is minimized to something like "n.p" and relying on an internal implementation detail.
What would be the proper approach to do this?
Setting the deployUrl setting in .angular-cli.json, or passing in the --deploy-url to the build command does 2 things. It makes sure that the script includes in the index.html file are using that as the base, and it sets a variable that makes sure that webpack adds that as the "base path" for any lazy loaded modules. That much we agree on I guess, and figuring out where to load the scripts from in the html is pretty simple. However, setting the path that webpack should use is a bit more tricky... The value used by webpack is not named __webpack_public_path__ as mentioned in the linked suggestion and in the documentation.
You even mention the solution yourself when you say that setting the --deploy-url causes the following
__webpack_require__.p = "https://example.com/myapp1";
So, instead of setting the __webpack_public_path__ at runtime, as mentioned explained in the documentation, you have to set the __webpack_require__.p property.
The easiest way to do this is to just set it in the app.module.ts file. Doing something like this should work in your scenario
index.html
<script>
window.config = { basePath: 'https://sub1.example.com/myapp1' }
</script>`
app.module.ts
// imports etc...
declare var __webpack_require__: any;
declare var config;
__webpack_require__.p = window.config.basePath;
@NgModule({})
...
This will make sure that the __webpack_require__.p property is set to the configured value on load.
In this case I just added the configured value as a config variable on the window object, but you can fetch it from wherever you want. And to keep it simple, I just assumed the value would always be there... You might want to have a fallback in case the config object isn't available, or the basePath property isn't set.