Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

/public vs /src/assets behavior #1942

Closed
coryrylan opened this issue Sep 1, 2016 · 59 comments · Fixed by #2570
Closed

/public vs /src/assets behavior #1942

coryrylan opened this issue Sep 1, 2016 · 59 comments · Fixed by #2570
Assignees
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@coryrylan
Copy link
Contributor

coryrylan commented Sep 1, 2016

  1. OS? Windows 7, 8 or 10. Linux (which distribution). Mac OSX (Yosemite? El Capitan?)
    Mac OSX El Capitan
  2. Versions. Please run ng --version. If there's nothing outputted, please run
    in a Terminal: node --version and paste the result here:
    angular-cli: 1.0.0-beta.11-webpack.8
    node: 5.10.1
    os: darwin x64

The latest version of the cli replaces the public directory with the new src/assets directory which works great for copying static files into dist but I'm not sure if the behavior is quite right. Many files are expected to be on the root of a hosted site such as robots.txt and ico files. When the cli copies files over from assets into the dist they are placed at dist\assets. Is there any way to be able to copy files over to the root level of the dist?

@ghost
Copy link

ghost commented Sep 2, 2016

ico/faviocon files can be anywhere, the default location is usually the root, but you can change the locations in html. I consider robots and favicons web specific, not directly under the app scope. I would place them in the dist folder and commit those under git.

If you must change this behavior, edit the angular-cli.json 'assets: 'assets', changing it to 'assets: '.' should work.

@ghost
Copy link

ghost commented Sep 2, 2016

@robertbaker I've tried this. Turns out it doesn't work. But I think that this is a legitimate question of @splintercode. It should definetly be possible to add files like a robots.txt without hacking. assets should by default be mapped the way public was mapped. If you want a assets folder in your dist, you can always create a assets/assets folder.

@kylecordes
Copy link

This new behavior also affects our projects here. We have had to work around in the obvious hacky way, by building a build process around the CLI-provided build process which adds the files we need at the "root" of the output.

I think most real projects will eventually have at least one, and often many, files that needs to be located somewhere in the "root" of the output - files that CLI doesn't know about and can't be responsible for. Until .webpack.3..8, this was supported and worked very well. I request the feature be put back and kept in the future also.

@ghost
Copy link

ghost commented Sep 2, 2016

I would be fine if the contents of assets just where emitted to dist/ rather than dist/assets/. The public folder bugged me anyway, because everything in dist is public, too. Those are assets, therefore the name of the folder should be assets. Maybe resources, but please not public. Coming from a PHP background, this confused me a lot. I was thinking that the build process didn't work, because I was expecting the websever to serve from public.

@kylecordes
Copy link

Summary:

  • Rename of public to assets: good!
  • Restriction from being able to locate assets at dist root: bad!

@ghost
Copy link

ghost commented Sep 2, 2016

@kylecordes exactly, thank you, except:

Restriction from not being able to locate assets at dist root: bad!

@doggy8088
Copy link
Contributor

If angular-cli.json can configure "assets" property value as an array, that will be good.

For example:

"assets": ["assets", "robots.txt"],

@kylecordes
Copy link

I really don't want a solution like @doggy8088 outlined, in which I need to... tell... CLI... about... each... and... every... file... I... want... to... include.....

@ghost
Copy link

ghost commented Sep 2, 2016

@doggy8088 I think thats unnecessary, because if the contents of assets would be emitted directly into dist, you wouldn't need that. If you want a assets folder in dist, you could just create another assets folder. Like so:

src/assets/
├ assets/
│ ├ images/
│ ⋮
│ └ .htaccess
├ robots.txt
└ favicon.ico

would be mapped to:

dist/
├ assets/
│ ├ images/
│ ⋮
│ └ .htaccess
├ bundle.js
⋮
├ robots.txt
└ favicon.ico

In my opinion a second assets folder inside the src/assets/ folder would be useless, but at least you can do that if you want to

Update

I thought about it, and I think that the assets don't belong to src/, do they? I mean, assets are resources, not source files. Wouldn't it be the best to have a project structure like it was before, only with more descriptive names like this:

# Configs, like before. And with that, I mean **all** configs, 
# including angular-cli.json. Be consistent
config/
# distribution: compiled src/ and copied contents of resources/
dist/
# I'd rather have this in src/, since those are source files, aren't they?
e2e/ 
# images, global styles, robots.txt, .htaccess, who knows what,
# 1:1 mapped into dist/ on build
resources/
# source files, and with that, I mean source files and nothing else
# (no favicons or assets)
src/

@doggy8088
Copy link
Contributor

@christiandreher Actually, I like the original pubilc folder design better than current one. For the current 1.0.0-beta.11-webpack.8 design, the src/assets will copy to under dist/ so there is nothing can copy to the root of the 'dist/' folder, only the assets folder does.

@ghost
Copy link

ghost commented Sep 2, 2016

That's exactly what I am saying. Like I already said, I just didn't like the name public, because in the end, everything is public. I would just want to devide source files from static resources, using a src/ and a resources/ folder.

So in the end, you have a folder where you work (src/), a folder where you drop-in static resources (resources/) and a folder where your config goes (config/). Your compiled app, ready to ship, is then in the distribution folder dist/. I think thats a logical approach

@NgxDev
Copy link

NgxDev commented Sep 3, 2016

/public was fine, in my opinion (while also adding the possibility to customize copying other files too, like they've added /src/assets). But the /public folder behavior needs to be brought back (under the same or under a different folder name or even better: give us to possibility to set it up or not, our choosing). Problem with /public was: the cli was not copying .dot files over (like .htaccess) - see #1758. And when they fixed copying .dot files, they've also removed the /public folder, and closed the ".htaccess not getting copied" bug :)) nice :|
We definitely need to have files copied to the root of the /dist folder, and certainly not to have to point the cli to each and every single file.
Anyway, adding the /src/assets folder is not bad, perhaps. Although we could have been able to create an assets folder (or many other folders) in /public and everything from /public should have been copied over as is, keeping the folder structure - I think this would have been the ideal behavior.

@coryrylan
Copy link
Contributor Author

coryrylan commented Sep 5, 2016

This is preventing our team from upgrading to the latest CLI version as we have to have files in the root during development time. ng serve and ng build --watch wipe out the dist directory when building at development time. Has anyone come up with a workaround for this?

@NgxDev
Copy link

NgxDev commented Sep 5, 2016

It shouldn't have anything to do with the "mode" we're in (development or production). Custom files need to be copied to dist root no matter if you're in development mode or building for production

@coryrylan
Copy link
Contributor Author

@MrCroft correct, we have a workaround for a ng build command, just have a script to copy the files over to the dist but as for dev time ng serve or ng build --watch there doesnt seem to be a temporary workaround for this. I'm looking around to see if I can submit a PR but unfortunately my webpack skills are not up to par so might take a bit to figure how everything works.

@NgxDev
Copy link

NgxDev commented Sep 5, 2016

@splintercode oh, yeah...
Well, the solution needs to come from the CLI of course, because it should work both when building and serving, with the prod flag or without it, like it was intended before the public folder was removed (just that it had some bugs).
I wouldn't know how to accomplish that either, I've barely started to look at webpack recently.
And I don't know what they're planning here, but I suppose we will have the option to set up something similar to the public folder, because sooner or later everybody needs to have a bunch of files copied over to dist root. Whether we're serving or building, for production or not... the only difference is that in cases like yours (serve / build --watch) the dist folder isn't created physically in the project folder, but everything should work the same (wherever the dist/ files may reside - project folder, temp folder or memory).

@coryrylan
Copy link
Contributor Author

coryrylan commented Sep 6, 2016

Looks like this bug was introduced with this changeset 3dcd49b

@jjarrell50
Copy link

