Skip to content

Commit

Permalink
Include asset map file contents into index.html (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ruslan Zavacky committed Apr 2, 2017
1 parent 7023766 commit 35f48c0
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 28 deletions.
39 changes: 38 additions & 1 deletion README.md
Expand Up @@ -6,6 +6,17 @@
Inject fingerprinted assetMap.json file into your app and provide initializer, service, and helper to
dynamically reference fingerprinted assets.

**When to use this addon?**

1. If you have dynamic asset file names returned from API and/or you build paths based on several properties.
1. If you can't put your asset filemames into css or to have path as static in your .js files.
1. If you build your image/asset paths in a dynamic way, eg.
```js
imagePath: computed(function() {
return this.get('assetMap').resolve(`${this.get('image')}.png`);
})
```

## Installation

```bash
Expand All @@ -21,7 +32,8 @@ module.exports = function(environment) {
var ENV = {
...
ifa: {
enabled: true
enabled: true,
inline: false,
}
...
};
Expand Down Expand Up @@ -83,3 +95,28 @@ var app = new EmberApp(defaults, {
```
`/blog` will be prepended to the assetMap file path in the index.html.
### inline option
If `inline: true` is specified in config, contents of assetMap file will be inline into index.html.
```html
<script>
...

var __assetMapPlaceholder__ = {
"assets": {
"assets/assetMap.json": "assets/assetMap-0a0447ba419421fa257963a718324fa8.json",
"assets/failed.png": "assets/failed-836936cf32381ff14d191d7b10be9a89.png",
"assets/passed.png": "assets/passed-b8506cbc195c8b9db541745aee267c48.png",
"assets/tomster-under-construction.png": "assets/tomster-under-construction-da524c8bc9283f759ae640b68db81f24.png"
},
"prepend": ""
};
</script>

...
```
This might save one request to assetMap.json, but will increase overall size of `index.html` file, so use carefully.
40 changes: 25 additions & 15 deletions addon/initializers/asset-map.js
@@ -1,36 +1,46 @@
/* global window, __assetMapFilename__ */
/* global window, __assetMapPlaceholder__ */
import RSVP from 'rsvp';
import $ from 'jquery';
import AssetMap from '../services/asset-map';

export function initialize(app) {
app.deferReadiness();
let config = app.__container__.lookupFactory('config:environment');

let assetMapFile = window && window.__assetMapFilename__;
let assetMapFile = window && window.__assetMapPlaceholder__;

if (!assetMapFile) {
app.register('service:asset-map', AssetMap);
app.advanceReadiness();
return;
}

const promise = new RSVP.Promise((resolve, reject) => {
$.getJSON(assetMapFile, resolve).fail(reject);
});

promise.then((map = {}) => {
if (config.ifa.inline) {
AssetMap.reopen({
map: map.assets,
prepend: map.prepend,
map: assetMapFile.assets,
prepend: assetMapFile.prepend,
enabled: true
});
}).then(() => {
app.register('service:asset-map', AssetMap);
app.advanceReadiness();
});
} else {
app.deferReadiness();

const promise = new RSVP.Promise((resolve, reject) => {
$.getJSON(assetMapFile, resolve).fail(reject);
});

promise.then((map = {}) => {
AssetMap.reopen({
map: map.assets,
prepend: map.prepend,
enabled: true
});
}).then(() => {
app.register('service:asset-map', AssetMap);
app.advanceReadiness();
});
}
}

export default {
name: 'asset-map',
initialize: initialize
initialize
};
3 changes: 2 additions & 1 deletion config/environment.js
Expand Up @@ -4,7 +4,8 @@
module.exports = function(/* environment, appConfig */) {
return {
ifa: {
enabled: false
enabled: false,
inline: false
}
};
};
48 changes: 38 additions & 10 deletions index.js
Expand Up @@ -3,19 +3,40 @@

let fs = require('fs');

const findRoot = (current) => {
let app;

// Keep iterating upward until we don't have a grandparent.
// Has to do this grandparent check because at some point we hit the project.
do {
app = current.app || app;
} while (current.parent && current.parent.parent && (current = current.parent));

return app;
};

module.exports = {
name: 'ember-cli-ifa',

isDevelopingAddon: function() {
isDevelopingAddon() {
return false;
},

included: function(app) {
this.app = app;
included(app) {
this.app = findRoot(this);
this._super.included.apply(this, arguments);
},

postBuild: function (build) {
postBuild(build) {
this._super.included.apply(this, arguments);

const env = process.env.EMBER_ENV;
const ifaConfig = this.app.project.config(env).ifa;

if (!ifaConfig.enabled) {
return;
}

let fingerprintPrepend = '/';
let indexFilePath = build.directory + '/index.html';
let testIndexFilePath = build.directory + '/tests/index.html';
Expand Down Expand Up @@ -44,22 +65,29 @@ module.exports = {
fingerprintPrepend = this.app.options.fingerprint.prepend;
}

let assetMapContent = null;
let assetFileNamePath = `${build.directory}/assets/${assetFileName}`;

if (assetFileName) {
assetMapContent = `"${fingerprintPrepend + 'assets/' + assetFileName}"`;
let assetMapPlaceholder;

if (ifaConfig.inline && fs.existsSync(assetFileNamePath)) {
assetMapPlaceholder = fs.readFileSync(assetFileNamePath, {encoding: 'utf-8'});

} else {
if (assetFileName) {
assetMapPlaceholder = `"${fingerprintPrepend}assets/${assetFileName}"`;
}
}

fs.writeFileSync(indexFilePath, indexFile.replace(/__asset_map_placeholder__/, assetMapContent));
fs.writeFileSync(indexFilePath, indexFile.replace(/__asset_map_placeholder__/, assetMapPlaceholder));

if (testIndexFile) {
fs.writeFileSync(testIndexFilePath, testIndexFile.replace(/__asset_map_placeholder__/, assetMapContent));
fs.writeFileSync(testIndexFilePath, testIndexFile.replace(/__asset_map_placeholder__/, assetMapPlaceholder));
}
},

contentFor(type, config) {
if (type === 'head-footer' && config.ifa && config.ifa.enabled) {
return '<script>var __assetMapFilename__ = __asset_map_placeholder__;</script>';
return '<script>var __assetMapPlaceholder__ = __asset_map_placeholder__;</script>';
}
}
};
13 changes: 13 additions & 0 deletions tests/dummy/app/controllers/application.js
@@ -0,0 +1,13 @@
import Controller from 'ember-controller';
import service from 'ember-service/inject';
import computed from 'ember-computed';

export default Controller.extend({
assetMap: service(),

image: 'assets/tomster-under-construction',

imagePath: computed(function() {
return this.get('assetMap').resolve(`${this.get('image')}.png`);
}),
});
23 changes: 22 additions & 1 deletion tests/dummy/app/templates/application.hbs
@@ -1 +1,22 @@
<img src="assets/tomster-under-construction.png" />
<div style="display: flex; flex: 1 1 auto; align-items: center; justify-content: center;">
<div>
<img style="max-height: 150px;" src="assets/tomster-under-construction.png" />
<div style="display: flex; justify-content: center;">
Template replace
</div>
</div>

<div>
<img style="max-height: 150px;" src={{imagePath}} />
<div style="display: flex; justify-content: center;">
Asset Map Service
</div>
</div>

<div>
<img style="max-height: 150px;" src={{asset-map (concat image '.png')}} />
<div style="display: flex; justify-content: center;">
Asset Map Helper
</div>
</div>
</div>

0 comments on commit 35f48c0

Please sign in to comment.