Skip to content

Commit

Permalink
Create ManifestGenerator base class
Browse files Browse the repository at this point in the history
  • Loading branch information
Trent Willis committed Jul 29, 2016
1 parent 46455f1 commit 8843321
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 85 deletions.
46 changes: 24 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,42 @@ Provides experimental support for the [Asset Manifest RFC](https://github.com/em

Ember Asset Loader does three primary things:

1. Allows you to generate an Asset Manifest,
1. Provides a base class to easily generate an Asset Manifest,
2. Provides an Ember service to use the generated manifest at runtime, and
3. Initializes the above service with the above generated manifest.

### Generating an Asset Manifest

Generating a manifest is straightforward. Simply import the `generateAssetManifest` from `ember-asset-loader/lib/generate-asset-manifest` during `postprocessTree`:
You can generate an Asset Manifest by creating either a standalone or in-repo addon which extends from the
`ManifestGenerator` base class:

```js
postprocessTree: function(type, tree) {
if (type === 'all') {
var generateAssetManifest = require('ember-asset-loader/lib/generate-asset-manifest');
return generateAssetManifest(tree, {
supportedTypes: [ 'js', 'css' ],
bundlesLocation: 'engine-dist'
});
var ManifestGenerator = require('ember-asset-loader/lib/manifest-generator');
module.exports = ManifestGenerator.extend({
name: 'asset-generator-addon',
manifestOptions: {
bundlesLocation: 'engines-dist',
supportedTypes: [ 'js', 'css' ]
}

return tree;
}
});
```

The `generateAssetManifest` function will generate an asset manifest and merge it back into the provided tree. It can
also take in an option hash with the following supported fields:
The `ManifestGenerator` will generate an asset manifest and merge it into your build tree during post-processing. It
generates the manifest according to the options specified in `manifestOptions`:

* The `bundlesLocation` option is a string that specifies which directory in the build tree contains the bundles to be
placed into the asset manifest. This defaults `bundles`.

* The `bundlesLocation` option is a string that specifies which directory in the tree contains the bundles to be placed
into the asset manifest. This defaults `bundles`.
* The `supportedTypes` option is an array that specifies which types of files should be included into the bundles for
the asset manifest. This defaults to `[ 'js', 'css' ]`.

* The `supportedTypes` option is an array that specifies which types of files should be included into the bundles for the
asset manifest. This defaults to `[ 'js', 'css' ]`.
_Note: This class provides default `contentFor`, `postprocessTree`, and `postBuild` hooks so be sure that you call
`_super` if you override one of those methods._

### Why isn't a manifest generated by default?

No manifest is generated by default since there is no convention for bundling assets within Ember currently. Thus, to
prevent introducing unintuitive or conflicting behavior, we provide no default generation.

If no manifest is generated, you'll get a warning at build time to ensure that you understand no manifest has been
generated and thus you'll have to provide a manifest manually in order to use the Asset Loader Service. This warning can
Expand All @@ -52,10 +58,6 @@ var app = new EmberApp(defaults, {
});
```

### Why isn't a manifest generated by default?

No manifest is generated by default since there is no convention for bundling assets within Ember currently. Thus, to prevent introducing unintuitive or conflicting behavior, we provide no default generation.

## Installation

* `git clone https://github.com/trentmwillis/ember-asset-loader`
Expand Down
52 changes: 1 addition & 51 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,6 @@
/* jshint node: true */
'use strict';

var path = require('path');
var fs = require('fs-extra');

module.exports = {
name: 'ember-asset-loader',

/**
* Insert a meta tag to hold the manifest in the DOM. We won't insert the
* manifest until after postprocessing so the content is a placeholder value.
*/
contentFor: function(type, config) {
var options = this.app && this.app.options && this.app.options.assetLoader;
if (type === 'head-footer' && !(options && options.noManifest)) {
var metaName = config.modulePrefix + '/asset-manifest';
return '<meta name="' + metaName + '" content="%GENERATED_ASSET_MANIFEST%" />';
}
},

/**
* Replace the manifest placeholder with an escaped version of the manifest.
* We do this in both the app's index and test's index.
*/
postBuild: function(result) {
var options = this.app && this.app.options && this.app.options.assetLoader;
if (options && options.noManifest) {
return;
}

var manifestFile = path.join(result.directory, 'asset-manifest.json');
var manifest;

try {
manifest = fs.readJsonSync(manifestFile);
} catch (error) {
console.warn('\n\nWarning: Unable to read asset-manifest.json from build with error: ' + error)
console.warn('Warning: Proceeding without generated manifest; you will need to manually provide a manifest to the Asset Loader Service to load bundles at runtime. If this was intentional you can turn this message off via the `noManifest` flag.\n\n');
manifest = { bundles: {} };
}

var escapedManifest = escape(JSON.stringify(manifest));

var indexFilePath = path.join(result.directory, 'index.html');
this.replaceAssetManifestPlaceholder(indexFilePath, escapedManifest);

var testsIndexFilePath = path.join(result.directory, 'tests/index.html')
this.replaceAssetManifestPlaceholder(testsIndexFilePath, escapedManifest);
},

replaceAssetManifestPlaceholder: function(filePath, manifest) {
var resolvedFile = fs.readFileSync(filePath, { encoding: 'utf8' });
fs.outputFileSync(filePath, resolvedFile.replace(/%GENERATED_ASSET_MANIFEST%/, manifest));
}
name: 'ember-asset-loader'
};
63 changes: 63 additions & 0 deletions lib/manifest-generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
var path = require('path');
var fs = require('fs-extra');
var Addon = require('ember-cli/lib/models/addon');

var ManifestGenerator = Addon.extend({
/**
* Insert a meta tag to hold the manifest in the DOM. We won't insert the
* manifest until after postprocessing so the content is a placeholder value.
*/
contentFor: function(type, config) {
var options = this.app && this.app.options && this.app.options.assetLoader;
if (type === 'head-footer' && !(options && options.noManifest)) {
var metaName = config.modulePrefix + '/asset-manifest';
return '<meta name="' + metaName + '" content="%GENERATED_ASSET_MANIFEST%" />';
}
},

postprocessTree: function(type, tree) {
if (type === 'all') {
var generateAssetManifest = require('./generate-asset-manifest'); // eslint-disable-line global-require
return generateAssetManifest(tree, this.manifestOptions);
}

return tree;
},

/**
* Replace the manifest placeholder with an escaped version of the manifest.
* We do this in both the app's index and test's index.
*/
postBuild: function(result) {
var options = this.app && this.app.options && this.app.options.assetLoader;
if (options && options.noManifest) {
return;
}

var manifestFile = path.join(result.directory, 'asset-manifest.json');
var manifest;

try {
manifest = fs.readJsonSync(manifestFile);
} catch (error) {
console.warn('\n\nWarning: Unable to read asset-manifest.json from build with error: ' + error)
console.warn('Warning: Proceeding without generated manifest; you will need to manually provide a manifest to the Asset Loader Service to load bundles at runtime. If this was intentional you can turn this message off via the `noManifest` flag.\n\n');
manifest = { bundles: {} };
}

var escapedManifest = escape(JSON.stringify(manifest));

var indexFilePath = path.join(result.directory, 'index.html');
this.replaceAssetManifestPlaceholder(indexFilePath, escapedManifest);

var testsIndexFilePath = path.join(result.directory, 'tests/index.html')
this.replaceAssetManifestPlaceholder(testsIndexFilePath, escapedManifest);
},

replaceAssetManifestPlaceholder: function(filePath, manifest) {
var resolvedFile = fs.readFileSync(filePath, { encoding: 'utf8' });
fs.outputFileSync(filePath, resolvedFile.replace(/%GENERATED_ASSET_MANIFEST%/, manifest));
}
});

module.exports = ManifestGenerator;
19 changes: 7 additions & 12 deletions tests/dummy/lib/test-generator-plugin/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
/*jshint node:true*/
module.exports = {
name: 'test-generator-plugin',
var ManifestGenerator = require('../../../../lib/manifest-generator');

postprocessTree: function(type, tree) {
if (type === 'all') {
var generateAssetManifest = require('../../../../lib/generate-asset-manifest');
return generateAssetManifest(tree, {
bundlesLocation: 'test-dist',
supportedTypes: [ 'js', 'css' ]
});
}
module.exports = ManifestGenerator.extend({
name: 'test-generator-plugin',

return tree;
manifestOptions: {
bundlesLocation: 'test-dist',
supportedTypes: [ 'js', 'css' ]
}
};
});

0 comments on commit 8843321

Please sign in to comment.