+1 on bringing back public. It setup nicely for my bower dependencies (polymer) and a couple of others. Not sure what the official word on how to handle bower dependencies.

@NgxDev
Copy link

NgxDev commented Sep 7, 2016

@jjarrell50 for now, with webpack.8 at least, you can add styles (either css or even scss, if the app was initialized with --style=sass) and scripts by using the styles: [] and scripts: [] arrays in angular-cli.json (I've tried by giving paths relative to the angular-cli.json file). So you can have your bower components folder anywhere (or even get your packages through npm instead of bower) and tell the cli what styles/scripts you need from there (and I suppose that the --prod flag also minifies/bundles those).

But the problem with public being dropped is (or was, if it got fixed in the meantime) that there is no way to tell the cli to simply copy other/any types of files to dist root, as is, not just js/css (.dot files and other types of files that need to be directly in the dist root and nowhere else)

@serhiisol
Copy link
Contributor

serhiisol commented Sep 9, 2016

We need to have a way to copy some assets from, for instance, node_modules (maybe svg files or something else)
With @doggy8088 's solution it can be possible.

What do you think ?

@NgxDev
Copy link

NgxDev commented Sep 9, 2016

Yes, like I've already said (and others as well, including @doggy8088), we definitely need the public functionality back (a possibility to have any kind of files - even an entire folder structure - copied over anywhere we'd need them, up to the root of dist, not just in a sub-folder).

@ghost
Copy link

ghost commented Sep 9, 2016

Per default, I would just copy the contents of assets/ into dist/ (So that assets/example.txt maps to dist/example.txt)

For assets that are located in other directories, like node_modules/ as @serhiisol mentioned, we could have an dedicated option in angular-cli.json to take care of that. This is mostly what @doggy8088 described, except for the fact that you don't have to explicitely mention every file in assets/ which should directly be copied to dist/. This would be way to verbose. I hope that the difference is clear

@CodeJason
Copy link

Anyone looking for a temporary fix, especially for those needing .htaccess - in your angular-cli.json file set:

assets:""

And this will copy over everything from src/
Definitely not a solution but will let you continue development until the public folder behavior is sorted.

@sqwk
Copy link

sqwk commented Sep 14, 2016

To me it looks like @CodeJason's inbetween solution will break the compile on the second cycle of ng build --watch or ng serve. Works the first time, but as soon as you make changes, the webpage remains white and no JS is loaded. Can anyone verify this?

@CodeJason
Copy link

CodeJason commented Sep 14, 2016

Sorry @sqwk I should have mentioned I had only tried it with ng build.

It looks like any time after the first round of building, it overwrites index.html with the one from src/, which is why it isn't importing any JS.
If you were still wanting to use this hack, you can copy the generated index.html after the first build into your src/ folder.

@JanStureNielsen
Copy link

JanStureNielsen commented Sep 14, 2016

Should I expect .scss files in ./src/assets to be compiled? In

angular-cli: 1.0.0-beta.11-webpack.8
node: 6.5.0
os: linux x64

they are not, even though my component-level .scss files are. If not, where should cross-component .scss files go? Here's my associated SO question...

@ghost
Copy link

ghost commented Sep 14, 2016

@JanStureNielsen It's for static assets only.
But this should give you what you want.
http://stackoverflow.com/a/39497573/263457

@cschroeter
Copy link

cschroeter commented Sep 15, 2016

If you are using some kind of CI / build chain simply just copy the .htaccess.

Here an example if for lftp (FTP)

lftp -e "put src/.htaccess; bye" -u $USERNAME,$PASSWORD $HOST

@tomschreck
Copy link

I agree with @Meligy. I also am using IIS and require web.config file (btw, thanks for rewrite rules example @Meligy). I think these static files should be outside of src and should be called static which get written to root of dist folder. If there are subfolders in 'static', then they become subfolders of dist.

Ideally, I'd like dist to contain subfolders for each environment as opposed to wiping out dist and starting over. If I do 'ng build' and 'ng build --prod', then dist would be:

dist
|-- dev
|-- prod
|-- [whatever other environment you have]...

this allows me to compare different environments.

Thanks for your time.

@ghost
Copy link

ghost commented Sep 20, 2016

@tomschreck just use the --output-path parameter. ng b --dev --output-path dist-dev and ng b --prod --output-path dist-prod. There is no need to have environments in dist, as this functionality already exists. If you don't want to type that command, just make some npm scripts.

@Meligy
Copy link
Contributor

Meligy commented Sep 20, 2016

At least lets have the root public/assets/resources/static folder back for the shown scenarios please.

@coryrylan
Copy link
Contributor Author

coryrylan commented Sep 20, 2016

@Meligy To get around the IIS issue (I am in the same situation) build your project into dist/build
source control dist except dist/build. Now you can put your web config at the root of dist but ignore generated code in build. Then to build you have to run ng build --watch -o dist/build. Update your web config rewrite rule to point to the index in dist/build.

@tomschreck
Copy link

@christiandreher - thanks for the tip. good to know

@Meligy
Copy link
Contributor

Meligy commented Sep 21, 2016

@splintercode I was planning on something like that until I realised: in this way I need a rewrite for the routes, and a rewrite for the script files and other assets. That won't work very well.

The script tags in the HTML will be root (dist) relative because the browser thinks the HTML is served from the root when the rewrite happens, the script tags now will match nothing because there's nothing in root (dist), so, I'll need to have them rewritten not to dist/build/ (default document being index.html), but to dist/build/{path}.

Which sounds OK, until you think about client routes, those should not go to dist/build/{path}. They should go to dist/build/ only (effectively dist/build/index.html as default document)

It then gets very complex, for something that I already had solved when the public folder was supported, because I didn't need to worry about relation to scripts in that scenario, they are matched as existing physical files, and my rewrites only worry about client routes.

@filipesilva filipesilva added type: enhancement P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent labels Sep 22, 2016
@filipesilva filipesilva self-assigned this Sep 22, 2016
@filipesilva
Copy link
Contributor

We realize that the change from public/ to src/assets meant that now there's no way to copy files to the root of the dist directory, and we're looking at alternatives for that.

The main motivations for src/assets were:

  • better support of upcoming multi-app setups by having a local folder instead of a global one
  • maintain reference integrity for editor tooling and just general making sense (e.g. referencing ./assets/img.png from ./src/styles.css exists, and the same if you want to reference something from index.html)

Point two presents a problem for any setup that copies stuff from a certain folder to the dist root.

There's a number of solutions that we're considering, but I don't have any to share at the moment since we haven't decided what avenue to take.

@peterennis
Copy link

@filipesilva also referenced this: #2232

@jjarrell50
Copy link

I was hosting bower references (polymer) into the public/bower_components
and referencing it from index.html with something like this


  <!--Polymer-->
  <script src="bower_components/webcomponentsjs/webcomponents.js"></script>

  <script>
    window.Polymer = window.Polymer || {};
    window.Polymer.dom = 'shadow';
  </script>

  <!--Polymer-->
  <link rel="import" href="bower_components/polymer/polymer.html">
  <link rel="import" href="bower_components/paper-styles/color.html">

So i tried to redirect the reference to assets/bower_components. it didn't
work, 404s. I'm thinking there is more to it than a directory rename and
would appreciate it if someone could confirm that. Perhaps, webpack has a
subtle change from it's former public behavior.

Can anybody confirm, that the move to assets is more than just a rename of
the folder?

@ghost
Copy link

ghost commented Sep 22, 2016

Why are you using bower? You shouldn't need it anymore. Use 'npm i --save polymer'

@jjarrell50
Copy link

@robertbaker - you got me encouraged for a moment, but the NPM polymer is not the polymer I'm referring to. The one I'm referring https://www.polymer-project.org/1.0/ which happens to be a google project. The docs all say it's bower. It's much farther along, today than Angular2 Material Design. At this point, I'm looking any solution, I'm thinking about serving these dependencies CDN style, at least until I can figure a way to include them in my build.

