Comments (37)
@devinrhode2 I wrote an article about fingerprinting - https://medium.com/@ruslanzavacky/ember-cli-fingerprinting-and-dynamic-assets-797a298d8dc6 and also created a relevant addon that helps to solve fingerprinting issues - https://github.com/RuslanZavacky/ember-cli-ifa. Its still not ideal, but at least its doing it from the "box".
from broccoli-asset-rev.
I'm not sure if this will work in an ember app, but here is what I do with handlebars on my server side app. I have a helper like this:
var handlebars = require('handlebars');
var assetMap = require('../../dist/assets/assetMap.json');
var prepend = assetMap.prepend || '/';
handlebars.registerHelper('asset', function (asset) {
return prepend + assetMap.assets[asset];
});
And then in a handlebars template, I can access the asset via:
<link rel="stylesheet" href="{{asset 'path/to/filename.css'}}">
Perhaps you can use the assetMap.json
in some way to look up the filename at runtime.
from broccoli-asset-rev.
I stumbled over the same problem. The workaround I've used now is async loading the assetMap.json and injecting a dependency in an initializer. It provides an assets.resolve(localPath)
function.
import Ember from 'ember';
export function initialize(container, application) {
application.deferReadiness();
var AssetMap = Ember.Object.extend();
var promise = new Ember.RSVP.Promise(function(resolve, reject) {
Ember.$.getJSON('assets/assetMap.json', resolve).fail(reject);
});
promise.then(function(assetMap) {
AssetMap.reopen({
assetMap: assetMap,
resolve: function(name) {
return assetMap.assets[name];
}
});
}, function() {
AssetMap.reopen({
resolve: function(name) {
return name;
}
});
}).then(function() {
container.register('assetMap:main', AssetMap, {singleton: true});
application.inject('component', 'assets', 'assetMap:main');
application.advanceReadiness();
});
}
export default {
name: 'asset-map',
initialize: initialize
};
This can then be used with this.assets.resolve('img/posters/' + this.get('id') + '.jpeg')
. Hope this helps someone else.
from broccoli-asset-rev.
There is some discussion over here. Unfortunately, it is not at all easy to come up with a working solution. In fact, we had to go through several iterations to have a real bug-free solution.
you'll want the
fingerprint: {
...
generateAssetMap: true,
fingerprintAssetMap: true
},
option, so your asset map is generated (and uploaded), and so it's fingerprinted as well (otherwise a client might retrieve an outdated asset map from the cache!).
Then, in your code you can retrieve the asset map via assets/assetMap.json
. Ember CLI will automatically replace this string with the correct URL to the fingerprinted asset map in the production build. Then follow a similar procedure as outlined here (ignore the ENV.APP.CDN_PATH part, this turned out not to work exactly because the asset map is cached by the cliented; instead just use the assets/assetMap.json
string and let Ember CLI replace it with the correct URL).
from broccoli-asset-rev.
Sounds like there is no real resolution to this still.
Dynamic URLs are a huge part of large, production systems. We can implement the workarounds, but I would suggest this must be on a high priority of fixes for your next release (please!)
from broccoli-asset-rev.
Can you clarify your use case some more. You have an image name stored in the database, but the asset is stored in your application code?
from broccoli-asset-rev.
The logo property stores a relative asset URL like "/assets/images/bar-23.jpg" and that actual file is in my public/assets/images folder of my ember-cli app, which gets output to the dist folder with the fingerprints added.
If there's a better way to achieve what I'm trying to do (allowing users to modify the bars logo) I'm all ears. I'm still early on in the development process.
Thanks.
from broccoli-asset-rev.
I'm also building an ember project and am running into a similar issue. In a handlebars template, I bind the src attribute of an image to some string which I calculate in one of my Ember controllers. However, when I have fingerprinting/prepending enabled, these paths are not updated and the images are subsequently broken.
from broccoli-asset-rev.
I may be able to get around this by defining the CDN path in an environmental variable, but it would be nice if we could do fingerprinting too.
from broccoli-asset-rev.
Have you tried reading the assetMap as I described above? I think that may solve your problem.
from broccoli-asset-rev.
Unless I'm missing something, an asset map isn't produced in ember-cli (or at least it doesn't appear in dist/assets after build).
from broccoli-asset-rev.
Try passing generateAssetMap: true
in as one of the options.
from broccoli-asset-rev.
Will give it a go. If it works I'll report back to the ember-cli folks :)
from broccoli-asset-rev.
Adding generateAssetMap: true in the proper place in my Brocfile did produce the asset map. However, in ember-cli I don't think I can we can use helpers the way you use them. We'd have to use {{bind-attr href=something}}
.
from broccoli-asset-rev.
Could you bind the attribute to a variable, which you can then create in your controller that reads in the asset map?
from broccoli-asset-rev.
That could work. I'll try creating a Mixin in Ember that incorporates your idea so we can update dynamic paths created inside controllers, etc.
from broccoli-asset-rev.
I can't seem to be able to access/import/require the assetMap in a controller, perhaps it's not created yet? Can ping the ember-cli folks too to see if they have ideas.
from broccoli-asset-rev.
Can you post an example of what you are trying to accomplish? How you generate the URLs and how you use it in a template
from broccoli-asset-rev.
So in my project I'm working on generating paths for movie posters. So, for example, I may have something like this in a controller:
posterURL: function() {
var prefix = config.environment === 'staging' ? config.cdnPath : '';
return prefix + 'img/posters/' + this.get('id') + '.jpeg';
}.property('id'),
I pull a CDN prefix from my environmental settings, but this doesn't do anything regarding hashes. Then I basically use the id of the movie from my current model and build the path from that.
Then, in my corresponding template, I have something like this:
<img {{bind-attr src=posterURL}} />
from broccoli-asset-rev.
@rwjblue Do you have any ideas on the best approach to solve this problem?
from broccoli-asset-rev.
This is a bit of a workaround, but you could use the customHash
option instead of the default md5 hashes for the fingerprint. Then, because you know what to expect for the custom hash, you can build that assumption into your computed property:
return prefix + 'img/posters/' + this.get('id') + '-' + myCustomHash + '.jpeg';
For a custom hash, I use the current git commit SHA. It's predictable (you can look it up), and will change every time you deploy so the cache still gets broken.
from broccoli-asset-rev.
I'm going to close this for now. If you still are having trouble with this, please let me know.
from broccoli-asset-rev.
Hi everyone, I'm new to Ember here ... Can't see assetMap.json file on my project neither in my dist folder. Any ideas of how to achieve this in ember-cli ?
from broccoli-asset-rev.
Use generateAssetMap
as shown in the readme https://github.com/rickharrison/broccoli-asset-rev
from broccoli-asset-rev.
We're running into a similar issue. For our application, we're generating dynamic images from a helper and then injecting the correct one into a couple templates.
The use-case is pretty simple. We're checking the type of credit card a user has on file with us, then we're generating a path to the correct image asset (in our public folder) to display next to the card at checkout and in a user's settings.
Due to fingerprinting, our app is unable to find the asset path since we're generating the path outside our templates and stylesheets.We have a workaround for now however it'd be nice if we could fingerprint images from files outside our templates & stylesheets.
from broccoli-asset-rev.
@mksplg +1
How would I register a HTMLBars helper which would do the same for me but in the templates?
{{asset-resolve 'name-of-asset'}}
from broccoli-asset-rev.
@mksplg did you find a way to get the assetMap at compile-time?
My use-case is with ember-cli-deploy, which sends all the assets to (e.g.) S3, and only index.html
to your server, so there's no simple access to assetMap.json
(deployment will send it fingerprinted to S3). I stumbled upon ember-cli-inject-asset-map but there might be some cleanup to do there.
from broccoli-asset-rev.
This is my helper asset-resolve
import Ember from 'ember';
export function assetResolve(asset) {
var fn = Ember.container.lookup('assetMap:main');
var res = asset;
if (fn) {
var a = fn(asset);
if (a) { res = a; }
}
return res;
}
export default Ember.Helper.helper(assetResolve);
from broccoli-asset-rev.
I have chosen a slightly different solution. I have a config/cdn.json
file, and then I just read it in two places. I also use this package to read the current commit SHA and use it as a fingerprint:
// ember-cli-build.js
var cdnConfig = JSON.parse(require('fs').readFileSync('config/cdn.json'));
var cdnPath = cdnConfig[process.env.EMBER_ENV];
var isProductionLikeBuild = ... // check if production or staging or something
var app = new EmberApp(defaults, {
fingerprint: {
prepend: cdnPath,
enable: isProductionLikeBuild,
customHash: require('git-rev-sync').long()
})
// config/environment.js
var cdnConfig = JSON.parse(require('fs').readFileSync('config/cdn.json'));
ENV.APP.CDN_PATH = cdnConfig[process.env.EMBER_ENV];
ENV.APP.FINGERPRINT = require('git-rev-sync').long();
Yes, that duplicates the part of reading the file, but the stuff that is actually more likely to change, the paths themselves, are stored in one location.
With this, I can build a simple util:
import ENV from 'my-app/config/environment';
export function assetPath(asset, extension) {
return `${ENV.APP.CDN_PATH}assets/${asset}-${ENV.APP.FINGERPRINT}.${extension}`;
}
from broccoli-asset-rev.
@Fryie so you don't use fingerprinting? But just pre-pending URL? How you deal with client side assets caching?
from broccoli-asset-rev.
I do, I just excluded it from this example because it depends on a
"isProductionLikeBuild" variable. edit: updated example
from broccoli-asset-rev.
Oh I see what you mean now. Yeah, with fingerprinting you'd also need the specific asset fingerprint, so that solution won't work. I totally missed that.
from broccoli-asset-rev.
you could specify a custom fingerprint hash: http://www.ember-cli.com/user-guide/#asset-compilation
that could be the git commit, for example
edit: updated my example above with that
from broccoli-asset-rev.
@wehlutyk I am doing the same thing with ember-cli-deploy. Did you find a solution?
from broccoli-asset-rev.
@seawatts unfortunately nothing implemented yet. I think the way to go is what's explained as option 2 in this comment, but I haven't had the time to implement it. My next free slot to do it is in a month or two (but I won't make any promises -- if you know how to do it feel free :) ).
(In the meantime, since I only have 4 dynamic url assets, whenever they change I build once, then copy those particular fingerprints by hand from assetMap.json
into my app code, then build again.)
from broccoli-asset-rev.
Also encountered this issue. I have image names coded directly into a plain javascript file that provides some data for the ui (app/ui-data.js), but I dynamically create the full paths for each url in my ui-data object. Just hard coding the full asset paths, and removing my code dynamically creates them, fixes the issue for me.
The full path makes broccoli-asset-rev recognize them and rewrites them, apparently in any source file anywhere in the ember app.
from broccoli-asset-rev.
@carrotalan you can easily use an addon that I've provided. Works well and for large production systems :) And if it does not satisfy you, author of this repo will likely be happy to get contributions that will solve the issue that you've described :)
from broccoli-asset-rev.
Related Issues (20)
- Fingerprint prepend mysteriously added in wrong place in ONE file only HOT 1
- Support adding to the default fingerprinted extensions HOT 2
- Generate CSS/JS file hash after replacing fingerprinted asset paths HOT 12
- Is it possible to generate assetMap.json in development? HOT 1
- Multiple fingerprinted assetMap.json files with v2.6.0 HOT 5
- [Question] How can I use fingerprint for svg file inside my addon? HOT 2
- Breaks when html files don't contain html
- assetMap keys mysteriously also end up fingerprinted HOT 1
- 3.0.0 no tag at GitHub HOT 3
- how to custom sourcemap filename HOT 1
- Dynamically added assets prefix in the image URL - Ember-CLI HOT 2
- Add maintainers
- Dynamic URLs in JS don't get rewritten (rootURL case) HOT 1
- Ability to skip particular references HOT 1
- assetMap.json replacement is wrong HOT 1
- Add asset map to the bundle as a JS module, so that it can be accessed programmatically without extra network requests HOT 1
- Transfer to ember-cli org? HOT 2
- Template Literals + `prepend` doesn't work correctly and results in invalid JS build HOT 1
- release new version with updated deps
- version published to npm (3.0) does not exist in the codebase
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from broccoli-asset-rev.