Skip to content
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

Create Block: Create a more modular structure that is easier to extend to several blocks #25188

Open
klinge opened this issue Sep 9, 2020 · 57 comments
Assignees
Labels
Developer Experience Ideas about improving block and theme developer experience [Package] Create Block /packages/create-block [Status] In Progress Tracking issues with work in progress [Type] New API New API to be used by plugin developers or package users.
Projects

Comments

@klinge
Copy link

klinge commented Sep 9, 2020

Is your feature request related to a problem? Please describe.
I've been struggling for days to set up a plugin that implements several blocks. I've looked at examples at github and around the net but most are outdated compared to newer block standards. I admit that my skills in using javascript/webpack/npm are fairly low.

Using the @wordpress/create-block script I quickly get a plugin with a single block up and running - but it's not easily extendable to several blocks. The php side of block init+setup is in the common "plugin.php" file. And when trying move stuff that is common to a block and place that in a subfolder to the src-folder I realize that the build/webpack scripts are not really supporting that.

What solution would you like
I would like the create-block script to generate a structure that is more modular and easier to extend to implementing more than a single block. Something like this:

plugin-folder
/build
/src
--/block1
----<all js, php, css-files that are unique to block1>
--/block2
----<all js, php, css-files that are unique to block2>
--/common-assets
----<files that are common between blocks - included js libraries, common styling etc>
plugin.php
package.json
..

Alternative solutions
The alternative would be to create as many plugins as you want blocks but this seems a bit unnecessary if creating several blocks.

@youknowriad youknowriad added the [Package] Create Block /packages/create-block label Sep 15, 2020
@gziolo
Copy link
Member

gziolo commented Oct 24, 2020

The plan is to make it possible to build and use external templates for Create Block as proposed in #23712. When it's implemented it should be much easier to share alternative configurations that go beyond the setup optimized for Block Directory (https://wordpress.org/support/article/block-directory/) publishing.

@gziolo gziolo added the Needs Decision Needs a decision to be actionable or relevant label Oct 24, 2020
@gziolo
Copy link
Member

gziolo commented Jan 9, 2021

@wordpress/create-block is one step closer to make it possible to support multiple blocks. It works now with custom templates published as npm packages. #27881 is a good example that is being explored that contains a variation of the single block from the block creation tutorial. Those templates can have any number of blocks but it isn’t possible to dynamically pick number of such blocks or collect individual input for all of them. It isn’t clear how far we want to customize the scaffolding tool in the near future. How do you envision interactive mode in CLI for the proposed plugin structure?

@gziolo gziolo added this to To do in Core JS Feb 1, 2021
@gziolo gziolo moved this from To do to Needs decision in Core JS Feb 1, 2021
@skorasaurus
Copy link
Member

skorasaurus commented Jul 21, 2021

Been dealing with this on and off over the past couple months and @bosconian-dynamics has offered some solutions

https://wordpress.stackexchange.com/questions/390282/possible-to-use-wordpress-create-block-with-multiple-blocks

@gziolo gziolo moved this from Needs decision to To do in Core JS Sep 8, 2021
@gziolo gziolo added [Type] New API New API to be used by plugin developers or package users. and removed Needs Decision Needs a decision to be actionable or relevant labels Sep 8, 2021
@gziolo
Copy link
Member

gziolo commented Sep 8, 2021

It looks like it is a recurring request from the community that I see more often these days. The most recent one happened on Twitter and was started by @cr0ybot:

https://twitter.com/cr0ybot/status/1435379030522478596

Struggling with folder structure for new WordPress Gutenberg features, esp. block.json. I want one plugin that handles multiple blocks, & each block has a folder with all relevant src files. So it contains index.js, block.json, style.css, and also index.php for dynamic blocks.

This requires that we add support to @wordpress/create-block the capability to provide a CLI option to generate more than one block and based on that let users fill in details about multiple block. The other aspect is to settle on the folder structure used in the configuration with multiple blocks.

@gziolo gziolo changed the title Let the create-block package create a more modular structure that is easier to extend to several blocks Create Block: Create a more modular structure that is easier to extend to several blocks Sep 8, 2021
@cr0ybot
Copy link
Contributor

cr0ybot commented Sep 8, 2021

To add to what @gziolo pulled in from my tweet, while I do believe that the standard create-block template should offer a best-practice approach for multiple blocks, the main thing I'm struggling with in this context is the location of the block.json file. It doesn't look like create-block currently creates a block.json in the template, but I assume it would put it in the root of the plugin following the current single-block approach.

I prefer to have all files related to each "feature" grouped together in a single folder when possible. This works fine for JS+CSS only, but when you throw block.json in the mix you suddenly need a separate folder/location for the main block metadata. The funny thing is the Gutenberg block-library package is structured the way I want: all files for a block in one folder, including the block.json file. I haven't dug in to see how those metadata files are handled on compile—are they copied to another location?

@gziolo
Copy link
Member

gziolo commented Sep 8, 2021

It doesn't look like create-block currently creates a block.json in the template, but I assume it would put it in the root of the plugin following the current single-block approach.

It creates block.json in the top-level directory and it's independent from the selected template. We can definitely iterate on that when multiple blocks are supported as it won't scale 😄

I haven't dug in to see how those metadata files are handled on compile—are they copied to another location?

Yes, they are copied (with webpack plugin) to the build folder:

Screen Shot 2021-09-08 at 18 17 22

@cr0ybot
Copy link
Contributor

cr0ybot commented Sep 8, 2021

EDIT: This setup is currently not working. For some reason the renamed *.json files aren't playing nicely with register_block_type_from_metadata(). See additional comments below.

EDIT: Code below updated to include "-block.json" at the end of the custom metadata filenames so that they are recognized by register_block_type_from_metadata(). The "-block" should not be needed after WordPress 5.9 is released, see https://core.trac.wordpress.org/ticket/53806.

I've written up a quick webpack config for my project that moves the block.json file into the build folder. My plugin looks like this:

build
src
├ blocks
│  ├ my-block
│  │  ├ block.json
│  │  ├ index.js
│  │  └ style.scss
│  └ my-other-block
└ index.js
package.json
plugin.php
webpack.config.js

webpack.config.js

const { basename, dirname } = require('path');

const CopyWebpackPlugin = require('copy-webpack-plugin');
const defaultConfig = require('@wordpress/scripts/config/webpack.config');

module.exports = {
	...defaultConfig,
	plugins: [
		...defaultConfig.plugins,
		new CopyWebpackPlugin({
			patterns: [
				{
					// Copy block.json to build folder with name of block as filename
					from: 'src/blocks/**/block.json',
					to({ absoluteFilename }) {
						// Get the block folder name
						const blockName = basename(dirname(absoluteFilename));
						// Output with original extension (.json)
						return `./${blockName}-block[ext]`;
					},
				},
			],
		}),
	],
};

This copies the block.json file into the root of /build, so the relative paths within are as simple as possible:

{
  ...
  "editorScript": "file:index.js",
  "style": "file:style-index.css"
}

EDIT: I've removed the preceding ./ from the relative paths above, they aren't needed and the client side URLs end up output that way.

In plugin.php, each metadata file is fed to register_block_type().

I do need to apologize because this is starting to feel a little off-topic from the initial purpose of this issue. Sorry about that. 😓

@gziolo
Copy link
Member

gziolo commented Sep 8, 2021

@cr0ybot, thank you for sharing more details. It is very helpful to plan future iterations.

This copies the block.json file into the root of /build, so the relative paths within are as simple as possible:

{
  ...
  "editorScript": "file:./index.js",
  "style": "file:./style-index.css"
}

I agree that colocating JS, CSS, and block.json in one build's subfolder makes everything so much simpler in terms of defining paths. The only downside is that you need to use CopyWebpackPlugin to ensure it all integrates nicely.

@ryanwelcher
Copy link
Contributor

@gziolo @cr0ybot would it make sense to have an entry point for each block? If I am understanding the code here, it seems that all of the blocks are being combined into a single JS file. So in theory, calling the register_block_type for any block that uses the index.js file will register all the blocks on the client-side? This is probably fine in most cases, but might be worth calling out.

@cr0ybot
Copy link
Contributor

cr0ybot commented Sep 8, 2021

@ryanwelcher Yea sorry, I left that part out. The main /src/index.js file is importing each block folder's index.js file, which is where the actual registerBlockType() is located. But I don't believe that a single call to register_block_type() in PHP would pull all of them in, since as far as I understand it only registers a single block via a namespaced identifier or the path to a block.json metadata file. So the plugin.php file is running register_block_type() on each *.json file in the build folder, which in turn registers the script/style handles automatically for enqueuing.

Here's where I've run into a weird hitch however, and I'm still determining if I've done something wrong: when I try using register_block_type() on these renamed block.json files (say, page-header.json), it isn't working. If I rename one back to block.json it works just fine? Looking at the source for register_block_type_from_metadata(), it looks like a differently-named json file should work just fine, no? I konw this isn't the place for troubleshooting but this is a huge hitch in my block.json relocating/renaming plan...

EDIT: I just realized what you meant when you specified "client side". Yes, since the main index.js file should be enqueued, even if you only registered one block server-side, I see now that they would all be registered client side (only). Sorry!

@gziolo
Copy link
Member

gziolo commented Sep 9, 2021

would it make sense to have an entry point for each block?

@ryanwelcher, I would say it depends on the use case. If you have a parent block that needs some child blocks to be fully functional then I'd say bundling them together makes sense into one JS file. In that case, you probably need to manually register a script and pass the used script handle as a reference in block.json rather than relative paths as in the example above. If you have completely independent blocks, then it seems like a JS file for each block might have some benefits in case you would like to register some of those blocks conditionally for some reason. Although, we still need to add better handling for controlling JS/CSS assets in WP Admin.

Here's where I've run into a weird hitch however, and I'm still determining if I've done something wrong: when I try using register_block_type() on these renamed block.json files (say, page-header.json), it isn't working. If I rename one back to block.json it works just fine?

register_block_type() should work with a custom name for block.json when you pass the full path to the folder. Related code in WP core:

https://github.com/WordPress/wordpress-develop/blob/0bf7d5ea0dd8761ec3026a01aaa27646db8bd7a4/src/wp-includes/blocks.php#L222-L225

@gziolo
Copy link
Member

gziolo commented Sep 9, 2021

Let me also share the guidelines for The WordPress.org Plugin Directory related to single vs multiple blocks:

  1. Block Plugins are separate blocks.

Block plugins are intended to be single purpose, separate, independent blocks, not bundles or compendiums of many blocks. In most cases, a Block Plugin should contain only one single top-level block. The Block Directory will not include collections of blocks that could be reasonably split up into separate, independent, blocks.

Block plugins may contain more than one block where a clearly necessary parent/child or container/content dependency exists; for example a list block that contains list item blocks.

It's worth emphasizing that from the start the intention is to drive folks to submit their blocks to the Block Directory and this is why the documentation is organized around that idea. However, knowing that the motivation from plugin authors can differ, we should make @wordpress/scripts and @wordpress/create-block flexible enough to be able to support multiple blocks that have parent/child relation but also allow a collection of loosely related blocks.

@cr0ybot
Copy link
Contributor

cr0ybot commented Sep 9, 2021

@gziolo As an agency developer, my use case is that I generally want to put all of the custom blocks for a particular site into one plugin for organization, ease of development, and a minimal number of repos.

I also was starting at the code in register_block_type_from_metadata() almost all day yesterday, and looking at it with fresh eyes I think I see the issue.

$filename      = 'block.json';
$metadata_file = ( substr( $file_or_folder, -strlen( $filename ) ) !== $filename ) ?
	trailingslashit( $file_or_folder ) . $filename :
	$file_or_folder;

Walking through the code:

  1. If the $file_or_folder string does not end with "block.json"
  2. then add "/block.json" to the end of $file_or_folder
  3. else use $file_or_folder directly

Therefore, if my metadata file is page-header.json:

  1. "/path/to/metadata/page-header.json" does not end with "block.json"
  2. append "/block.json", so $metadata_file becomes "/path/to/metadata/page-header.json/block.json"

So currently, differently-named metadata files do not work, unless you happen to name your file with "block.json" at the end, i.e. "page-header-block.json". I'm going that route for now.

I went to file this on trac but it looks like it's already being tracked: https://core.trac.wordpress.org/ticket/53806. Kinda disappointed it didn't make it into the 5.8.1 release. I've updated my custom Webpack config above to account for this.

@gziolo
Copy link
Member

gziolo commented Sep 10, 2021

Therefore, if my metadata file is page-header.json:

  1. "/path/to/metadata/page-header.json" does not end with "block.json"
  2. append "/block.json", so $metadata_file becomes "/path/to/metadata/page-header.json/block.json"

So currently, differently-named metadata files do not work, unless you happen to name your file with "block.json" at the end, i.e. "page-header-block.json". I'm going that route for now.

Now I don't remember if there was some rationale behind the current implementation that was incorrectly documented, or that's a bug that needs to be fixed 🤔

Thank you for sharing the Trac ticket. This behavior has been around from the start - WordPress 5.5. I need to research the initial discussion.

Edit: In the initial implementation in the Gutenberg plugin, you would always have to name the file block.json:

gutenberg/lib/compat.php

Lines 26 to 27 in 3345144

function register_block_type_from_metadata( $path, $args = array() ) {
$file = trailingslashit( $path ) . 'block.json';

One thing that comes to my mind is integrations with the Plugin Directory or WP-CLI. A good example is WP-CLI command to extract translations, it restricts processing to files that have block.json name:

https://github.com/wp-cli/i18n-command/blob/49fb6d98ebd5cbe85c87a5efc3c0877be9e358d2/src/MakePotCommand.php#L641-L642

I don't remember how the Plugin Directory detects if the plugin contains blocks, but for sure it would be simpler if the presence of block.json file in the source code would be the way to do it.

@colorful-tones
Copy link
Member

I just watched @ryanwelcher Twitch for Creating a plugin with @wordpress/create-blocks that has multiple blocks, and this is a long overdue tutorial for elevating the developer experience. 👏

As an agency developer, my use case is that I generally want to put all of the custom blocks for a particular site into one plugin for organization, ease of development, and a minimal number of repos.

@cr0ybot I believe it is even likely that non-agency developers have been grappling with this as well, and I would postulate that this hinderance (single block only) is likely keeping from everyday developers from submitting their blocks ideas. I do not have the means to back that with metrics, and merely speculating (never good, I know). However, as an agency developer I've seen this as a rather big roadblock for developer experience.

@gziolo gziolo added the Developer Experience Ideas about improving block and theme developer experience label Oct 11, 2021
@gziolo
Copy link
Member

gziolo commented Oct 11, 2021

I just watched @ryanwelcher Twitch for Creating a plugin with @wordpress/create-blocks that has multiple blocks, and this is a long overdue tutorial for elevating the developer experience. 👏

I watched the stream as well. It was great to see all the options explained by @ryanwelcher 💯 The recording is now available also on YouTube: https://www.youtube.com/watch?v=lwXXckW3dT0 (on Twitch the content gets deleted after some time).

@gziolo
Copy link
Member

gziolo commented Oct 12, 2021

I wanted to share my thoughts after watching the stream from @ryanwelcher. For full transparency, I discussed the same ideas with Ryan in a private chat to better organize my thoughts.

Let me emphasize first that I fully agree that we should refactor @wordpress/create-block so it is capable to support the case with multiple blocks. It's clear that there is some technical limitation that we need to remove first before we get to the finish line. Some things mentioned in the stream greatly cover that, as well as the items discussed above in the issue:

  • block.json is located now in the top folder so it needs to get moved to the subfolder with the other source files for the individual block.
  • If block.json would also get copied to the build folder we could avoid dealing with these awkward paths where you need to use several folders up lookup in the file paths. The downside would be that every update in the source block.json would require the build step which isn't the case at the moment - unless it's also used in the JS code.
  • We could need a way to mark template files directly related to a single block so they could get cloned for every block.

There is also a related topic related to how the build process from @wordpress/scripts works as of today. I really like that @ryanwelcher in his stream ended up with a custom build process where every block has their assets bundled separately. It aligns with the direction that the Full Site Editing project promotes. The vision is to send to users only the code that is necessary for blocks present on the page. It contrasts with many plugins where a single JS or CSS file gets serves for all blocks. At the moment, @wordpress/scripts assumes that there is only a single JS file present in the project:

// By default the script checks if `src/index.js` exists and sets it as an entry point.
// In the future we should add similar handling for `src/script.js` and `src/view.js`.
[ 'index' ].forEach( ( entryName ) => {
const filepath = path.resolve(
process.cwd(),
'src',
`${ entryName }.js`
);
if ( fs.existsSync( filepath ) ) {
entry[ entryName ] = filepath;
}
} );

The initial plan was to handle also src/script.js and src/view.js as entry points when present, so we could offer some common patterns for dealing with block assets. In the scenario with multiple blocks in the plugin, we would bring another level of flexibility and detect subfolders with blocks. We can be creative here, and use glob to match a general pattern like:
src/**/block.json to detect blocks and assume that JS files are in the same folder.

In theory, we could achieve similar goals by changing package.json in the project by modifying wp-scripts build command in the scripts section, but it appears to be a difficult manual process. It would be beneficial to automate that for plugin authors, so they don't have to remember to update that or do what @ryanwelcher ended up doing - included the overridden config with webpack.config.js that defines entry points.

One final thing to think about is also the structure of the build folder in the case it supports multiple blocks. In the stream, you could see the following output generated:

Screen Shot 2021-10-08 at 15 41 56

As noted in #25188 (comment) by @cr0ybot, you could include a block.json file for every block that ends up with -block.json. However, in practice, it might be more convenient to have a subfolder for every block where file names align with the structure familiar from the one block use case:

- build
  - block-one
    - block.json
    - index.asset.php 
    - index.js
    - index.css
    - style-index.css
  - block-two
    - block.json 
    - index.asset.php
    - index.js
    - index.css
    - style-index.css

@cr0ybot
Copy link
Contributor

cr0ybot commented Oct 12, 2021

@gziolo I agree with your final build folder structure, which also solves the issue of having to rename each block.json file.

Something else I'd like to point out related to the relative file paths in block.json is that they can be even simpler than I mentioned in #25188 (comment). I've edited that comment, but the gist is that the ./ before the file path is unnecessary and actually gets output in the final URL last time I checked. I feel like I've mentioned this in another issue somewhere, but it looks like the way realpath() is being used to determine the final URL is not being handled properly.

Anyways, I'd love to see a more flexible way of handling entrypoints in wp-scripts, but I get that could be a slippery slope. I've been adding a view.js file where needed within the block's source folder (and I suppose script.js, though I haven't needed one yet). I like the idea of detecting block.json files and assuming the index.js and potentially the other entrypoints I just mentioned are in the same folder.

@dgwyer
Copy link
Contributor

dgwyer commented Mar 26, 2022

@gziolo @ryanwelcher How about adding support for a --name (alias -n) CLI option to specify block names? Apologies if this has been proposed already.

Single block:
npx @wordpress/create-block test -n block1 would create a single block with block1 for the block slug/name etc.

Multiple blocks:
npx @wordpress/create-block test -n block1 block2 block3 would create multiple blocks, each one inside it's own sub folder ./src/[name]/ with block1, block2, block3 for the block slug/names etc.

If no -n option is specified then use the plugin slug for the block name as is the case right now.

@illycz
Copy link

illycz commented Mar 27, 2022

Once you have the single block created just add it to a folder e.g. ./src/block1 and rename all references to the block to block1. Then it's just a case of duplicating the block folder for multiple blocks and updating all block1 string instances. Don't forget to also update the PHP block registration code too.

And compilation will be working within subfolders?

@dgwyer
Copy link
Contributor

dgwyer commented Mar 28, 2022

Yup, works right out of the box. wp-scripts is very flexible.

@illycz
Copy link

illycz commented Mar 28, 2022

Yup, works right out of the box. wp-scripts is very flexible.

This is my actual folder hierarchy:
image

I don't want copy also node_modules which has 250MB for each block and package.json.
But actual build looks to src folder in root. Is it somehow possible set build which looks to subfolders src folders?

Thanks

@illycz
Copy link

illycz commented Mar 28, 2022

OK, it's possible but:

  • it's impossible set for build task different path to block.json
  • when I change scripts task to new entrypoint in subfolder, block.json wasn't copied to build folder. Here is example from my new hierarchy: "build:upto-price": "wp-scripts build blocks/upto-price/src/index.js --output-path=blocks/upto-price/build". And I moved block.json from src to parent folder. Paths need to be changed.
  • so my actual hierarchy:

image

If there is better/simpler solution, I like to know about it.

Thanks

@illycz
Copy link

illycz commented Mar 28, 2022

I think, the best solution would be setting glob rule for all block.json files. And in block.json set not only scripts and styles paths but also build path. Or generate build folder on same level as src.

So
root-folder
-- block-folder
---- src-folder within block.json, js and css files and php templates
---- build-folder with same content as src

And in packace.json something like this:
"build": "wp-scripts build **/block.json" or omit path because script will find all block.json files...

But I understand that wp-scripts in not only for scaffold blocks, right?

@ryanwelcher
Copy link
Contributor

ryanwelcher commented Apr 5, 2022

The @wordpress/scripts package supports multiple blocks out of the box without any changes required. It just expects a certain structure is in place.

Inside of the src directory, create a directory for each block:

root
-> src
    -> block-one
        -> block.json
        -> OTHER FILES FOR YOUR BLOCK
     -> block-two
        -> block.json
        -> OTHER FILES FOR YOUR BLOCK

This structure will detect all of the block.json files and output each block in its own directory in build and copy all the appropriate files:

root
-> build
    -> block-one
       -> block.json
       -> index.asset.php
       -> index.js
       -> etc
    -> block-two
       -> block.json
       -> index.asset.php
       -> index.js
       -> etc
-> src
    -> SAME AS ABOVE

The important note here is that you need to use src as the name of the directory that contains your code ( it's the default ) in order to have the entry point detection and file copy functionality work. We have just merged #39618 which will allow customization of that directory but that's not in the package yet.

@illycz
Copy link

illycz commented Apr 6, 2022

Ah, OK, make sense. I will try it.

Thanks

@dgwyer
Copy link
Contributor

dgwyer commented Apr 6, 2022

You can use this utility I wrote to create multiple blocks automatically until it's available in core. It's a wrapper around the @wordpress/create-block script.

https://www.npmjs.com/package/create-wp-block

@illycz
Copy link

illycz commented Apr 6, 2022

@ryanwelcher great!
@dgwyer thanks :)

@amjadr360
Copy link

Hi @ryanwelcher @gziolo,
Thanks for all your hard work :)

I manage to handle multiple blocks. But multiple blocks do not work with --hot "Fast Refresh". It's through
[HMR] Update failed: ChunkLoadError: Loading hot update chunk block-one/index failed. error.

Any idea how to solve this issue.

Thanks,

@gziolo
Copy link
Member

gziolo commented Apr 20, 2022

@amjadr360, I can reproduce the same issue when using two blocks (entry points):

Screenshot 2022-04-20 at 17 58 19

@gziolo
Copy link
Member

gziolo commented Apr 21, 2022

I did some investigation on the case with multiple blocks (entry points) and it's fixable but there are some technical challenges. It's also why this feature needs to be activated with --hot flag.

There is an explicit mention for the same use case in the React Fast Refresh Webpack Plugin documentation https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#component-not-updating-with-bundle-splitting-techniques:

Only one copy of both the HMR runtime and the plugin's runtime should be embedded for one Webpack app
This concern only applies when you have multiple entry points. You can use Webpack's optimization.runtimeChunk option to enforce this.

module.exports = {
  optimization: {
    runtimeChunk: 'single',
  },
};

I can confirm that adding this line to the webpack config resolves the issue but the challenge is that we now need to enqueue another script (runtime.js) in the plugin:


Screenshot 2022-04-20 at 18 13 02

I hacked it by adding the following code in my plugin before lines that register blocks:

wp_enqueue_script(
	'webpack-runtime-my-block',
	plugins_url( 'build/runtime.js', __FILE__ ),
);

However, we would need something better that could be handled automatically. I would appreciate some ideas from people on how to integrate that into the existing projects.

@DeoThemes
Copy link

DeoThemes commented Apr 26, 2022

I'm not sure if this is the right place to ask, but I'm struggling to find any information about how to include external libraries as dependencies.

Let's say I have a few blocks that rely on the Swiper slider. Swiper slider provides a way to import only specific modules, which reduces the final bundle. So if I import only specific modules inside of each block I'll end up with multiple copies of the same library in multiple blocks. If I simply copy the production bundle from /node_modules and enqueue it as a regular script, it will work, but the size of the script is very large since it includes all the modules.

I also tried to import only specific modules of the Swiper inside of my scr/js/ folder, this looks a bit hacky. The script compiles only if I provide a block.json file. But my other scripts don't see Swiper instance anymore.