I'd generally expect support in angular-cli for polymer. They both come out of the googleverse after all.

@Meligy
Copy link
Contributor

Meligy commented Sep 22, 2016

@filipesilva would it be too bold to ask what are the major downsides of the following approach?

  • Bring back public folder into the root, same level as src
  • Add a key copyToOutput, pointing at "public"
  • Copy the folder to output with some Webpack copy plugin

I can think of a few questions you might ask

  • It might complex / confusing people
    You can avoid generating folder and key by default, and leave it as documented feature only
  • People might be greedy and ask for an array
    Shouldn't be a big difference though to implement or ignore
  • What if people want it in src, or even apps
    Since it's relative to root, people can still do that

Are there other concerns with this approach compared to other approaches? It's the closest one to the old approach, which is proven valuable by many comments here.

P.S.

Thanks a lot for all your own voluntary efforts in this free tool

@cheresier
Copy link

Another workaround for those who need to include web.config into the prod build, here is another workaround that works. I simply added an entry for it in the assets section of angular-cli.json
"assets": [
"assets",
"favicon.ico",
"Web.config"
]
Webpack will then copy it from src/app to the root of dist.

@ghost
Copy link

ghost commented Nov 19, 2016

Thats no workaroound, @cheresier, thats how it is intended to work after the update. The issue is old, back then it was not possible to do that.

@cheresier
Copy link

Oh, cool. Sorry, Looks like I got the wrong idea looking through the thread that we are looking for a solution equivalent to the /public folder.

@Nikkelmann
Copy link

Is there really no other way than typing every file into apps[0].assets?

Eg. when using http://realfavicongenerator.net to generate the favicon files you get ~10 files - thats a lot of clutter to have in the root folder. (Not including .htaccess or web.config and robots.txt)

@ghost
Copy link

ghost commented Mar 6, 2017

@Nikkelmann There is nothing stopping you from putting your favicons into assets/favicons and adding the favicon/browser meta tags in your index for it. That's what I do and works fine.

@Nikkelmann
Copy link

@robertbaker Sure, but the recommended way is to put the files in the root folder.

http://realfavicongenerator.net/faq

Why do you recommend to put all files at the root of the web site?
When generating a favicon with RealFaviconGenerator, the instructions ask you to place all files at the root of your web site. You may want to place them in a sub-directory, for example in http://mywebsite.com/icons/, just to make things clearer. However, there are three drawbacks with this approach:

  • Internet Explorer looks for favicon.ico at the root of the web site. Granted: this is because we ask you to not declare favicon.ico.
  • iOS devices look for files such as apple-touch-icon-144x144.png at the root of the web site, as described by Apple. This issue can be mitigated by declaring the icons in the HTML code (this is necessary for Android anyway), but following Apple conventions is probably the best move.
  • By default, Internet Explorer 11 looks for browserconfig.xml at the root of the web site.
    Several services, such as Yandex, look for favicon.ico in the root directory.

Why is favicon.ico not declared in the HTML code?
Looking for some sample favicon code, you've probably encountered:
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
When your favicon is in the root directory, RealFaviconGenerator does not generate this code. This is because it somehow confuses some other browsers like Chrome. And since IE looks for a file named favicon.ico anyway, the best solution is to not even talk about it. This is described by Jonathan T. Neal (http://www.jonathantneal.com/blog/understand-the-favicon/) and Mathias Bynens (http://mathiasbynens.be/notes/rel-shortcut-icon).

Really? But W3C says this is a bad thing!
Yes, W3C discourages the usage of a predefined URI. If you follow this recommandation, you will get into troubles with browsers which wrongly choose favicon.ico instead of the nice PNG versions gently prepared just for them. It is way better and pragmatic to trick them with this little hack.

mattxwang added a commit to weblue/wanna_b_tierlist that referenced this issue Apr 10, 2019
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet