Add JS file without it being built into vendor.js?


#1

I have a case where i need to output a JS file into my /dist/ without it being included in my vendor.js. It seems ember-cli tries its very best to snatch up anything js related and stick it in there. Can this be done?

In my particular application i have a google map and then i have several bower google map plugins. Due to license / account hit limit restrictions i need to load the google map only when a map is to be displayed. Unfortunately the google map plugins are stupid and execute as soon as they are loaded. When they are included in the vendor.js file this causes instant exceptions when the page loads as google maps itself isn’t loaded yet.

So far i’ve tried specifying an desDir in ember-cli-build.js and placing the file in the vendor folder but both times ember-cli just throws it into the vendor.js file.

edit: It looks like i can place the raw file in the /public/ directory but then that breaks the bower_components/… structure.


#2

Hmm basically this function says what i want is impossible unless i change the file extension. I know its an edge case so maybe i’ll just rename the file .js-google or something


#3

I implemented this via scripts in the /public folder - which is of course not the prettiest solution, but it does work reasonably well.

For example, I have a very specific part of my app that is only accessible for a few users where I use Handsontable, which is a pretty big library. I felt it would be unnecessary to load this library for every user even though only ~1% of them would ever need it. So basically what I did was:

  • add the JS, e.g. in /public/assets/handsontable.js
  • deactivate fingerprinting for this file

Then, in the part of the app where I need the library, I added the following in the route:

beforeModel: function() {
  return $.getScript("/assets/handsontable.js");
}

This way, I could be sure that the library was available one the route was loaded.


#4

In our app we have an in-repo addon and we take advantage of the contentFor hooks in the index.js file.

Here is a docs example: http://ember-cli.com/extending/#content

Here is what we do in our app:

contentFor: function(type, config){
  var content = [];
  if (type == 'head-footer') {
    content.push('<script src="/assets/handsontable.js"></script>');
  }
  // ...
  return content.join('\n');
}

Options for the type are:

  • head - Before the app and vendor styles.
  • head-footer - After the app and vendor styles.
  • body - Before the app and vendor JS.
  • body-footer - After the app and vendor JS.

Edit: I thought I should explain how this comes together. If you open up the “index.html” file in your app. You’ll see: {{content-for 'head-footer'}} and others. That’s where your code will be inserted. What’s brilliant about this design is that every add-on has a chance to add their own content scripts.


#5

This is a neat solution. Is there a way to control when in the app lifecycle the script gets loaded? For me the scripts should only be loaded when I go to a certain route.


#6

Oh I’m sorry. I read your question completely but it didn’t click that you meant route.

Engines would likely be good for this, unfortunately they’re still work in progress at this point.

The solution proposed by @francesconovy is your best option I think. I’ve used that before and it’s worked great.


#7

With public/, remember you can symlink to files and folders within ../bower_components/ to keep their structure, and avoid checking vendor files into your repo.


#8

There was an RFC for another possible solution to be built into ember-cli:

https://github.com/ember-cli/rfcs/blob/app-import-output-file/active/0000-app-import-output-file.md


#9

I thought about using symlinks but i use both windows and osx so i didn’t want to deal with cross system issues.