-
-
Notifications
You must be signed in to change notification settings - Fork 491
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make config run async #1429
Make config run async #1429
Conversation
6dcbf0f
to
8d4c0ba
Compare
Fixes: #614 |
I've been testing this in a real setting today and I hit this:
I'm not sure if it is related to this change or not but it looks like then the config changes the We should test this... might be happening with the existing prod build. |
I found a bug where changes to the
|
Got it! The data is correct. I'd moved the initialization of the watcher until after the config was initialized because it needed the config in the constructor. However init is run on change so I ended up with a new browser-sync server instance every time files changed and thus... no reload. Fixed by changing the watcher constructor. |
93348b0
to
32f501f
Compare
I think this was solved by ensuring the config init() was only called once |
6dd4374
to
e84d7f1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really sorry to do this but adding config arguments to constructors isn’t likely ideal for future maintenance—can you rework those? 😭
this.config.inputDir = this.inputDir; | ||
|
||
let formats = this.formatsOverride || this.config.templateFormats; | ||
this.extensionMap = new EleventyExtensionMap(formats); | ||
this.extensionMap = new EleventyExtensionMap(formats, config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d super rather just use the setter style here rather than changing the constructor signature. this.extensionMap.config =
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can attempt this, but in some cases config is already used in the constructor and I'm not sure I know how to handle that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could really use an example I think.
|
||
this.templateData = new TemplateData(this.inputDir); | ||
this.templateData = new TemplateData(this.inputDir, config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as the comment above but it looks like this one will be a little more annoying because there isn’t a setter in place already
src/TemplateConfig.js
Outdated
let localConfig = {}; | ||
let path = TemplatePath.join( | ||
TemplatePath.getWorkingDir(), | ||
localProjectConfigPath | ||
); | ||
debug(`Merging config with ${path}`); | ||
|
||
// Note for Mike: I'm delaying the processing of plugins until here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you have your think here 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I did if by think you mean run enough scenarios in a production scale project until you hit the bugs.
What I did was move the merging of the config part to a new method: mergeEleventyConfig
now I run this before and after processing the plugins. This means that the plugins get the initial merged data and that any data changes\added by plugins is remerged.
let merged = this.mergeEleventyConfig(localConfig);
await eleventyConfig.applyPlugins(merged);
merged = this.mergeEleventyConfig(localConfig);
For performance reasons I chose not to merge after each individual plugin, meaning plugins can't read data added or changed by other plugins, and order of plugins doesn't matter.
Will delete comment.
this.config.inputDir = this.inputDir; | ||
|
||
let formats = this.formatsOverride || this.config.templateFormats; | ||
this.extensionMap = new EleventyExtensionMap(formats); | ||
this.extensionMap = new EleventyExtensionMap(formats, config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can attempt this, but in some cases config is already used in the constructor and I'm not sure I know how to handle that.
return this.configOverride || require("./Config").getConfig(); | ||
return this.configOverride || this.config; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another reason I am confused about using a getter\setter is that config is not the same thing as templateConfig
need multiple getters\setters?
} | ||
set config(cfg) { | ||
this.configOverride = cfg; | ||
} | ||
|
||
get engineManager() { | ||
if (!this._engineManager) { | ||
this._engineManager = new TemplateEngineManager(); | ||
this._engineManager = new TemplateEngineManager(this.templateConfig); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getter/Setter here too?
@@ -2,8 +2,8 @@ const HandlebarsLib = require("handlebars"); | |||
const TemplateEngine = require("./TemplateEngine"); | |||
|
|||
class Handlebars extends TemplateEngine { | |||
constructor(name, includesDir) { | |||
super(name, includesDir); | |||
constructor(name, includesDir, templateConfig) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getter/Setter here too?
src/TemplateConfig.js
Outdated
let localConfig = {}; | ||
let path = TemplatePath.join( | ||
TemplatePath.getWorkingDir(), | ||
localProjectConfigPath | ||
); | ||
debug(`Merging config with ${path}`); | ||
|
||
// Note for Mike: I'm delaying the processing of plugins until here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I did if by think you mean run enough scenarios in a production scale project until you hit the bugs.
What I did was move the merging of the config part to a new method: mergeEleventyConfig
now I run this before and after processing the plugins. This means that the plugins get the initial merged data and that any data changes\added by plugins is remerged.
let merged = this.mergeEleventyConfig(localConfig);
await eleventyConfig.applyPlugins(merged);
merged = this.mergeEleventyConfig(localConfig);
For performance reasons I chose not to merge after each individual plugin, meaning plugins can't read data added or changed by other plugins, and order of plugins doesn't matter.
Will delete comment.
this.config.inputDir = this.inputDir; | ||
|
||
let formats = this.formatsOverride || this.config.templateFormats; | ||
this.extensionMap = new EleventyExtensionMap(formats); | ||
this.extensionMap = new EleventyExtensionMap(formats, config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could really use an example I think.
@zachleat @MadeByMike I love this change! It'll be super useful for all kinds of async tasks done during the config setup, e.g. using Shiki (which requires async initialization) as a syntax highlighter. Thanks for working on this! :) |
This feature would be extremely useful for me too. |
Agreed, this would be amazing! In particular, it would let you do really cool things like generating different favicon sizes at build time so that you don't have to do that with external tools. I don't think you can do this with the 11ty Image plugin unless you make it a shortcode since it's async. (Edit: This is possible, disregard my old post.) |
Hey y’all, I feel bad about this but unfortunately (and this is entirely my fault) I need to close this one as stale. The timing ended up being really bad and the scope of this PR ended up being a huge contributor to its downfall, as I did a pretty sizable refactor of the configuration stuff shortly after this was opened. Really sorry. (Also cross linking to #2103) |
Another cross link to home base at #614 |
This allows for acync config. Such as:
I know this looks like a HEFTY PR please ignore the number of files changed and look at the types of changes. Significan't changes to the way tests are structure and how
templateConfig
is handled but the changes to the core core are relatively small.The main changes are to
cmd.js
and the mainEleventy
class. A number of calls in main 11ty runner are now delayed until after the config has been initialised. Other significant changes include the way plugins are added. These are now also async so they are resisted and resolved when config is run.Finally the way the global template config is managed has changed. Previously this could be imported from
src/Config.js
into anywhere and this would work since it is global. Now, since config is async we need to ensure that it is passed explicitly to each classes that uses it after it has been initialised.Because of this there were also significant changes to tests to ensure that the config has been initialised before tests that depend on it.
There are a few todos including:
Throwing this up here for feedback and to test the CI. Since 11ty doesn't ship a lock file I sometimes get differences with the way prism does highlighting.
I think the passing around of
templateConfig
could be improved by adding a base class that sets and manages these global properties. Tests could then override this property for individual classes. Happy to consider these type of suggestions or for future improvement to 11ty in general.