I have an addon which needs to copy a set of JS files from their bower directory to the Ember app's root of /dist (this is for scoping rules associated with service workers). I thought maybe I could use the treeForApp hook but while I'm getting no errors I'm also not getting the desired result.
The index.js is:
const Funnel = require('broccoli-funnel');
module.exports = {
name: 'ember-upup',
treeForApp: function(tree) {
tree = new Funnel(tree, { include:
[
'bower_components/upup/dist/upup.min.js',
'bower_components/upup/dist/upup.sw.min.js'
]});
return this._super.treeForApp.call(this, tree);
},
Note: I thought I might be able to solve this problem by simply copying the javascript files as part of index.js postBuild hook but while this DOES put the JS files into the dist folder's root it is not served by ember-cli's ember serve apparently if not pushed through one of it's build pipelines.
Stefan Penner has now pointed out the the dist directory is for developers to look at but serving is actually done within the tmp directory structure ... this explains why my "hack" didn't work.
It looks like my initial attempt wasn't entirely far off. To make it work you need to hook into the treeForPublic hook like so:
const path = require('path');
const Funnel = require('broccoli-funnel');
const mergeTrees = require('broccoli-merge-trees');
const JS_FILES = ['upup.min.js', 'upup.sw.min.js'];
module.exports = {
treeForPublic: function() {
const upupPath = path.join(this.app.bowerDirectory, 'upup/dist');
const publicTree = this._super.treeForPublic.apply(this, arguments);
const trees = [];
if (publicTree) {
trees.push(publicTree);
}
trees.push(new Funnel(upupPath, {
include: JS_FILES,
destDir: '/'
}));
return mergeTrees(trees);
}
}
Hope that helps.
Related
I'm using a "core" ember addon in a boilerplate, with
npm link core-addon
This addon contains generic components, helpers, routes...
Is there a way to exclude some of these components in the boilerplate's ember-cli-build file?
I already tried the following in the ember-build-cli in my boilerplate project, which is probably wrong:
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const environment = EmberApp.env();
module.exports = function (defaults) {
let app = new EmberApp(defaults, {
funnel: {
enabled:true,
exclude:['core-addon/pods/components/pages/**/*']
},
});
return app.toTree();
};
Ember version: 3.5.0
Ember cli version 3.5.0 node version 8.11.3
Addons generally take the reverse approach of this: The addon manages what gets merged into the consuming app via configuration in the consuming app.
At the highest level, each addon has an entry point that is the index.js file sitting in the root directory of the addon. The addon provides certain configuration options that it reads from config/environment.js of the consuming app when installing.
I think a really good case study for you would be ember-bootstrap. Look at their configuration options and more specifically the blacklist option. They allow the consuming application to only install a subset of the bootstrap components. Furthermore, the project supports bootstrap 3 or bootstrap 4, but the consuming app isn't getting both! The work is done in index.js
Let's look just at how they blacklist (ie exclude) certain components from being added to the consuming app:
treeForApp(tree) {
tree = this.filterComponents(tree);
return this._super.treeForApp.call(this, tree);
},
filterComponents(tree) {
let whitelist = this.generateWhitelist(this.bootstrapOptions.whitelist);
let blacklist = this.bootstrapOptions.blacklist || [];
// exit early if no opts defined
if (whitelist.length === 0 && blacklist.length === 0) {
return tree;
}
return new Funnel(tree, {
exclude: [(name) => this.excludeComponent(name, whitelist, blacklist)]
});
}
where this.excludeComponent at it's core is a boolean returning filter function that returns true if the blacklist contains it in the blacklist case (there for excluding it). The treeForApp function returns the tree for all app files, ie what will be merged from the addon's app dir into the consuming app:
The consuming app's ember-cli-build would look something like this:
//your-bootstrap-app/ember-cli-build.js
module.exports = function(defaults) {
let app = new EmberApp(defaults, {
'ember-bootstrap': {
blacklist: ['bs-popover', 'bs-accordion']
}
});
return app.toTree();
};
and the result would be no bs-popover and no bs-accordion available in the consuming apps app tree. These options are obtained in the index.js file like so:
let options =Object.assign({}, defaultOptions, app.options['ember-bootstrap']);
this.bootstrapOptions = options;
Check this general guide to building addons and the more advanced api for more info.
I got situation like, I included morris.js file from vendor folder, and configured in ember-cli-build.js file but then my specific modified feature is working in development but not in the production build.
I am using ember-cli-babili for minification. either I should fix which minification part causing the issue or I should remove this file alone from minification.
Is this possible? any guidance is appreciated.
Yes, it is possible!
// ember-cli-build.js
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
minifyJS: {
options: {
exclude: ["**/morris.js"]
}
}
});
//...
return app.toTree();
};
I am developing an ember-cli project and I am working on a system that allows me to resolve templates that have not been loaded and may possibly live outside of the project structure.
I would like to have a folder in my dist/assets directory called templates and inside that folder would be all the pre compiled templates from app/templates/external. This is my current Brocfile.js attempt with broccoli stew
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var stew = require("broccoli-stew");
var app = new EmberApp({
vendorFiles: {
"jquery.js": null
},
sassOptions: {
includePaths: [
'bower_components/bourbon/app/assets/stylesheets/',
'bower_components/neat/app/assets/stylesheets/',
'bower_components/bitters/app/assets/stylesheets/'
]
}
});
var additionalTrees = [];
var templateFiles = stew.find(appTree, "assets/app/templates/external");
templateFiles = stew.mv(templateFiles, "assets/app/templates/external", "assets/templates");
additionalTrees.push(templateFiles);
module.exports = app.toTree(additionalTrees);
There is npm package called broccoli-file-mover , easy to use , and can be found here
The usage is very simple , as easy as :
moveFile(inputTree, options)
can be used to move files ( multiple , or single ) , or whole folders
Example :
Moving a single file from app/main to app:
var moveFile = require('broccoli-file-mover');
var tree = moveFile('app', {
srcFile: 'app/main.js',
destFile: '/app.js'
});
Moving app/main to app and test/main to test:
var moveFile = require('broccoli-file-mover');
var tree = moveFile('app', {
files: {
'app/main.js': 'app.js',
'test/main.js': 'test.js'
}
});
Also , prior to blessnm comment broccoli funnel is a possible solution , as you can copy your directory to wherever you want ( thought the question states moving , but thought copying might be an acceptable solution ) , here is the repo of the plugin.
I have an ember-cli based app which needs to be integrated into an existing java/JSP app. For this to happen I need to generate a JSP file with js/css fingerprinted URLs which are generated by ember-cli/broccoli-asset-rev.
This is working fine for a html file and I can set it use a JSP file by changing my Brocfile.js to include:
var app = new EmberApp({
outputPaths: {
app : {
html: 'index.jsp'
}
}
});
but this prevents ember serve working as it uses the index.jsp as the html file. Is it possible to have both generated?
After trying many things I have come up with two solutions, both have drawbacks. The first is to use make a new broccoli tree and merge it with he app tree then explicity run broccoli-asset-rev on the resulting tree. The downside of this is that the mustache does not get hydrated, this is useful for outputting config. This would look something like:
//Brocfile.js
var mergeTrees = require('broccoli-merge-trees');
var funnel = require('broccoli-funnel');
var assetRev = require('broccoli-asset-rev');
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var jspTree;
var app = new EmberApp({
fingerprint: {
enabled: false
},
storeConfigInMeta: false
});
jspTree = funnel('app', {
files: ['index.jsp']
});
module.exports = assetRev(mergeTrees([appTree = app.toTree(), jspTree]), {
extensions: ['js', 'css'],
replaceExtensions: ['jsp', 'html']
});
The other solution is the override a private api method in ember-cli which builds the tree for the index. This solution does let the mustache get hydrated but relies on a private method. You can find details here and here
How about adding symbolic link?
ln -s index.jsp index.html
Depending on what build tool you're using in your project, I'd probably recommend something like the following:
Put some placeholder sections in your index.html.
Copy index.jsp to index.jsp.tmp.
Copy in code from index.jsp into your placeholder sections.
Move index.jsp.tmp back to index.jsp and clean up.
You might consider something like gulp-replace to do the work.
In an Ember-CLI project, if I add a directory containing webfonts and their CSS stylesheets to the public/assets directory, I can use them with something like #import 'assets/font/regular/stylesheet.css. This works fine.
Ideally though, I'd like to keep these assets out my git repository, and instead bower install them as client-side dependencies, but how can these assets be used in the Ember-CLI build?
The documentation mentions app.import(FILE) in Brocfile.js, which works for CSS stylesheets, but not for a WOFF font file:
$ ember build
version: 0.0.28
Build failed.
Error: Path or pattern "nicefont.woff" did not match any files
at Object.multiGlob (/(PATH)/node_modules/ember-cli/node_modules/broccoli-static-compiler/node_modules/broccoli-kitchen-sink-helpers/index.js:216:13)
at /(PATH)/demo/node_modules/ember-cli/node_modules/broccoli-static-compiler/index.js:25:27
at invokeCallback (/(PATH)/node_modules/ember-cli/node_modules/rsvp/dist/commonjs/rsvp/promise.js:228:21)
at publish (/(PATH)/node_modules/ember-cli/node_modules/rsvp/dist/commonjs/rsvp/promise.js:176:9)
at publishFulfillment (/(PATH)/node_modules/ember-cli/node_modules/rsvp/dist/commonjs/rsvp/promise.js:312:5)
at flush (/(PATH)/node_modules/ember-cli/node_modules/rsvp/dist/commonjs/rsvp/asap.js:41:9)
Also, I would like to specify a directory, which is app.import() refuses.
Is there an Ember-CLI / Brocolli way of doing this?
I thought I was stuck on this issue, but apparently a cup of tea and explicitly phrasing the question on StackOverflow pushed me in the right direction…
If you install a client-side dependency with bower, then in an Ember-CLI project these will end up in vendor/. To use (parts of) them without changing them, we can use Broccoli's slightly awkwardly named broccoli-static-compiler. First, install two build-time dependencies:
npm install --save-dev broccoli-static-compiler
npm install --save-dev broccoli-merge-trees
In Brocfile.js add at the top below the EmberApp import:
var mergeTrees = require('broccoli-merge-trees');
var pickFiles = require('broccoli-static-compiler');
And at the bottom of Brocfile.js:
// Remove this line:
// module.exports = app.toTree()
// Copy only the relevant files:
var fontOpenSans = pickFiles('vendor/font-opensans', {
srcDir: '/',
files: ['**/*.woff', '**/stylesheet.css'],
destDir: '/assets/fonts'
});
// Merge the app tree and our new font assets.
module.exports = mergeTrees([app.toTree(), fontOpenSans]);
Here our client-side dependency is a font-opensans, which refers to a local git repository containing a copy of the Open Sans webfont.
That is all! To use the web-font, link to assets/ from index.html:
<link rel="stylesheet" href="assets/fonts/opensans_regular/stylesheet.css">
This was tested with ember-cli 0.0.40 and a few earlier versions.
The supported answers are a bit out of date. At the time of this writing Ember CLI 0.2.2, there is support for directly copying/fingerprinting vendor folders you want in your assets directory.
// Brocfile.js
var app = new EmberApp();
...
var extraAssets = new Funnel('bower_components/a-lovely-webfont', {
srcDir: '/',
include: ['**/*.woff', '**/stylesheet.css'],
destDir: '/assets/fonts'
});
module.exports = app.toTree(extraAssets);
Documentation here
Similar to answer from JeroenHoek, in ember-cli, version 0.0.40, I ended up doing it right under the app.import before module.exports. I use the augmentation pattern to encapsulate what I'm trying to do so that when/if it's no longer necessary, or there is a more preferred way to do it, I can clean it up easily, and remove modules that aren't used anymore.
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var app = new EmberApp();
// Use `app.import` to add additional libraries to the generated
// output files.
//
// ... [comments omitted]
app.import('vendor/moment/moment.js');
var tree = app.toTree();
tree = (function mergeFontAwesomeTree(tree) {
var mergeTrees = require('broccoli-merge-trees');
var pickFiles = require('broccoli-static-compiler');
var fontawesome = pickFiles('vendor/fontawesome/fonts', {
srcDir: '/',
destDir: '/fonts'
});
return mergeTrees([tree, fontawesome]);
})(tree);
module.exports = tree;