-
Notifications
You must be signed in to change notification settings - Fork 394
Should suggest explicit *ToExport entries in module manifest #434
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
Comments
Wow, that's a surprise, so +1 for this rule then if that's what's required. It seems intuitive to me that if you explicitly provide entries for the commands that are exported that you're taking control and saving PowerShell from having to do the guesswork. That's a practice I've been following for a while not. It doesn't seem intuitive to me that if you don't have a FunctionsToExport attribute in your manifest (because you explicitly removed it) that PowerShell would do extra work to make sure that you did the right thing. That seems like behaviour I'd prefer work differently. If I do use a manifest but I explicitly remove or don't include FunctionsToExport, isn't that clear enough guidance for PowerShell? I guess not, and if that's the case (which Jason is indicating it is), having a rule pick up on this and provide the tip will be helpful. Now I've got another TODO for my modules, to add back empty command array attributes. |
Agreed, it's not intuitive. I have an unreleased change to PowerShell that works like you (and I) expect, but it breaks real world scripts. The change was made to get better performance, but I'm not keeping the change because of the risk of breaking more scripts, instead I'm hoping we can fix more module manifests to improve performance. This issue is one way I hope to help address the performance problem. |
Thanks for filing this here, Jason. I was also not aware that this is how autoloading works until our conversation last week. I think we'd definitely like to do this one. My only remaining question is whether this should be a warning or an error. Given it's impact, I'd actually make the push for error, but I know it will be extremely noisy given how many people use wildcards today. Our guidance will have to be very clear that this high-impact in order to avoid people just suppressing the output. |
Excellent info. I didn't know either. Can someone please update New-ModuleManifest or the TechNet page about module manifests? https://technet.microsoft.com/en-us/library/dd878337(v=vs.85).aspx It seems that the entries in the module manifest take precedence over Export-ModuleMember statements. Jason, what is the precedence order and is it affected by anything, like module type or nested modules? |
The module manifest is the final truth if it has a non-null value, but it's not precedence, it's more like filtering. If a psm1 uses Export-ModuleMember, only those names are available to the manifest for export. I am updating New-ModuleManifest as well. |
Thanks. Appreciate the doc update. [Sorry to diverge from the rules discussion, but this is really valuable.] In Joel Bennett's BetterCredentials module, he used Export-ModuleMember to This is consistent with the non-null value explanation, but it seems that, So, maybe what we need is an explanation of the order of evaluation. On Mon, Feb 1, 2016 at 12:49 PM, Jason Shirk notifications@github.com
Thanks, |
@juneb: I think you mean AliasesToExport, not FunctionsToExport, since you're talking about aliases, right? I already knew about the filtering nature of the manifest. It quickly becomes very apparent when you opt for explicit export of functions and cmdlets in your modules and you forget to include a function/cmdlet name in the appropriate manifest attribute. |
To get the conversation back on track - warning vs error? I'd lean towards warning. It can be annoying or easy to forget to update your manifest. We need to encourage frequently used modules to do the right thing (e.g. the Azure module can add 200ms to the command search time (generally a one time cost) because they use wildcards), but smaller modules have much less impact (typically <10ms). |
I agree, warning, not error. It's not broken, just recommended for change. |
"Warning" severity fits here. "Error" is for critical issues. Jason - Do we enable this rule for modules targeted to any PowerShell version? Or does this behavior affect certain versions? |
From a performance perspective, the advice only matters from V3 onwards. I think it's safe and reasonable to warn when targeting V2 though. |
#449 Rule added and available in v1.4.0 release |
Making the ToExport fields explicit makes module discovery faster. The fields must not be null or contain wildcards. The discussion can be found here: Should suggest explicit *ToExport entries in module manifest PowerShell/PSScriptAnalyzer#434
Just FYI for people who come across this, it turns out that this rule is about more than just performance. If you have a module that is included in the NestedModules attribute of another module (call it "A"), and if module "A" does not explicitly set *ToExport collections in the manifest, then the nested module will not autoload when you try to invoke one of the commands it contains because PowerShell gets confused about where to go find that command (since the module was loaded as nested in module "A", it tries to find the command there but it can't be invoked through that module because the module is nested and therefore not visible outside of the scope of module "A"). Once you clean up your manifests and explicitly export empty collections for *ToExport fields in modules that have none of those items to export, and once you clear your module command cache after doing that cleanup, only then will your module that was loaded in as a Nested module auto-load properly when you try to invoke one of its commands in the global scope. |
Module auto-discovery is fastest when a module has entries for:
During module auto-discovery, if any of these entries are missing or $null, PowerShell do some potentially expensive work to analyze the rest of the module (e.g. do reflection on a dll, or parse and analyze the psm1).
If these entries are all present and non null, then this extra work can be avoided and provide a better overall experience.
If one of these entries is missing, PSScriptAnalyzer should suggest adding an entry like:
FunctionsToExport = @()
If one of the entries uses wildcards, PSScriptAnalyzer should suggest replacing the wildcards with an explicit list.
The module type (script or binary) doesn't matter, these entries are needed for the best performance.
The text was updated successfully, but these errors were encountered: