Dependency Extraction Webpack Plugin: Externalize script modules as import() and emit module_dependencies#76397
Conversation
…mport() and emit module_dependencies Packages like @wordpress/abilities and @wordpress/core-abilities are script modules (registered via wpScriptModuleExports) that don't expose window globals. The plugin currently treats all @wordpress/* packages as window-global scripts, which breaks at runtime. This adds these packages to the existing defaultRequestToExternalModule switch and makes non-module (IIFE) builds also consult that function via a try-catch bridge. Script module externals are detected in processModule via m.externalType === 'import' and emitted as module_dependencies in the asset file, matching the format WordPress PHP expects.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Size Change: 0 B Total Size: 6.89 MB ℹ️ View Unchanged
|
|
Flaky tests detected in 28eac5d. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/22956287715
|
| try { | ||
| externalRequest = | ||
| defaultRequestToExternalModule( request ); | ||
| } catch { | ||
| // Not a script module, fall through. | ||
| } | ||
| if ( typeof externalRequest === 'undefined' ) { | ||
| externalRequest = defaultRequestToExternal( request ); | ||
| } |
There was a problem hiding this comment.
Will you help me understand why this is necessary?
There was a problem hiding this comment.
This is the essential part of this PR, even if we are not using modules we may be importing a module so with this change we always try defaultRequestToExternalModule if it successes ( we are requesting a module) we use it otherwise we do what we did defaultRequestToExternal.
| case '@wordpress/interactivity-router': | ||
| case '@wordpress/a11y': | ||
| case '@wordpress/abilities': | ||
| case '@wordpress/core-abilities': |
There was a problem hiding this comment.
No, we need the two other changes: on the change at https://github.com/WordPress/gutenberg/pull/76397/changes#r3009852731 we make sure that for non script module defaultRequestToExternalModule is called. Without that change this function is not even called so the changes here don't change anything.
The computation of the sets:
/** @type {Set<string>} */
const chunkScriptModuleStaticDeps = new Set();
/** @type {Set<string>} */
const chunkScriptModuleDynamicDeps = new Set();
Is to ensure the build generates the correct dependencies and module_dependencies arrays I don't think we can remove anything from this PR.
|
I'm guessing this is for old plugins right? Cause AFAIK wp-build already handles this right? |
@jonathanbossenger didn't you have problems with wp-build and the abilities package? |
|
@sirreal I did, I had to use Example plugin https://github.com/jonathanbossenger/wp-ai-client-demo/ I also stumbled across this example where someone else uses the same workaround: WordPress/ai#346 |
|
If I'm not wrong, wp-builds discovers the module dependencies but just ignore them when it comes to scripts registration and if there's a PHP API for it, we should follow-up to actually use the "module_dependencies" array from the asset file. |
If you needed webpackignore, it means you're not using wp-build which doesn't use webpack. |
|
Aha, apologies @youknowriad, I didn't see your comment. So switching from wp-scripts to wp-build would fix this, is what you're saying? |
|
@jonathanbossenger I can't tell for sure haha :) , but you won't need the webpackignore comment that's certain. |
|
I'll try it out and see. But yeah, if using wp-scripts, which most plugin developers are probably using, the issue exists. |
Hi @youknowriad, |
Hi @sirreal, #76395 is an alternative to this to achieve the same goal. While this one relies on a hardcode list and will only work for core packages, that one can work on any package even if it is not in core and does not uses na hardcoded list. It has a big drawback it forces the packages to be published to npm so the build can read its package.json and know if it is a script module or not. I think we should probably go with this one as it is much simpler. |
|
Hi @youknowriad, @sirreal I answered all questions raised. |
Summary
FIxes: #75196
Packages like
@wordpress/abilitiesand@wordpress/core-abilitiesare script modules (registered viawpScriptModuleExports) that don't exposewindowglobals. The webpack dependency extraction plugin currently treats all@wordpress/*packages as window-global scripts, which causes:window.wp.abilities(doesn't exist at runtime)wp-abilitiesindependenciesinstead ofmodule_dependenciesin the asset fileThis PR adds these packages to the existing
defaultRequestToExternalModuleswitch (alongside@wordpress/a11yand@wordpress/interactivity-router) and makes non-module (IIFE) builds also consult that function. Script module externals are detected inprocessModuleviam.externalType === 'import'and emitted asmodule_dependenciesin the asset file, matching the format WordPress PHP expects.Changes
util.js— 2 lines: add@wordpress/abilitiesand@wordpress/core-abilitiesto the existingdefaultRequestToExternalModuleswitchindex.js— 3 changes:defaultRequestToExternalModulefirst (try-catch), fall through todefaultRequestToExternalfor regular scriptsprocessModule: detect import-type externals viam.externalType === 'import', route to separatechunkScriptModuleStaticDeps/chunkScriptModuleDynamicDepssetsmodule_dependenciesarray with static/dynamic entriesTest plan
npm install && npm run build. Check out https://github.com/jonathanbossenger/wp-ai-client-demo/tree/debug-wp-build-2 (branch debug-wp-build-2 ).