You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I noticed that all assets are copied over to the dist directory. However even if we change the image in src/assets directory. The image wont be pulled in after release as name is the same.
It would be nice if during a release we update urls in css/html simply appending version number of sort in css such as:
url(assets/logo.png) -> url(assets/logo.png?123)
this would force the browser to download new image. Is this something we can do with cli ?
Thanks for the help
Reacted by adamdport, Eli Black and Rijin Elayambari
@Meligy what you have found in master is --output-hashing which is available as of beta.26 and apparently doesn't touch the assets directory and its content as per this.
@hansl@Meligy A year later, it looks like --output-hashing has no effect on anything in assets. The entire directory is just copied into the build folder without any means of cache invalidation. Should this be reopened?
Assets are intended to be copied verbatim with no additional processing. That is their defining characteristic.
The test above is also turning the ./assets/image.png file into a resource (used by a global stylesheet). Resources, in contrast to assets, are processed by the system and will be potentially inlined, optimized, and/or hashed depending on the options provided. In practice, an application would generally not have an file be both an asset and a resource as this would cause the file to be present twice within the build output. Once as a directly copied asset and once as a processed resource.
Thanks for the article @clydin. I totally agree that correct cache configuration on the server is important for ensuring browsers treat cached assets correctly. However, a common strategy to ensure the browser immediately requests a new version when an asset has changed is to use unique names for assets based on their contents. The article you linked specifically calls this out:
How do you get the best of both worlds: client-side caching and quick updates? You change the URL of the resource and force the user to download the new response whenever its content changes. Typically, you do this by embedding a fingerprint of the file, or a version number, in its filename—for example, style.x234dff.css.
With the behaviour of angular just copying the assets with no processing, no hash is generated for these assets, making it not possible to achieve this, and it was this I was hoping you had advice on.
@jeffora Further in that same section, the example specifically using an image (as a token asset example) without a unique hash in the file name. max-age combined with ETags are highly effective for image/video/etc. assets.
Sure, for a photo that rarely or never changes, where the user experience will not change with an out of date image. However, if the asset is an SVG for a menu item, or something that should be considered part of a single "deployment", there is no way to make sure a new version of the app will reference the latest version of the asset.
Another issue is that as assets are not processed at all, they do not follow the --deploy-url semantics, so if all assets are uploaded to a CDN at a different domain name, the image assets maintain their relative paths to the host domain.
In that case, you have several options. Three of which are to either set the image to no-cache (like the index) and ensure Etags are being used; with HTTP/2 there is no reconnection overhead. Or if the SVG is small, inline it in the template HTML. Or use a CSS background image; which has numerous advantages over an HTML img element (e.g., transformations, animations, etc.).
As to the second aspect, base HREF would be the preferred option in that scenario. There is rarely a reason to use deploy URL over base HREF.
Ok thanks for the discussion. It sounds like there is no out of the box support via the angular cli, so I'll look into 6+ builder pack options to customise it ourselves.
Base href is not really appropriate for this use case, as that tells the browser that all relative URLs on the page should be interpreted as relative to the base href, which is not the behaviour we're after. We serve the site (index.html) from one domain, e.g. site.example.com, and all relative URLs should be relative to that domain (e.g. relative AJAX calls to site.example.com/someapi). All JS/CSS/image assets are uploaded to a CDN hosted at a different domain, e.g. cdn.example-static.net, for a variety of reasons - one of these being that this prevents the browser from sending unnecessary cookies to the server when retrieving static assets.
The other options suggested might work for specific cases, but they all feel like workarounds - surely there is a valid (and possibly common) use case where static assets that are not JS / CSS should be processed through the same content pipeline as JS / CSS. This is fully supported by webpack, so it would be nice to have an easy way to opt in to this functionality in angular.
With HTTP/2’s header compression, the entire cookie can be encoded in 1 to 2 bytes for repeat requests. There’s no need for a complex setup if cookie request elimination is the primary goal.
angular-automatic-lock-bot commented on Sep 9, 2019
Activity
Meligy commentedon Jan 13, 2017
There's something in master not yet released.
A new flag for
ng buildthat's calledoutput-hashing. It takes one of the following values:none,all,media,bundles.I suspect you can try setting it to
allwhenever the next version is released.P.S.
Reference: #3885
un33k commentedon Jan 24, 2017
@Meligy what you have found in master is
--output-hashingwhich is available as of beta.26 and apparently doesn't touch the assets directory and its content as per this.adamdport commentedon Jan 26, 2018
@hansl @Meligy A year later, it looks like
--output-hashinghas no effect on anything inassets. The entire directory is just copied into the build folder without any means of cache invalidation. Should this be reopened?macleanpinto commentedon Apr 10, 2018
@hansl @Meligy
ng build --env=prod --output-hashing=all
The entire directory is copied into the build folder. According to the build tests https://github.com/angular/angular-cli/blob/master/tests/e2e/tests/build/output-hashing.ts
export default function() {
return Promise.resolve()
.then(() => writeMultipleFiles({
'src/styles.css': 'body { background-image: url("./assets/image.png"); }'
}))
// use image with file size >10KB to prevent inlining
.then(() => copyProjectAsset('images/spectrum.png', './src/assets/image.png'))
.then(() => ng('build', '--output-hashing=all'))
.then(() => expectFileToMatch('dist/test-project/index.html', /runtime.[0-9a-f]{20}.js/))
.then(() => expectFileToMatch('dist/test-project/index.html', /main.[0-9a-f]{20}.js/))
.then(() => expectFileToMatch('dist/test-project/index.html', /styles.[0-9a-f]{20}.(css|js)/))
.then(() => verifyMedia(/styles.[0-9a-f]{20}.(css|js)/, /image.[0-9a-f]{20}.png/))
The defect needs to be reopened.
clydin commentedon Apr 10, 2018
Assets are intended to be copied verbatim with no additional processing. That is their defining characteristic.
The test above is also turning the
./assets/image.pngfile into a resource (used by a global stylesheet). Resources, in contrast to assets, are processed by the system and will be potentially inlined, optimized, and/or hashed depending on the options provided. In practice, an application would generally not have an file be both an asset and a resource as this would cause the file to be present twice within the build output. Once as a directly copied asset and once as a processed resource.macleanpinto commentedon Apr 10, 2018
are the files mentioned as assets in angular-cli.json
I18n contains 2 files
I am using them for translations.
These files are cached. As per the documention
must add hashing to all files, irrespective of contents in assets.
adamdport commentedon Apr 10, 2018
My team ended up appending a timestamp of the release onto our assets, eg.
en.json?v=123456.@clydin If assets were intentionally not hashed, what is the suggested approach for invalidating cache of assets?
jeffora commentedon Nov 19, 2018
@clydin I would also love to know what the recommended practice is for this
clydin commentedon Nov 21, 2018
Please see the following for recommended practices. Note that server configuration is a critical element to an effective caching strategy.
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching
jeffora commentedon Nov 21, 2018
Thanks for the article @clydin. I totally agree that correct cache configuration on the server is important for ensuring browsers treat cached assets correctly. However, a common strategy to ensure the browser immediately requests a new version when an asset has changed is to use unique names for assets based on their contents. The article you linked specifically calls this out:
With the behaviour of angular just copying the assets with no processing, no hash is generated for these assets, making it not possible to achieve this, and it was this I was hoping you had advice on.
clydin commentedon Nov 21, 2018
@jeffora Further in that same section, the example specifically using an image (as a token asset example) without a unique hash in the file name.
max-agecombined with ETags are highly effective for image/video/etc. assets.jeffora commentedon Nov 22, 2018
Sure, for a photo that rarely or never changes, where the user experience will not change with an out of date image. However, if the asset is an SVG for a menu item, or something that should be considered part of a single "deployment", there is no way to make sure a new version of the app will reference the latest version of the asset.
Another issue is that as assets are not processed at all, they do not follow the
--deploy-urlsemantics, so if all assets are uploaded to a CDN at a different domain name, the image assets maintain their relative paths to the host domain.clydin commentedon Nov 22, 2018
In that case, you have several options. Three of which are to either set the image to no-cache (like the index) and ensure Etags are being used; with HTTP/2 there is no reconnection overhead. Or if the SVG is small, inline it in the template HTML. Or use a CSS background image; which has numerous advantages over an HTML img element (e.g., transformations, animations, etc.).
As to the second aspect, base HREF would be the preferred option in that scenario. There is rarely a reason to use deploy URL over base HREF.
jeffora commentedon Nov 22, 2018
Ok thanks for the discussion. It sounds like there is no out of the box support via the angular cli, so I'll look into 6+ builder pack options to customise it ourselves.
Base href is not really appropriate for this use case, as that tells the browser that all relative URLs on the page should be interpreted as relative to the base href, which is not the behaviour we're after. We serve the site (index.html) from one domain, e.g.
site.example.com, and all relative URLs should be relative to that domain (e.g. relative AJAX calls tosite.example.com/someapi). All JS/CSS/image assets are uploaded to a CDN hosted at a different domain, e.g.cdn.example-static.net, for a variety of reasons - one of these being that this prevents the browser from sending unnecessary cookies to the server when retrieving static assets.The other options suggested might work for specific cases, but they all feel like workarounds - surely there is a valid (and possibly common) use case where static assets that are not JS / CSS should be processed through the same content pipeline as JS / CSS. This is fully supported by webpack, so it would be nice to have an easy way to opt in to this functionality in angular.
clydin commentedon Nov 22, 2018
With HTTP/2’s header compression, the entire cookie can be encoded in 1 to 2 bytes for repeat requests. There’s no need for a complex setup if cookie request elimination is the primary goal.
angular-automatic-lock-bot commentedon Sep 9, 2019
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.