3

I'm having difficulty with my in-repo addon writing to appDir/public. What I'd like to do is write out a JSON file on each build to be included in the app /dist. The problem I'm running into is when running "ember serve", the file watcher detects the new file and rebuilds again, causing an endless loop.

I've tried writing the JSON file using preBuild() and postBuild() hooks, saving to /public, but after build, the watcher detects it and rebuild over and over, writing a new file again each time. I also tried using my-addon/public folder and writing to that, same thing.

The only thing that partially works is writing on init(), which is fine, except I don't see the changes using ember serve.

I did try using the treeForPublic() method, but did not get any further. I can write the file and use treeForPublic(). This only runs once though, on initial build. It partially solves my problem, because I get the files into app dist folder. But I don't think ember serve will re-run treeForPublic on subsequent file change in the app.

Is there a way to ignore specific files from file watch? Yet still allow files to include into the build? Maybe there's an exclude watch property in ember-cli-build?

Here's my treeForPublic() , but I'm guessing my problems aren't here:

treeForPublic: function() {
    const publicTree = this._super.treeForPublic.apply(this, arguments);
    const trees = [];
    if (publicTree) {
        trees.push(publicTree);
    }
    // this writes out the json
    this.saveSettingsFile(this.pubSettingsFile, this.settings);
    trees.push(new Funnel(this.addonPubDataPath, {
        include: [this.pubSettingsFileName],
        destDir: '/data'
    }));

    return mergeTrees(trees);
},

UPDATE 05/20/2019

I should probably make a new question at this point...

My goal here is to create an auto-increment build number that updates both on ember build and ember serve. My comments under @real_ates's answer below help explain why. In the end, if I can only use this on build, that's totally ok.

The answer from @real_ate was very helpful and solved the endless loop problem, but it doesn't run on ember serve. Maybe this just can't be done, but I'd really like to know either way. I'm currently trying to change environment variables instead of using treeforPublic(). I've asked that as a separate question about addon config() updates to Ember environment: Updating Ember.js environment variables do not take effect using in-repo addon config() method on ember serve

I don't know if can mark @real_ate's answer as the accepted solution because it doesn't work on ember serve. It was extremely helpful and educational!

gregthegeek
  • 1,353
  • 3
  • 14
  • 24

1 Answers1

2

This is a great question, and it's often something that people can be a bit confused about when working with broccoli (I know for sure that I've been stung by this in the past)

The issue that you have is that your treeForPublic() is actually writing a file to the source directory and then you're using broccoli-funnel to select that new custom file and include it in the build. The correct method to do this is instead to use broccoli-file-creator to create an output tree that includes your new file. I'll go into more detail with an example below:

treeForPublic: function() {
  const publicTree = this._super.treeForPublic.apply(this, arguments);
  const trees = [];
  if (publicTree) {
    trees.push(publicTree);
  }

  let data = getSettingsData(this.settings);
  trees.push(writeFile('/data/the-settings-file.json', JSON.stringify(data)));

  return mergeTrees(trees);
}

As you will see the most of the code is exactly the same as your example. The two main differences are that instead of having a function this.saveSettingsFile() that writes out a settings file on disk we now have a function this.getSettingsData() that returns the content that we would like to see in the newly created file. Here is the simple example that we came up with when we were testing this out:

function getSettingsData() {
  return {
    setting1: 'face',
    setting2: 'my',
  }
}

you can edit this function to take whatever parameters you need it to and have whatever functionality you would like.

The next major difference is that we are using the writeFile() function which is actually just the broccoli-file-creator plugin. Here is the import that you would put at the top of the file:

let writeFile = require('broccoli-file-creator');

Now when you run your application it won't be writing to the source directory any more which means it will stop constantly reloading


This question was answered as part of "May I Ask a Question" Season 2 Episode 2. If you would like to see us discuss this answer in full you can check out the video here: https://youtu.be/9kMGMK9Ur4E

real_ate
  • 10,861
  • 3
  • 27
  • 48
  • Sorry, took me forever to respond, had to work on another project. So this is working to solve the endless loop, awesome! Just using that broccoli-file-creator to write out the json was all I needed. And that is very helpful to get files into the tree, so I'll be using that trick for other things too. However, I'm kind of still in the same boat because I don't see updated JSON when ember serve updates on livereload. The treeForPublic() only runs on initial build I think. I know the settings update on serve because preBuild() shows in console. But writeFile() doesn't output the file. – gregthegeek May 17 '19 at 17:59
  • Hey @gregthegeek. Can you explain more as to why you need the JSON to update during ember serve? I have had a bit of a mixed response with getting this to work in general. Also you mention in the youtube comment that it's supposed to be used for an auto-incrementing build number, why would this be used during local development rather than in a CI? – real_ate May 20 '19 at 13:25
  • Yeah, its really me being stubborn. I really only need it on build. Its just driving me nuts I can't have it also on serve. The reason for a build number? because its simple and I can see at a glance that my app updated or not. Its more helpful during dev for me because there's been many times I didn't have an update show up on serve, or maybe I had some code that could be checking for a new version and do other things. Having an incrementing build number would have solved the odd cases. I usually end up with a workaround or better way, but I like having it available. ... – gregthegeek May 20 '19 at 17:28
  • Its just this... I've run into times over a the last 2-3 years now where I thought, "Man, having a build number would be handy, why doesn't Ember do this?" So one day I just couldn't stand not scratching that itch, and tried something to get it working. Oh! And part of my use for this is because I'm using service workers. There's been so many times I had to go though many clicks just to find out my app didn't even update due to SW somehow. Its been annoying me a lot recently. Having a build number on my app status bar would be super easy and helpful, even on serve. – gregthegeek May 20 '19 at 17:35
  • What about a "last built time" for the serve situation? – real_ate May 21 '19 at 16:26
  • Good idea. I'm testing a simple function in environment.js that stamps datetime. I add that result to ENV. But I'm still running into the same problem, ENV does not update on serve, which make no sense because if I change the file, ember detects and reloads again. Yet, values do not update in ENV. I think that's the root problem no matter what I try. – gregthegeek May 21 '19 at 19:22
  • I think that's actually a completely different issue I have not had much success updating ENV and having the Ember app notice without restarting ember-cli. It might be worth asking in the #ember-cli channel in the Ember Community discord if this is even possible – real_ate May 22 '19 at 10:09
  • 1
    Yeah, I'm pretty much moving on from this for now. Unless I can get updated, dynamic data loaded into ENV somehow, or get a file written on every serve, I don't know how I can solve this. But as I said, its not a huge priority. I *can* do this on build and it works great, so I think I'm good for any published builds which is most important. Thanks so much for your help on this! It was very helpful and I learned more about Ember and the CLI, which is still a win for me! – gregthegeek May 22 '19 at 17:53