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

Use HTML meta to store asset map information #40

Merged
merged 2 commits into from
Oct 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 1 addition & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,24 +127,6 @@ var app = new EmberApp(defaults, {

### 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>

...
```
If `inline: true` is specified in config, contents of assetMap file will be inline into index.html.

This might save one request to assetMap.json, but will increase overall size of `index.html` file, so use carefully.
5 changes: 1 addition & 4 deletions addon/initializers/asset-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import getAssetMapData from 'ember-cli-ifa/utils/get-asset-map-data';
export function initialize(app) {
let assetMapFile = getAssetMapData();

// This is split out like this, in order to prevent this from being accidentally replaced
let replacementPath = ['__', 'asset_map_placeholder', '__'].join('');

if (!assetMapFile || assetMapFile === replacementPath) {
if (!assetMapFile) {
app.register('service:asset-map', AssetMap);
return;
}
Expand Down
8 changes: 6 additions & 2 deletions addon/utils/get-asset-map-data.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
export default function getAssetMapData() {
// This placeholder is replaced in the build step
return '__asset_map_placeholder__';
const assetMapString = document.querySelector("meta[name='ember-cli-ifa:assetMap']").content;
if (!assetMapString) {
return;
}

return JSON.parse(decodeURIComponent(assetMapString));
}
65 changes: 28 additions & 37 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
'use strict';

let fs = require('fs');
let path = require('path');
const fs = require('fs');
const path = require('path');

const MetaPlaceholder = '__ember-cli-ifa__AssetMapPlaceholder__';

function replacePlaceholder(filePath, assetMap) {
const assetMapString = encodeURIComponent(JSON.stringify(assetMap));
const fileBody = fs.readFileSync(filePath, { encoding: 'utf-8' });
fs.writeFileSync(filePath, fileBody.replace(MetaPlaceholder, assetMapString));
}

module.exports = {
name: 'ember-cli-ifa',
Expand All @@ -10,21 +18,19 @@ module.exports = {
return false;
},

included(app) {
this._super.included.apply(this, arguments);

// You could overwrite the path to replace the placeholder in
// By default, it looks for a `vendor.js` or `vendor-XXXXX.js` file
// It looks for that file in the `/assets` folder
let options = app.options['ember-cli-ifa'] || {};
this._replacePathRegex = options.replacePathRegex || /^vendor(-(\w|\d)*)?\.js$/i;
},

treeForFastBoot: function(tree) {
treeForFastBoot(tree) {
this._isFastBoot = true;
return tree;
},

contentFor(type) {
if (type !== 'head') {
return;
}

return `<meta name="ember-cli-ifa:assetMap" content="${MetaPlaceholder}">`;
},

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

Expand All @@ -37,8 +43,8 @@ module.exports = {

let fingerprintPrepend = '/';

let files = fs.readdirSync(path.join(build.directory, 'assets'));
let totalFiles = files.length;
const files = fs.readdirSync(path.join(build.directory, 'assets'));
const totalFiles = files.length;

let assetFileName = null;
for (let i = 0; i < totalFiles; i++) {
Expand All @@ -48,44 +54,29 @@ module.exports = {
}
}

let replacePathRegex = this._replacePathRegex;
let vendorJsFileName = null;
for (let i = 0; i < totalFiles; i++) {
if (files[i].match(replacePathRegex)) {
vendorJsFileName = files[i];
break;
}
}

let vendorJsFilePath = path.join(build.directory, 'assets', vendorJsFileName);
let vendorJsFile = fs.readFileSync(vendorJsFilePath, { encoding: 'utf-8' });

// Prepend the URL of the assetMap with the location defined in fingerprint
// options.
if (this.app && this.app.options && this.app.options.fingerprint) {
fingerprintPrepend = this.app.options.fingerprint.prepend;
}

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

let assetMapPlaceholder;
const assetFileNamePath = `${build.directory}/assets/${assetFileName}`;

// When using fastboot, always use the inline form
// As ajax is not so easily possible there
if (!ifaConfig.inline && this._isFastBoot) {
this.ui.writeLine('When running fastboot, ember-cli-ifa is forced into inline mode.');
}
let inline = ifaConfig.inline || this._isFastBoot;
const inline = ifaConfig.inline || this._isFastBoot;

let assetMap;
if (inline && fs.existsSync(assetFileNamePath)) {
assetMapPlaceholder = fs.readFileSync(assetFileNamePath, { encoding: 'utf-8' });
assetMapPlaceholder = JSON.stringify(JSON.parse(assetMapPlaceholder));
assetMap = JSON.parse(fs.readFileSync(assetFileNamePath, { encoding: 'utf-8' }));
} else if (assetFileName) {
assetMapPlaceholder = `"${fingerprintPrepend}assets/${assetFileName}"`;
assetMap = `${fingerprintPrepend}assets/${assetFileName}`;
}

// When minifiying, '__asset_map_placeholder__' may be re-written into "__asset_map_placeholder__"
// So we need to replace both variants
fs.writeFileSync(vendorJsFilePath, vendorJsFile.replace(/('|")(__asset_map_placeholder__)('|")/, assetMapPlaceholder));
replacePlaceholder(path.join(build.directory, 'index.html'), assetMap);
replacePlaceholder(path.join(build.directory, 'tests/index.html'), assetMap);
}
};