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

Scripts: Enable React Fast Refresh for block development #28273

Merged
merged 2 commits into from Dec 14, 2021

Conversation

gziolo
Copy link
Member

@gziolo gziolo commented Jan 18, 2021

Description

Part of #21008 targeting @wordpress/scripts.

I followed instructions at https://github.com/pmmmwh/react-refresh-webpack-plugin and it fully works as expected for Chrome and Safari. It should work with both React Developer Tools enabled but also without them.

I was testing with SCRIPT_DEBUG set to true for WordPress to ensure that development versions of react and react-dom were served. In general, the challenge is that we are using externals for both libraries, while in the examples shared they are all bundled together.

At the moment React Refresh needs to be activated with the --hot flag when executing the start command from @wordpress/scripts:

wp-scripts start --hot

If the flag is not provided then the start command should work as before.

Resolved Blockers

How has this been tested?

The way I test it:

npx wp-create-block my-block --no-wp-scripts
cd my-block
../node_modules/.bin/wp-scripts start --hot

This is to ensure that we are using the latest @wordpress/scripts from the branch and with the default webpack config from @wordpress/scripts.

Ensure your WordPress instance has SCRIPT_DEBUG set to true.

Screenshots

React.Refresh.Safari.mov
React.Refresh.Chrome.and.Safari.mov

Types of changes

New feature (non-breaking change which adds functionality).

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR.

@gziolo gziolo self-assigned this Jan 18, 2021
@gziolo gziolo added [Package] Scripts /packages/scripts [Status] In Progress Tracking issues with work in progress [Type] Build Tooling Issues or PRs related to build tooling labels Jan 18, 2021
@github-actions
Copy link

github-actions bot commented Jan 18, 2021

Size Change: 0 B

Total Size: 1.12 MB

ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 960 B
build/admin-manifest/index.min.js 1.1 kB
build/annotations/index.min.js 2.75 kB
build/api-fetch/index.min.js 2.21 kB
build/autop/index.min.js 2.12 kB
build/blob/index.min.js 459 B
build/block-directory/index.min.js 6.28 kB
build/block-directory/style-rtl.css 1.01 kB
build/block-directory/style.css 1.01 kB
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
build/block-editor/index.min.js 139 kB
build/block-editor/style-rtl.css 14.4 kB
build/block-editor/style.css 14.4 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 65 B
build/block-library/blocks/archives/style.css 65 B
build/block-library/blocks/audio/editor-rtl.css 58 B
build/block-library/blocks/audio/editor.css 58 B
build/block-library/blocks/audio/style-rtl.css 111 B
build/block-library/blocks/audio/style.css 111 B
build/block-library/blocks/audio/theme-rtl.css 125 B
build/block-library/blocks/audio/theme.css 125 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 470 B
build/block-library/blocks/button/editor.css 470 B
build/block-library/blocks/button/style-rtl.css 560 B
build/block-library/blocks/button/style.css 560 B
build/block-library/blocks/buttons/editor-rtl.css 291 B
build/block-library/blocks/buttons/editor.css 291 B
build/block-library/blocks/buttons/style-rtl.css 275 B
build/block-library/blocks/buttons/style.css 275 B
build/block-library/blocks/calendar/style-rtl.css 207 B
build/block-library/blocks/calendar/style.css 207 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 79 B
build/block-library/blocks/categories/style.css 79 B
build/block-library/blocks/code/style-rtl.css 90 B
build/block-library/blocks/code/style.css 90 B
build/block-library/blocks/code/theme-rtl.css 134 B
build/block-library/blocks/code/theme.css 134 B
build/block-library/blocks/columns/editor-rtl.css 210 B
build/block-library/blocks/columns/editor.css 208 B
build/block-library/blocks/columns/style-rtl.css 503 B
build/block-library/blocks/columns/style.css 502 B
build/block-library/blocks/comment-template/style-rtl.css 127 B
build/block-library/blocks/comment-template/style.css 127 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/cover/editor-rtl.css 546 B
build/block-library/blocks/cover/editor.css 547 B
build/block-library/blocks/cover/style-rtl.css 1.22 kB
build/block-library/blocks/cover/style.css 1.22 kB
build/block-library/blocks/embed/editor-rtl.css 488 B
build/block-library/blocks/embed/editor.css 488 B
build/block-library/blocks/embed/style-rtl.css 417 B
build/block-library/blocks/embed/style.css 417 B
build/block-library/blocks/embed/theme-rtl.css 124 B
build/block-library/blocks/embed/theme.css 124 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 255 B
build/block-library/blocks/file/style.css 255 B
build/block-library/blocks/file/view.min.js 322 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 966 B
build/block-library/blocks/gallery/editor.css 970 B
build/block-library/blocks/gallery/style-rtl.css 1.63 kB
build/block-library/blocks/gallery/style.css 1.62 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 159 B
build/block-library/blocks/group/editor.css 159 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 114 B
build/block-library/blocks/heading/style.css 114 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 810 B
build/block-library/blocks/image/editor.css 809 B
build/block-library/blocks/image/style-rtl.css 507 B
build/block-library/blocks/image/style.css 511 B
build/block-library/blocks/image/theme-rtl.css 124 B
build/block-library/blocks/image/theme.css 124 B
build/block-library/blocks/latest-comments/style-rtl.css 284 B
build/block-library/blocks/latest-comments/style.css 284 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B
build/block-library/blocks/latest-posts/editor.css 137 B
build/block-library/blocks/latest-posts/style-rtl.css 528 B
build/block-library/blocks/latest-posts/style.css 527 B
build/block-library/blocks/list/style-rtl.css 94 B
build/block-library/blocks/list/style.css 94 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 493 B
build/block-library/blocks/media-text/style.css 490 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 649 B
build/block-library/blocks/navigation-link/editor.css 650 B
build/block-library/blocks/navigation-link/style-rtl.css 94 B
build/block-library/blocks/navigation-link/style.css 94 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation-submenu/view.min.js 343 B
build/block-library/blocks/navigation/editor-rtl.css 1.91 kB
build/block-library/blocks/navigation/editor.css 1.91 kB
build/block-library/blocks/navigation/style-rtl.css 1.68 kB
build/block-library/blocks/navigation/style.css 1.67 kB
build/block-library/blocks/navigation/view.min.js 2.79 kB
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 377 B
build/block-library/blocks/page-list/editor.css 377 B
build/block-library/blocks/page-list/style-rtl.css 172 B
build/block-library/blocks/page-list/style.css 172 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B
build/block-library/blocks/paragraph/editor.css 157 B
build/block-library/blocks/paragraph/style-rtl.css 273 B
build/block-library/blocks/paragraph/style.css 273 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/style-rtl.css 446 B
build/block-library/blocks/post-comments-form/style.css 446 B
build/block-library/blocks/post-comments/style-rtl.css 507 B
build/block-library/blocks/post-comments/style.css 507 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 721 B
build/block-library/blocks/post-featured-image/editor.css 721 B
build/block-library/blocks/post-featured-image/style-rtl.css 153 B
build/block-library/blocks/post-featured-image/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 391 B
build/block-library/blocks/post-template/style.css 392 B
build/block-library/blocks/post-terms/style-rtl.css 73 B
build/block-library/blocks/post-terms/style.css 73 B
build/block-library/blocks/post-title/style-rtl.css 80 B
build/block-library/blocks/post-title/style.css 80 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 198 B
build/block-library/blocks/pullquote/editor.css 198 B
build/block-library/blocks/pullquote/style-rtl.css 389 B
build/block-library/blocks/pullquote/style.css 388 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 273 B
build/block-library/blocks/query-pagination/style.css 269 B
build/block-library/blocks/query/editor-rtl.css 131 B
build/block-library/blocks/query/editor.css 132 B
build/block-library/blocks/quote/style-rtl.css 187 B
build/block-library/blocks/quote/style.css 187 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 397 B
build/block-library/blocks/search/style.css 398 B
build/block-library/blocks/search/theme-rtl.css 64 B
build/block-library/blocks/search/theme.css 64 B
build/block-library/blocks/separator/editor-rtl.css 99 B
build/block-library/blocks/separator/editor.css 99 B
build/block-library/blocks/separator/style-rtl.css 245 B
build/block-library/blocks/separator/style.css 245 B
build/block-library/blocks/separator/theme-rtl.css 172 B
build/block-library/blocks/separator/theme.css 172 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 772 B
build/block-library/blocks/site-logo/editor.css 772 B
build/block-library/blocks/site-logo/style-rtl.css 165 B
build/block-library/blocks/site-logo/style.css 165 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 84 B
build/block-library/blocks/site-title/editor.css 84 B
build/block-library/blocks/social-link/editor-rtl.css 177 B
build/block-library/blocks/social-link/editor.css 177 B
build/block-library/blocks/social-links/editor-rtl.css 670 B
build/block-library/blocks/social-links/editor.css 669 B
build/block-library/blocks/social-links/style-rtl.css 1.32 kB
build/block-library/blocks/social-links/style.css 1.32 kB
build/block-library/blocks/spacer/editor-rtl.css 307 B
build/block-library/blocks/spacer/editor.css 307 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 471 B
build/block-library/blocks/table/editor.css 472 B
build/block-library/blocks/table/style-rtl.css 481 B
build/block-library/blocks/table/style.css 481 B
build/block-library/blocks/table/theme-rtl.css 188 B
build/block-library/blocks/table/theme.css 188 B
build/block-library/blocks/tag-cloud/style-rtl.css 146 B
build/block-library/blocks/tag-cloud/style.css 146 B
build/block-library/blocks/template-part/editor-rtl.css 560 B
build/block-library/blocks/template-part/editor.css 559 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 569 B
build/block-library/blocks/video/editor.css 570 B
build/block-library/blocks/video/style-rtl.css 173 B
build/block-library/blocks/video/style.css 173 B
build/block-library/blocks/video/theme-rtl.css 124 B
build/block-library/blocks/video/theme.css 124 B
build/block-library/common-rtl.css 857 B
build/block-library/common.css 856 B
build/block-library/editor-rtl.css 10 kB
build/block-library/editor.css 10 kB
build/block-library/index.min.js 163 kB
build/block-library/reset-rtl.css 474 B
build/block-library/reset.css 474 B
build/block-library/style-rtl.css 10.7 kB
build/block-library/style.css 10.8 kB
build/block-library/theme-rtl.css 672 B
build/block-library/theme.css 677 B
build/block-serialization-default-parser/index.min.js 1.09 kB
build/block-serialization-spec-parser/index.min.js 2.79 kB
build/blocks/index.min.js 46.3 kB
build/components/index.min.js 215 kB
build/components/style-rtl.css 15.5 kB
build/components/style.css 15.5 kB
build/compose/index.min.js 10.9 kB
build/core-data/index.min.js 13.2 kB
build/customize-widgets/index.min.js 11.4 kB
build/customize-widgets/style-rtl.css 1.5 kB
build/customize-widgets/style.css 1.49 kB
build/data-controls/index.min.js 631 B
build/data/index.min.js 7.49 kB
build/date/index.min.js 31.5 kB
build/deprecated/index.min.js 485 B
build/dom-ready/index.min.js 304 B
build/dom/index.min.js 4.5 kB
build/edit-navigation/index.min.js 16 kB
build/edit-navigation/style-rtl.css 3.76 kB
build/edit-navigation/style.css 3.76 kB
build/edit-post/classic-rtl.css 492 B
build/edit-post/classic.css 494 B
build/edit-post/index.min.js 29.7 kB
build/edit-post/style-rtl.css 7.1 kB
build/edit-post/style.css 7.09 kB
build/edit-site/index.min.js 35.4 kB
build/edit-site/style-rtl.css 6.57 kB
build/edit-site/style.css 6.57 kB
build/edit-widgets/index.min.js 16.5 kB
build/edit-widgets/style-rtl.css 4.18 kB
build/edit-widgets/style.css 4.18 kB
build/editor/index.min.js 37.8 kB
build/editor/style-rtl.css 3.78 kB
build/editor/style.css 3.77 kB
build/element/index.min.js 3.29 kB
build/escape-html/index.min.js 517 B
build/format-library/index.min.js 6.58 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.63 kB
build/html-entities/index.min.js 424 B
build/i18n/index.min.js 3.71 kB
build/is-shallow-equal/index.min.js 501 B
build/keyboard-shortcuts/index.min.js 1.8 kB
build/keycodes/index.min.js 1.39 kB
build/list-reusable-blocks/index.min.js 1.72 kB
build/list-reusable-blocks/style-rtl.css 838 B
build/list-reusable-blocks/style.css 838 B
build/media-utils/index.min.js 2.92 kB
build/notices/index.min.js 925 B
build/nux/index.min.js 2.08 kB
build/nux/style-rtl.css 747 B
build/nux/style.css 743 B
build/plugins/index.min.js 1.84 kB
build/primitives/index.min.js 924 B
build/priority-queue/index.min.js 582 B
build/react-i18n/index.min.js 671 B
build/react-refresh-entry/index.min.js 8.49 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.65 kB
build/reusable-blocks/index.min.js 2.22 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 11 kB
build/server-side-render/index.min.js 1.57 kB
build/shortcode/index.min.js 1.49 kB
build/token-list/index.min.js 639 B
build/url/index.min.js 1.9 kB
build/viewport/index.min.js 1.05 kB
build/warning/index.min.js 248 B
build/widgets/index.min.js 7.15 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.04 kB

compressed-size-action

@gziolo gziolo force-pushed the try/react-fast-refresh branch 2 times, most recently from 5423c71 to 346e856 Compare January 29, 2021 15:08
Base automatically changed from master to trunk March 1, 2021 15:45
@gziolo gziolo added this to In progress in Core JS Mar 17, 2021
@gziolo
Copy link
Member Author

gziolo commented Mar 17, 2021

The current status can be summarized with the following demo:

react-fast-refresh.mov

It works perfectly fine for JavaScript files when developing a block 🎉

There are some issues with how webpack 4 works when MiniCSSExtractPlugin is integrated. In particular, it fails miserably with optimization.splitChunks.cacheGroups for shared styles.

@gziolo gziolo changed the title Scripts: Try adding React Fast Refresh support Scripts: Enable React Fast Refresh for block development Mar 17, 2021
@iandunn
Copy link
Member

iandunn commented Mar 17, 2021

That's awesome, thanks!

I had trouble getting it setup on a site that's served from a local domain w/ SSL (e.g., https://wp.test). Webpack's dev server was running on http://localhost, but the browser was requesting https://localhost. It looks like overriding the config to use 127.0.0.1 as the hostname might work, but I ran out of time to try that.

@gziolo
Copy link
Member Author

gziolo commented Mar 18, 2021