root
-> src
    -> js
        -> block.json
        -> index.js // import Swiper modules here
    -> block-one
        -> block.json
        -> script.js // uses Swiper, but don't see it

in PHP I enqueue the bundle of Swiper from /build/js/index.js, but my block-one script.js doesn't see the Swiper.

What is the correct approach here?

@cr0ybot
Copy link
Contributor

cr0ybot commented Apr 26, 2022

@DeoThemes The way that JavaScript is compiled with WebPack, each entrypoint and module is enclosed so that you avoid issues with everything being in the global scope. If you want the Swiper modules to be globally available on the page, you'll need to add them to the window global var and reference them that way in your various modules. That or enqueue the compiled Swiper library script (not imported modules) separately and earlier than the other scripts.

@stefanfisk
Copy link
Contributor

@cr0ybot Webpack supports sharing libraries between entrypoints if you use optimizations.runtimeChunk = 'single'. I've used it in several projects both for WordPress and random React stuff, and it works great as long as you have tooling to figure out which files need to be loaded.

@iamleese
Copy link

It seems this issue has been resolved, for the most part. I was able to create multiple blocks using this method stated by @ryanwelcher.

The block registrations in the .php file just needs to point to the correct build directory.

function create_block_root_init() { register_block_type( __DIR__ . '/build/block-one' ); register_block_type( __DIR__ . '/build/block-two' ); }

The documentation for @wordpress/create-block should be updated to reflect these changes since I pretty much wasted my time trying to modify the package.json with several start/build scripts.

@cr0ybot
Copy link
Contributor

cr0ybot commented Jul 18, 2022

@stefanfisk Oof, I should have looked into that a bit more before making a suggestion, thanks. Do you happen to know what kind of tooling would be required? Are you talking about WordPress script enqueuing or something else?

@stefanfisk
Copy link
Contributor

@cr0ybot Here's the code I was using at the time https://gist.github.com/stefanfisk/bb4e045f3d15829a377916dc5fee9acc

I am no longer using this as my needs changed, so YMMV.

@gziolo
Copy link
Member

gziolo commented Aug 25, 2022

In the the last version published to npm you can find 2 new CLI options that should vastly improve the experience for extending existing projects with new blocks:

--no-plugin

With #41642 from @ryanwelcher, you can scaffold only the block folder with:

npx @wordpress/create-block --no-plugin

This way you can add as many blocks as you need to your project. You will only have to remember to wire them with:

register_block_type( __DIR__ . '/build/path-to-block' );

--variant

With #41289 from @ryanwelcher, you can also pick different variants of the same block. By default, scaffolded blocks use the static form that contain the save method that produces HTML to store in the database and use on the front end. If you prefer to have more control over the output of the block, you can use , if template supports it, the dynamic block variant where save gets skipped and block gets rendered on the frontend with render_callback PHP implementation. This option can be passed with CLI command:

npx @wordpress/create-block --variant dynamic

or selected in the interactive mode.

@colorful-tones
Copy link
Member

I'm just catching up over here and wanted to point to #44717 which has a good deal of overlap here and I would love feedback from you folks. cc: @dgwyer @cr0ybot @illycz @gziolo Thanks!

@dgwyer
Copy link
Contributor

dgwyer commented Oct 6, 2022

@colorful-tones I created a wrapper CLI tool around create-block to extend it's capabilities. e.g. named blocks, and full Tailwind integration compiling CSS at the block level (separate files). I'd be open to adding more features. 🙂

https://github.com/dgwyer/create-wp-block

@shoelaced
Copy link

Trying this and I'm getting messages like Skipping "./index.js" listed in "C:/path/to/plugin/src/block-a/block.json". File is located outside of the "src" directory and No entry file discovered in the "src" directory when trying to re-structure the folders as @ryanwelcher mentioned. Has this functionality changed? I'm on Windows, could there be something breaking #38781 from a while back?

@shoelaced
Copy link

Nevermind, I've figured it out and created an issue: #45792

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Developer Experience Ideas about improving block and theme developer experience [Package] Create Block /packages/create-block [Status] In Progress Tracking issues with work in progress [Type] New API New API to be used by plugin developers or package users.
Projects
No open projects
Core JS
  
In progress
Development

No branches or pull requests