简体   繁体   English

In-repo插件在构建时编写公共文件会导致无法在服务上构建循环

[英]In-repo addon writing public files on build causes endless build loop on serve

I'm having difficulty with my in-repo addon writing to appDir/public. 我在处理appDir / public的in-repo插件时遇到了困难。 What I'd like to do is write out a JSON file on each build to be included in the app /dist. 我想要做的是在每个构建上写出一个JSON文件,以包含在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. 我遇到的问题是当运行“ember serve”时,文件监视器会检测到新文件并再次重建,从而导致无限循环。

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. 我尝试使用preBuild()和postBuild()钩子编写JSON文件,保存到/ public,但是在构建之后,观察者会检测到它并反复重建,每次都重新写入一个新文件。 I also tried using my-addon/public folder and writing to that, same thing. 我也尝试使用my-addon / public文件夹并写入相同的内容。

The only thing that partially works is writing on init(), which is fine, except I don't see the changes using ember serve. 唯一可以部分工作的是写init(),这很好,除了我没有看到使用ember serve的更改。

I did try using the treeForPublic() method, but did not get any further. 我确实尝试使用treeForPublic()方法,但没有进一步。 I can write the file and use treeForPublic(). 我可以编写该文件并使用treeForPublic()。 This only runs once though, on initial build. 这只在初始构建时运行一次。 It partially solves my problem, because I get the files into app dist folder. 它部分解决了我的问题,因为我把文件放到app dist文件夹中。 But I don't think ember serve will re-run treeForPublic on subsequent file change in the app. 但我不认为ember serve会在应用程序中的后续文件更改时重新运行treeForPublic。

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? 也许在ember-cli-build中有一个排除监视属性?

Here's my treeForPublic() , but I'm guessing my problems aren't here: 这是我的treeForPublic(),但我猜我的问题不在这里:

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 更新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. 我的目标是创建一个自动增量构建号,在ember构建和ember服务上更新。 My comments under @real_ates's answer below help explain why. 我在@ real_ates下面的回答中的评论有助于解释原因。 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. @real_ate的答案非常有用,解决了无限循环问题,但它不能在ember服务上运行。 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(). 我目前正在尝试更改环境变量而不是使用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 我已经将这个问题作为一个单独的问题,关于对Ember环境的addon config()更新: 使用ember-serve上的in-repo addon config()方法更新Ember.js环境变量不会生效

I don't know if can mark @real_ate's answer as the accepted solution because it doesn't work on ember serve. 我不知道是否可以将@ real_ate的答案标记为已接受的解决方案,因为它不适用于ember服务。 It was extremely helpful and educational! 这非常有帮助和教育!

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. treeForPublic()的问题是您的treeForPublic()实际上是将文件写入源目录,然后您使用broccoli-funnel选择新的自定义文件并将其包含在构建中。 The correct method to do this is instead to use broccoli-file-creator to create an output tree that includes your new file. 执行此操作的正确方法是使用broccoli-file-creator创建包含新文件的输出树。 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. 两个主要的区别是,没有一个函数this.saveSettingsFile()在磁盘上写出一个设置文件,我们现在有一个函数this.getSettingsData() ,它返回我们希望在新创建的文件中看到的内容。 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. 下一个主要区别是我们使用的是writeFile()函数,它实际上只是broccoli-file-creator插件。 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 这个问题作为“我可以提问”第2季第2集的一部分得到了回答。如果您希望我们完整地讨论这个答案,您可以在这里查看视频: https//youtu.be/9kMGMK9Ur4E

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM