x)
- [ ] new
- [x] build
- [ ] serve
- [ ] test
- [ ] e2e
- [ ] generate
- [ ] add
- [ ] update
- [ ] lint
- [ ] xi18n
- [ ] run
- [ ] config
- [ ] help
- [ ] version
- [ ] doc
Right now, running ng build, generates a flattened directory structure.
In of itself, there's nothing wrong with this, so "not a bug".
However, when serving via some frameworks, for example "Flask", angular's build directory structure becomes a pain point of either your js/css assets throwing 404's, or your media assets throwing 404's.
Not without plenty of cp/mv/rm/etc magic to go along with it.
There already exists --deploy-url but doesn't affect the output structure like you'd expect.
I'd like, ideally, to have an angular.json architect option to specify where I want my js and css files to be placed.
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "../src/client_build",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/static"
],
"assetsOutputPath": "static/media",
"styles": [
"node_modules/bootstrap/scss/bootstrap.scss",
"node_modules/@fortawesome/fontawesome-free/css/all.css",
"node_modules/ngx-toastr/toastr.css",
"src/styles.scss"
],
"stylesOutputPath": "static/css",
"scripts": [
"node_modules/@fortawesome/fontawesome-free/js/all.js"
],
"scriptsOutputPath": "static/js",
"es5BrowserSupport": true
},
See as I've got a few *OutputPath options in there now where I can explicitly say within the context of outputPath where I want the build to spit out the js files and adjust the internal directory pathing to reflect.
I've followed several Flask specific angular guides to no effect. Additionally while im in a fortuitous position to make adjustments to the server side layer, I know many many many others do not have that luxury.
I also know Flask isn't unique in this scenario, it's just the one affecting me right now.
The react-app I just replaced with Angular, had the following directory structure
|_ index.html
|_ static/
|_ media/
|_ *.png
|_ js/
|_ *.js
|_ css/
|_ *.css
When placed verbatim into a Flask configuration such as
template_dir = os.path.abspath('client_build')
static_dir = os.path.abspath('client_build/static')
app = Flask(
__name__,
template_folder=template_dir,
static_folder=static_dir,
)
it works perfectly. Everything is found, everything functions as it should.
When I place the angular distribution in there, the index.html loads fine, but everything else fails to load, js/css/images included.
I've been monkeying with Flask and angular-cli for days now trying to find the sweet spot configuration wise, but it still isn't quite there.
currently I have as modified build options
"build-dev": "ng build --watch --deploy-url=/assets/",
"build": "ng build --deploy-url=/assets/ && cp ../src/client_build/assets/* ../src/client_build/ && rm -rf ../src/client_build/assets",
"build-prod": "ng build --prod --build-optimizer --delete-output-path --optimization --progress --vendor-chunk --aot --deploy-url=/assets/ && cp ../src/client_build/assets/* ../src/client_build/ && rm -rf ../src/client_build/assets",
with a flask config like
template_dir = os.path.abspath("client_build")
static_dir = os.path.abspath("client_build")
static_url = "/assets"
app = Flask(
__name__,
template_folder=template_dir,
static_folder=static_dir,
static_url_path=static_url,
)
and the problem I face now, is that all of my everything is in the root directory, images included, AND, with the build-dev script, the app works but all the images are missing because the --watch doesn't know to manipulate the output directory every time.
I know this isn't a Flask help thread, but if I could just tell angular-cli where to put things (like I feel I should be able too..) I would be a much happier camper. Not every hosting situation for angular output is going to be like throwing the distribution into an s3 bucket and calling it a day.
Doesn't the resourcesOutputPath option help you with that?
Also, note that the you can already specify where to output the assets.
Example:
"assets": [
{ "glob": "**/*", "input": "src/assets/", "output": "/assets/" },
{ "glob": "favicon.ico", "input": "src/", "output": "/" },
]
See https://angular.io/cli/build and https://next.angular.io/guide/workspace-config#project-asset-configuration for more details.
Doesn't the
resourcesOutputPathoption help you with that?
This helps a little, unfortunately this only seems to work with fonts, some images, and everything else not involving the .js
I'm looking to as well move the *.js files to the /assets folder
Also, note that the you can already specify where to output the assets.
Example:
"assets": [ { "glob": "**/*", "input": "src/assets/", "output": "/assets/" }, { "glob": "favicon.ico", "input": "src/", "output": "/" }, ]See https://angular.io/cli/build and https://next.angular.io/guide/workspace-config#project-asset-configuration for more details.
There doesn't appear to be an output available in the angular.json for where to stash these js and css files

for the sake of brevity, here's my build script
ng build --prod --build-optimizer --delete-output-path --optimization --progress --vendor-chunk --aot --deploy-url=/assets/ --resourcesOutputPath=/assets/
with this build in the angular.json
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "../src/client_build",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"node_modules/bootstrap/scss/bootstrap.scss",
"node_modules/@fortawesome/fontawesome-free/css/all.css",
"node_modules/ngx-toastr/toastr.css",
"src/styles.scss"
],
"scripts": [
"node_modules/@fortawesome/fontawesome-free/js/all.js"
],
"es5BrowserSupport": true
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
Angular CLI doesn't have an option to configure where assets of particular types go inside the output folder, no.
It sounds like something simple to add but I think it'd end up being fairly complex. JS and CSS files can attempt to load both media and css resources. Making those work is probably possible but requires a lot of rewiring in the js/css pipeline. It also requires that all the css processors we support (scss/sass/less/stylus) have options for this, and if they don't then we'd have to add our own custom rewiring plugins.
Trying to adopt Flasks specific requires sounds like a slippery slope: what about other servers that also expect different file structures? I can't say I know much about Flask but I find it hard to imagine there's no way to just serve the files in a directory as most basic servers do. I don't think it makes a lot of sense to add options to massage valid output to the liking of individual servers, and would expect that servers can be configured to accept valid output.
I can't say I know much about Flask but I find it hard to imagine there's no way to just serve the files in a directory as most basic servers do
Hi @filipesilva
Web frameworks like Express and Symfony are extremely easy to setup with Angular due to how you configure the static resource basically at it's core simply being a folder.
Web frameworks like Flask do it different where I think it's instead it's trying to manipulate it's router.
What I would offer to challenge is to try and setup a very very basic does-nothing flask app, and just try to get an Angular +Router production-build and dev-watch-build output into it, which runs the angular app when hitting the server url, and the angular app can make an http call to the flask app as if it were an api layer
Honestly, it may be _very_ easy and I'm just missing something, but it feels very incompatible with how these frameworks want to work with static assets. Because React worked, and it worked because it uses a sub-folder structure by default to put requested sourced js/css/img files into subfolders away from the root, and Flask really liked that.
separately, Flask isn't a difficult framework to get up and running and try this with, but if you're more familiar with Node then I found a somewhat closeish parallel: https://github.com/fastify/fastify where I ran into a pretty similar issue, but the situation might differ a little. Or maybe it doesn't, it's been a while, I havent touched Flask since I forcibly shoehorned my angular app into it and manually manipulated the files everytime to work with it (In the end, I just had to accept that during Dev, images just weren't going to work until I made the production build)