Open g-elwell opened 2 years ago
@scottblackburn this is related to enqueuing of assets per-block, would be interested to know what you think
Hey @g-elwell and @ampersarnie I was going to open a new issue for Increase support for block.json asset values
but noticed this open issue and believe the goals are the same so I've added what would have been my issues description below.
Happy to discuss any of this further though as a lot of this is untested/theoretical as was just putting down some ideas around it.
block.json
allows the declaration of a blocks style, script and render assets directly, I believe we should increase support for this to leverage a number of benefits and potentially move towards this way as standard as this is currently the recommended approach for specific block scripts/styles.
The current supported assets via block.json
are as follows;
editorScript
script
viewScript
viewScriptModule
editorStyle
style
viewStyle
render
More information and definitions of the above can be found here.
Currently I think the only way to use block.json
assets would be to register your styles/scripts via the corresponding wp_register_
function and then use the registered handle for each asset in the block.json
.
Multiple entrypoints
files would be required to generate the corresponding asset files for a block and if you have multiple blocks the entrypoints
folder will potentially become crowded with the separate files for each block.
src/
entrypoints/
block-one-editor.js
block-one-shared.js
block-one-frontend.js
block-two-editor.js
block-two-shared.js
block-two-frontend.js
...
...
...
block-ten-editor.js
block-ten-shared.js
block-ten-frontend.js
This will also lead to the maintenance of the required checks around any defined asset constants used from asset-settings.php
increasing in difficulty due to the amount of new entries for each of the blocks assets.
I propose that we look into modifying the build tools to also check for src/blocks/*
folders or something similar and then generate the corresponding dist/blocks/*
folders after a build
or watch
command.
A basic example of a folder structure of src/blocks
would look something like;
src/
blocks/
sample-block/
block.json
edit.js
editor.js (`editorScript` asset)
shared.js (`script` asset)
frontend.js (`viewScript` asset)
editor.scss (`editorStyle` asset)
shared.scss (`style` asset)
frontend.scss (`viewStyle` asset)
render.php (`render` asset)
built to;
dist/
blocks/
sample-block/
block.json
editor.js (`editorScript` asset)
shared.js (`script` asset)
frontend.js (`viewScript` asset)
editor.scss (`editorStyle` asset)
shared.scss (`style` asset)
frontend.scss (`viewStyle` asset)
render.php (`render` asset)
These folder structures would be duplicated for as many blocks as necessary.
Each blocks render.php
and block.json
files would be included in the src/blocks/*
folders to avoid fragmenting the blocks files across locations. This makes it easier to maintain each block as the src/blocks/*
folder becomes the source of truth for any block changes.
Depending on changes and with the new structure we could use block.json
to handle assets in a couple of ways off the top of my head.
block.json
This would be similar to the way it potentially works now but with the different file/folder structure. Each blocks assets would need to be registered with wp_register_style
or wp_register_script
and each handle used with the corresponding block.json
asset value.
The render
value can use the file path directly as the render.php
file would always have the same relative path in both the src
and dist
folders .e.g ./render.php
.
block.json
from dist/blocks/*
I believe this would require the most effort to implement in the build tools but would also require the least amount of work when registering a block.
Alongside handling the new file/folder structure we would need to also implement the below;
*.asset.php
dependency files will need to be generatedWithout the need to use a registered handle for each blocks assets, the below should be enough to register the block and all required assets.
register_block_type( '../dist/blocks/sample-block/' );
With multiple blocks it should be possible to do something like the below and register them automatically, avoiding having to add each additional block manually.
$path_to_blocks = plugin_dir_path( __FILE__ ) . 'dist/blocks';
$blocks = scandir( $path_to_blocks );
foreach ( $blocks as $block ) {
if ( ! is_dir( $path_to_blocks . '/' . $block ) || str_contains( $block, '.' ) ) {
continue;
}
register_block_type( $path_to_blocks . '/' . $block );
}
Implementing something like this will most likely be a breaking change, there is no guarantee that a project hasn't already used a src/blocks/
folder, suggests a major
version bump.
The current entrypoints
folder should be left as is, as this is required for features that aren't blocks.
Keep an eye on what core is recommending as best practices and make sure we can support any changes/new features going forward.
No support for strategy
or in_footer
arguments when using a direct file path as an asset value but support for these values is being looked into I believe.
Shouldn't warrant any changes in current CI/CD pipeline steps.
Thanks for sharing @chrishbite ! This issue would also be implemented by https://github.com/bigbite/build-tools/issues/117 which was added recently and is something we can hopefully explore sooner rather than later.
The additional context you've added here will also be relevant in discussions around how we approach that issue
I've been looking into block themes and how blocks are going to be built in WP going forward, there's some interesting developments in enqueuing assets on a per-block basis.
For example, if you register a block using
block.json
you can define its script/style assets there - including separate ones for editor/frontend bundles. WordPress will only load the assets if the block is present on the current page, so it's a pretty cool optimisation and has already landed in core.Since these build tools support multiple entrypoints, it's possible to get this working, but I feel like treating a block more as a 'project' could be an overall better approach, especially since a theme or plugin might have several blocks each featuring multiple entrypoints.
This could also enable block code to live together, rather than the current requirement where JS and PHP code for the same block need to be managed in separate locations, perhaps something like this (you'd potentially have multiples of these inside a specific plugin/theme):
The end result should be that you just need to require the
index.php
file in order for your block to work, since it usesblock.json
to register the block, and theblock.json
tells it which scripts/styles to enqueue. I haven't tested this fully, since I wanted to see what you all think about whether it woulda good idea to integrate this with the build tools?I'm guessing either another folder would need to be scanned for projects, or we'd consider adding a config so you can tell the build tools which projects it should be looking for explicitly...
Ref: https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/