I had trouble getting it setup on a site that's served from a local domain w/ SSL (e.g., https://wp.test). Webpack's dev server was running on http://localhost, but the browser was requesting https://localhost. It looks like overriding the config to use 127.0.0.1 as the hostname might work, but I ran out of time to try that.

I guess this line needs to be improved in the webpack config:

publicPath: `http://localhost:${ DEV_SERVER_PORT }/build/`,

I'm also not too fond of:

headers: {
 	// Requests come from the WP port.
 	'Access-Control-Allow-Origin': '*',
 },

So it's definitely where it would have to improve to support different scenarios available other than using @wordpress/env that I used for testing.

@iandunn
Copy link
Member

iandunn commented Mar 18, 2021

Ah, yeah, that got me further. It looks like changes are need to both config.output and config.devServer:

diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js
index c33d154..5eb2655 100644
--- a/packages/scripts/config/webpack.config.js
+++ b/packages/scripts/config/webpack.config.js
@@ -8,6 +8,9 @@ const path = require( 'path' );
 const ReactRefreshWebpackPlugin = require( '@pmmmwh/react-refresh-webpack-plugin' );
 const TerserPlugin = require( 'terser-webpack-plugin' );
 
+const fs = require( 'fs' );
+
 /**
  * WordPress dependencies
  */
@@ -89,7 +92,9 @@ const config = {
 		// are used on the same page.
 		// @see https://github.com/WordPress/gutenberg/issues/23607
 		jsonpFunction: getJsonpFunctionIdentifier(),
-		publicPath: `http://localhost:${ DEV_SERVER_PORT }/build/`,
+		publicPath: `https://learn.wordpress.test:${ DEV_SERVER_PORT }/build/`,
 	},
 	resolve: {
 		alias: {
@@ -255,10 +260,20 @@ if ( ! isProduction ) {
 		headers: {
 			// Requests come from the WP port.
 			'Access-Control-Allow-Origin': '*',
 		},
 		liveReload: false,
+		host: 'learn.wordpress.test',
 		port: DEV_SERVER_PORT,
 		writeToDisk: true,
+
+		https: {
+			key: fs.readFileSync( '/Users/iandunn/vhosts/localhost/learn.wordpress.test/learn.wordpress.test-key.pem' ),
+			cert: fs.readFileSync( '/Users/iandunn/vhosts/localhost/learn.wordpress.test/learn.wordpress.test.pem' ),
+			ca: fs.readFileSync( '/Users/iandunn/Library/Application Support/mkcert/rootCA.pem' )
+		}
 	};
 }

I just hardcoded those for testing, but plugins could set cross-environment things by overriding webpack.config.js, and individual devs could set environment-specific things with CLI args.

That gets rid of the JS-related console errors during the initial page load. I still get errors about stylesheets, but that seems to be expected at the moment.

I haven't gotten it working with updates, though. Each save to edit.js gets this in the console:

[HMR] Checking for updates on the server... log.js:24
[HMR] Checking for updates on the server... log.js:24
[HMR] Checking for updates on the server... log.js:24
[HMR] Checking for updates on the server... log.js:24
[HMR] Checking for updates on the server... log.js:24
[HMR] Nothing hot updated. log.js:24
[HMR] App is up to date. log.js:24
[HMR] Nothing hot updated. log.js:24
[HMR] App is up to date. log.js:24
[HMR] Nothing hot updated. log.js:24
[HMR] App is up to date. log.js:24
[HMR] Nothing hot updated. log.js:24
[HMR] App is up to date. log.js:24
[HMR] Updated modules: log.js:24
[HMR]  - ./js/workshop/src/edit.js log.js:24
[HMR] App is up to date. log.js:24

The watcher sees the edit to edit.js, but the changes aren't reflected 🤔

@gziolo
Copy link
Member Author

gziolo commented Mar 19, 2021

I just hardcoded those for testing, but plugins could set cross-environment things by overriding webpack.config.js, and individual devs could set environment-specific things with CLI args.

It looks like you can set some of those custom settings with CLI, not sure how it would work with https though:
https://github.com/webpack/webpack-dev-server#with-the-cli

I haven't gotten it working with updates, though. Each save to edit.js gets this in the console:

Yes, it might be because of issues with CSS imports. In my testing, I removed all references to all files that match style.*css pattern. I hope it will work out of the box with webpack 5.

@gziolo gziolo force-pushed the try/react-fast-refresh branch 4 times, most recently from 864727c to 59b9e5f Compare August 10, 2021 12:11
@gziolo
Copy link
Member Author

gziolo commented Aug 11, 2021

I rebased this branch with the latest changes from trunk including webpack migration to v5.

Resolves issues

I managed to resolve two known issues that existed before sp CSS reloading works perfectly fine in this branch:

New issues

It looks like hot reloading still works for JavaScript changes, but it doesn't refresh updated React components anymore. At least for my test scenario:

npx wp-create-block gutenpride --no-wp-scripts -t wp-block-directory-template
cd gutenpride
../node_modules/.bin/wp-scripts start --hot

The comment with the default webpack config shortcomings is still relevant: #28273 (comment).

@gziolo gziolo added [Status] Blocked Used to indicate that a current effort isn't able to move forward and removed [Status] In Progress Tracking issues with work in progress labels Nov 5, 2021
@gziolo
Copy link
Member Author

gziolo commented Feb 24, 2022

@nicholasio, I'm very excited to see it being implemented at 10up 🎉 I'm happy to help you to make it work so we could learn from each other.

It seems like compiling react-refresh-entry is not actually needed https://github.com/WordPress/gutenberg/blob/trunk/tools/webpack/development.js#L24 and I'm not sure if you're even loading this in WP at all?

It depends on the browser used. It isn't necessary in Chome when React Developer Tools are enabled. I see a comment from @fabiankaegy in the PR referenced above that there are some issues in Safari. I left the following comment there:

There are no React Developer Tools for Safari so it's harder to configure it. React Refresh entry and runtime needs to be externalized and initialized before React loads (https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#externalising-react). At the moment it's only available with the Gutenberg plugin enabled and SCRIPTS_DEBUG set to true that ensures that the React Refresh runtime is correctly configured. In Chrome, it should work with the Gutenberg plugin enabled and it probably doesn't need the React Refresh runtime.

@nicholasio
Copy link

@gziolo Thanks for following up. re: react-refresh-entry yeah we noticed it wasn't working for @fabiankaegy I guess bc he didn't have the react developer tools installed. I have included it again and it's now working.

@dgwyer
Copy link
Contributor

dgwyer commented Mar 17, 2022

@gziolo it works with that. I am currently using this:

"start:hot": "wp-scripts start --hot --allowed-hosts all",

@shivapoudel I'm also trying to get this working with LocalWP but without much success. No matter what settings I use it doesn't hot reload. Is this still working for you? I'm on Windows and am beginning to wonder if this is a factor too.

@shivapoudel
Copy link
Contributor

@dgwyer You have to activate the Gutenberg plugin to get this working, my friend :)

@gziolo
Copy link
Member Author

gziolo commented Mar 18, 2022

You have to activate the Gutenberg plugin to get this working, my friend :)

It reminds me that we should bring the same scripts to WordPress core in the 6.0 release cycle. We still will need to put it behind the SCRIPT_DEBUG constant.

pento pushed a commit to WordPress/wordpress-develop that referenced this pull request Apr 11, 2022
Brings the same functionality introduced in the Gutenberg plugin with WordPress/gutenberg#28273. In effect, it brings React Fast Refresh support to WordPress core for block development with `@wordpress/scripts`.

Props walbo, antonvlasenko.
See #51750, #55505.
Follow-up [53135].



git-svn-id: https://develop.svn.wordpress.org/trunk@53140 602fd350-edb4-49c9-b593-d223f7449a82
markjaquith pushed a commit to markjaquith/WordPress that referenced this pull request Apr 11, 2022
Brings the same functionality introduced in the Gutenberg plugin with WordPress/gutenberg#28273. In effect, it brings React Fast Refresh support to WordPress core for block development with `@wordpress/scripts`.

Props walbo, antonvlasenko.
See #51750, #55505.
Follow-up [53135].


Built from https://develop.svn.wordpress.org/trunk@53140


git-svn-id: http://core.svn.wordpress.org/trunk@52729 1a063a9b-81f0-0310-95a4-ce76da25c4cd
gMagicScott pushed a commit to gMagicScott/core.wordpress-mirror that referenced this pull request Apr 11, 2022
Brings the same functionality introduced in the Gutenberg plugin with WordPress/gutenberg#28273. In effect, it brings React Fast Refresh support to WordPress core for block development with `@wordpress/scripts`.

Props walbo, antonvlasenko.
See #51750, #55505.
Follow-up [53135].


Built from https://develop.svn.wordpress.org/trunk@53140


git-svn-id: https://core.svn.wordpress.org/trunk@52729 1a063a9b-81f0-0310-95a4-ce76da25c4cd
@gziolo
Copy link
Member Author

gziolo commented Jul 26, 2022

You have to activate the Gutenberg plugin to get this working, my friend :)

It works now also with WordPress 6.0 with the SCRIPT_DEBUG flag enabled.

@rafaucau
Copy link

rafaucau commented Aug 9, 2022

@gziolo I set allHosts and refresh works, but I get this errors in the console:
image
image

When I update the code (React) of my block, the page refreshes instead of applying the update.

Edit:
The --https flag was missing wp-scripts start --hot --allowed-hosts localhost --allowed-hosts .localhost --https, but still the page refreshes instead of updating live.
image

@gziolo
Copy link
Member Author

gziolo commented Aug 11, 2022

The --https flag was missing wp-scripts start --hot --allowed-hosts localhost --allowed-hosts .localhost --https, but still the page refreshes instead of updating live.

Setting up the connection between the WordPress instance and the dev server is the worst. Unfortunately, I don't have enough experience with that part 😞

@rafaucau
Copy link

I found a solution. I'm using Docker and the site in the localhost subdomain works in the browser, but there was no this subdomain in the hosts file. I added it and it started working.

@eduwass
Copy link
Contributor

eduwass commented Feb 16, 2023

@shivapoudel @dgwyer I know I'm late to the party but I can't get this to work in LocalWP, tried all of the solutions in the post I think.

Currently my script has this:

		"start:hot": "wp-scripts start --hot --host officehours.local --allowed-hosts all"

It looks like it starts:

officehours on  main [!] is 📦 v0.1.0 via ⬢ v19.0.1 via 🐘 v8.1.12 took 1m 33s 
➜ npm run start:hot

> officehours@0.1.0 start:hot
> wp-scripts start --hot --host officehours.local --allowed-hosts all

<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Server: http://officehours.local:8080/
<i> [webpack-dev-server] Loopback: http://[::1]:8080/
<i> [webpack-dev-server] Content not from webpack is served from '/Users/eduwass/Sites/officehours/app/public/wp-content/plugins/officehours/public' directory
assets by chunk 123 KiB (name: index)
  asset index.js 122 KiB [emitted] [minimized] (name: index)
  asset index.asset.php 139 bytes [emitted] (name: index)
  asset index.css 57 bytes [emitted] (name: index)
asset block.json 491 bytes [emitted] [from: src/block.json] [copied]
asset render.php 142 bytes [emitted] [from: src/render.php] [copied]
...

But then I see nothing on the Server URL?

officehours on  main [!] is 📦 v0.1.0 via ⬢ v19.0.1 via 🐘 v7.4.30
➜ curl -I http://officehours.local:8080/
HTTP/1.1 404 Not Found
X-Powered-By: Express
Content-Security-Policy: default-src 'none'
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8
Content-Length: 140
Vary: Accept-Encoding
Date: Thu, 16 Feb 2023 03:46:02 GMT
Connection: keep-alive
Keep-Alive: timeout=5


officehours on  main [!] is 📦 v0.1.0 via ⬢ v19.0.1 via 🐘 v7.4.30
➜ curl http://officehours.local:8080/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /</pre>
</body>
</html>

Apologies if I'm missing something obvious! Would love to see this working 😅

@dgwyer
Copy link
Contributor

dgwyer commented Feb 16, 2023

I didn't get this working in LocalWP either. Haven't tried for a while though.

@rafaucau

I found a solution. I'm using Docker and the site in the localhost subdomain works in the browser, but there was no this subdomain in the hosts file. I added it and it started working.

Did you mean you got it to work with wp-env (which is Docker based), or your own Docker solution? Would love to learn more about this.

@eduwass
Copy link
Contributor

eduwass commented Feb 17, 2023

@gziolo any idea on #28273 (comment) and if not, do you think it's worth creating a separate issue? thanks!

@rafaucau
Copy link

rafaucau commented Feb 17, 2023

@dgwyer Did you mean you got it to work with wp-env (which is Docker based), or your own Docker solution? Would love to learn more about this.

My own Docker solution based on this: https://github.com/litespeedtech/ols-docker-env
Currently this doesn't work for me if the plugin has multiple Gutenberg blocks. When the plugin has one block (block.json directly in the src folder), it works.

So, it doesn't work:
-src
--block1
---block.json
--block2
---block.json

But it works:
-src
--block.json

With wp-env, both versions works ¯_(ツ)_/¯

@rafaucau

This comment was marked as resolved.

@rafaucau
Copy link

rafaucau commented Feb 26, 2023

I finally found a solution (at least for me)! The problem is caused by multiple entry points (I have multiple blocks in one plugin). You need to add the following code to webpack.config.js:

optimization: {
  runtimeChunk: 'single',
},

For example:

const defaultConfig = require('@wordpress/scripts/config/webpack.config');
const { getWebpackEntryPoints } = require('@wordpress/scripts/utils/config');

const isProduction = process.env.NODE_ENV === 'production';

const config = {
  ...defaultConfig,
  entry: {
    ...getWebpackEntryPoints(),
    index: './src/index.ts',
  },
};

if (!isProduction) {
  // Fix HMR
  config.optimization = {
    ...defaultConfig.optimization,
    runtimeChunk: 'single',
  };
}

module.exports = config;

This creates an additional runtime.js file. You need to load it in the editor:

add_action( 'enqueue_block_assets', function () {
  $runtime_asset_path = plugin_dir_path( __FILE__ ) . 'build/runtime.asset.php';

  if ( file_exists( $runtime_asset_path ) ) {
    $runtime_asset = require $runtime_asset_path;

    wp_enqueue_script(
      'my-plugin-runtime',
      plugin_dir_url( __FILE__ ) . 'build/runtime.js',
      $runtime_asset['dependencies'],
      $runtime_asset['version'],
    );
  }
} );

@dgwyer
Copy link
Contributor

dgwyer commented Feb 26, 2023

Nice work, thanks for sharing.

@gziolo
Copy link
Member Author

gziolo commented Feb 26, 2023

I finally found a solution (at least for me)! The problem is caused by multiple entry points (I have multiple blocks in one plugin). You need to add the following code to webpack.config.js:

optimization: {
  runtimeChunk: 'single',
},

It took me some time to find my old comment about using runtime chunk added in a different place: #25188 (comment). Thank you for sharing your findings. It looks like it still works. It would be great to have this runtime always present in the development mode when using hot module replacement. The only challenge would be to integrate the script enqueuing somehow with register_block_type call.

@gziolo any idea on #28273 (comment) and if not, do you think it's worth creating a separate issue? thanks!

I don't think I can help much here. Have you tried accessing thebuild subfolder on the webpack dev server? It's where files are exposed if I recall correctly. See settings:

https://github.com/WordPress/gutenberg/blob/f64379314802d2d4b64077ca6b980e9df824b762/packages/scripts/config/webpack.config.js#L312L325

@eduwass
Copy link
Contributor

eduwass commented Mar 5, 2023

Hi @gziolo been playing with this a bit today:

Have you tried accessing thebuild subfolder on the webpack dev server? It's where files are exposed if I recall correctly. See settings:

I created a new site in LocalWP, called tests1.local

I have an example plugin running inside it:

CleanShot 2023-03-05 at 18 46 14@2x

As you can see I've added a webpack.config.js so I'm able to mess around with config details.

Starting script

I've added the following script to package.json:

		"start:hot": "wp-scripts start --webpack-copy-php --hot"

When I start it, this is the output

wp-content/plugins/example-dynamic is 📦 v0.1.0 via ⬢ v19.7.0 via 🐘 v8.1.9
➜ npm run start:hot

> example-dynamic@0.1.0 start:hot
> wp-scripts start --webpack-copy-php --hot

<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Server: http://tests1.local:8887/
<i> [webpack-dev-server] Loopback: http://[::1]:8887/
<i> [webpack-dev-server] Content not from webpack is served from '/Users/eduwass/Sites/tests1/app/public/wp-content/plugins/example-dynamic/public' directory
assets by chunk 519 KiB (name: index)
  asset index.js 518 KiB [emitted] (name: index) 1 related asset
  asset index.css 959 bytes [emitted] (name: index) 1 related asset
  asset index.asset.php 167 bytes [emitted] (name: index)
asset ./style-index.css 1 KiB [emitted] (name: ./style-index) (id hint: style) 1 related asset
asset block.json 503 bytes [emitted] [from: src/block.json] [copied]
asset render.php 149 bytes [emitted] [from: src/render.php] [copied]
Entrypoint index 520 KiB (537 KiB) = ./style-index.css 1 KiB index.css 959 bytes index.js 518 KiB index.asset.php 167 bytes 3 auxiliary assets

Build folder

I am able to access files from the /build folder, for example:

➜ curl tests1.local:8887/block.json
{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 2,
  "name": "create-block/example-dynamic",
  "version": "0.1.0",
  "title": "Example Dynamic",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block scaffolded with Create Block tool.",
  "supports": {
    "html": false
  },
  "textdomain": "example-dynamic",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "render": "file:./render.php"
}%

So it seems like webpack is connect properly? Also this:

[webpack-dev-server] Content not from webpack is served from '/Users/eduwass/Sites/tests1/app/public/wp-content/plugins/example-dynamic/public' directory

...is also true, if I create a /public/index.html inside of my plugin folder, I can see it when I do:

wp-content/plugins/example-dynamic is 📦 v0.1.0 via ⬢ v19.7.0 via 🐘 v8.1.9
➜ curl tests1.local:8887
<h1>Hello world</h1>

It's like webpack is there serving the correct files, but the connection with the browser is not working?

@jlandrum
Copy link

jlandrum commented Oct 12, 2023

I'm not quite sure how to approach this, an issue may be needed, but I'm not too sure what exactly the issue is and thus how to indicate what needs to be fixed exactly. I've been trying to get fast refresh working, maybe it's because the package itself is unstable (as indicated by the authors) but...

In a project with no changes and multiple blocks:

  • Only one block will fast refresh; this seems to be expected due to multiple hot reload runtimes being instantiated.
  • Only that same block's CSS updates
  • viewScript works (and also does seem to hot reload fine regardless of number of blocks)

After making changes as suggested by @rafaucau :

  • Blocks fast refresh just fine
  • CSS updates just fine, but only if style is updated to: ["file:./style-index.css", "file:./index.css"]. I'm not even sure why style.scss is becoming style-index.css, tried looking through source but can't find anything indicating why this name change is happening
  • viewScript no longer works. Manually editing the generated js and adding a console log shows it's being loaded just fine, but the contents of the script aren't being executed. There's nothing obvious showing why.

I'd like to get this working properly, and contribute back to these scripts as they are extremely useful - any direction would be greatly appreciated so I can open a new issue with clearer details and possibly attempt at fixing this.

Edit:
In case anyone else is still having issues as well, for scope - I am building a tool for rapid theme development where blocks are installed in the theme (with plans to eventually allow this tool to target plugins instead if the user wishes - but the focus is on themes with theme-specific blocks), I realized that in most cases it's only necessary to live reload a single block type at a time, so here's what I'm using:

wp-scripts start --hot --webpack-src-dir=blocks/${name} --output-path=${getThemeDestination()}/blocks/${name}

So far it has solved all of my issues without the need to modify anything.

@gziolo
Copy link
Member Author

gziolo commented Oct 18, 2023

@jlandrum, thank you so much for sharing your use case and the way you approached moving forward by building only a single block at the time. It's a known limitation that we would like to resolve finally. I recently opened a pike PR against WordPress Core seeking a way to introduce shared scripts: WordPress/wordpress-develop#5118. So there are two ideas discussed currently:

  • We enable support for the runtime chunk in the development mode, which ensures that webpack can share its mechanism for controlling chunks between blocks.
  • Alternatively, we bundle all blocks together when targeting the editor, which means we remove the same issue using only a single entry point.

@jsnajdr might have some more thoughts to add on how we can address this recurring issue. Once we have it sorted out, we can also explore how to improve hot module reloading for the code that is outside React components. In particular, registerBlockType has this limitation in that it can be registered only once with a given name, so when reloading the file, we would have to unregister the block or lift the limitation in that mode. I documented my previous exploration around that part in #28273 (comment).

CSS updates just fine, but only if style is updated to: ["file:./style-index.css", "file:./index.css"]. I'm not even sure why style.scss is becoming style-index.css, tried looking through source but can't find anything indicating why this name change is happening

This is coming from this "optimization":

splitChunks: {
cacheGroups: {
style: {
type: 'css/mini-extract',
test: /[\\/]style(\.module)?\.(pc|sc|sa|c)ss$/,
chunks: 'all',
enforce: true,
name( _, chunks, cacheGroupKey ) {
const chunkName = chunks[ 0 ].name;
return `${ dirname(
chunkName
) }/${ cacheGroupKey }-${ basename( chunkName ) }`;
},
},

If I remember correctly, the idea was that there is a single style file extracted for every entry point so the names don't conflict if the JS files end up in the same folder. However, this might not make sense anymore, and it could benefit from an update. The initial reasoning seems to be captured in https://github.com/WordPress/gutenberg/tree/trunk/packages/scripts#using-css. It feels like enforcing a separate folder for every entry point would allow us having something like ["file:./index/style.css"], but it's also something that @jsnajdr has recently pointed out as it could get auto-generated in the block.json by the wp-scripts start / wp-scripts build so the path wouldn't matter that much anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Scripts /packages/scripts [Type] Build Tooling Issues or PRs related to build tooling
Projects
No open projects
Core JS
  
Done
Development

Successfully merging this pull request may close these issues.

None yet