@plaudit/webpack-extensions 2.84.0 → 2.85.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.85.0] - 2026-03-05
9
+ ### Added
10
+ - Support for inlining (and otherwise controlling the enqueuing of) assets
11
+ - This only applies to plain entrypoints and assets declared within block.json files at present
12
+
13
+ ## [2.84.1] - 2026-02-11
14
+ ### Fixed
15
+ - Typedef compatibility issues with Webpack 5.105.0
16
+
8
17
  ## [2.84.0] - 2026-01-30
9
18
  ### Added
10
19
  - Support for using `lazyLoader` on plain entrypoints
package/USER-GUIDE.md ADDED
@@ -0,0 +1,598 @@
1
+ <!-- TOC -->
2
+ * [General Information](#general-information)
3
+ * [What is This?](#what-is-this)
4
+ * [Why is This?](#why-is-this)
5
+ * [How to Read This Guide](#how-to-read-this-guide)
6
+ * [General](#general)
7
+ * [Paths](#paths)
8
+ * [Examples](#examples)
9
+ * [Best Practices](#best-practices)
10
+ * [Folder Structure](#folder-structure)
11
+ * [Blocks](#blocks)
12
+ * [Extensions](#extensions)
13
+ * [Plain Assets](#plain-assets)
14
+ * [Configuration](#configuration)
15
+ * [Quick Start](#quick-start)
16
+ * [1. Create webpack.config.js](#1-create-webpackconfigjs)
17
+ * [2. Set Up Your File Structure](#2-set-up-your-file-structure)
18
+ * [3. Include unified-loader.php in Your Plugin](#3-include-unified-loaderphp-in-your-plugin)
19
+ * [4. Run Build Commands](#4-run-build-commands)
20
+ * [Using Asset Handles in PHP](#using-asset-handles-in-php)
21
+ * [Handle Format](#handle-format)
22
+ * [Finding Your Handles](#finding-your-handles)
23
+ * [Example: Manual Enqueue with Localization](#example-manual-enqueue-with-localization)
24
+ * [Common Patterns](#common-patterns)
25
+ * [Pattern 1: Frontend-Only Script](#pattern-1-frontend-only-script)
26
+ * [Pattern 2: Conditional Loading (Manual Enqueue)](#pattern-2-conditional-loading-manual-enqueue)
27
+ * [Pattern 3: Admin-Only Styles](#pattern-3-admin-only-styles)
28
+ * [Pattern 4: Block Editor Styles](#pattern-4-block-editor-styles)
29
+ * [Reference](#reference)
30
+ * [Root Options](#root-options)
31
+ * [Per-Entrypoint Options](#per-entrypoint-options)
32
+ * [Boolean-form](#boolean-form)
33
+ * [String-form](#string-form)
34
+ * [Object-form](#object-form)
35
+ * [Additional Dependencies](#additional-dependencies)
36
+ * [In webpack.config.js (per entrypoint)](#in-webpackconfigjs-per-entrypoint)
37
+ * [First-line comment in the entry source file](#first-line-comment-in-the-entry-source-file)
38
+ * [Entrypoint Types](#entrypoint-types)
39
+ * [Blocks](#blocks-1)
40
+ * [File Structure](#file-structure)
41
+ * [Notes](#notes)
42
+ * [Per-Entrypoint Options](#per-entrypoint-options-1)
43
+ * [Extensions](#extensions-1)
44
+ * [File Structure](#file-structure-1)
45
+ * [File Naming](#file-naming)
46
+ * [Notes](#notes-1)
47
+ * [Per-Entrypoint Options](#per-entrypoint-options-2)
48
+ * [Plain](#plain)
49
+ * [File Structure](#file-structure-2)
50
+ * [Per-Entrypoint Options](#per-entrypoint-options-3)
51
+ * [The Locations Object](#the-locations-object)
52
+ * [WordPress Types](#wordpress-types)
53
+ * [WordPress Script Args](#wordpress-script-args)
54
+ * [Supported File Types](#supported-file-types)
55
+ * [Need Help?](#need-help)
56
+ <!-- TOC -->
57
+
58
+ # General Information
59
+
60
+ ## What is This?
61
+
62
+ This webpack wrapper automates the process of compiling and loading assets for WordPress sites.
63
+ It is guaranteed to work on all Plaudit-made themes and plugins and can be dropped into most non-Plaudit-made plugins and themes with minimal edits to their structure.
64
+
65
+ It does this by taking advantage of patterns in how WordPress expects assets to be provided combined with a dash of template-generated PHP.
66
+
67
+ You only need to configure `webpack.config.js` and run `pnpm run watch` or `pnpm run build`.
68
+
69
+ ## Why is This?
70
+
71
+ This webpack wrapper started out as a method of mapping the source names to destination names automatically. Over time, it has expanded to automate all the mapping that WordPress expects developers to do manually.
72
+ Its output has *significant* performance boosts compared to what following WordPress's guides will get by eliminating *all* folder iteration and replacing the `O(N)` asset configuration loading that following WordPress' guides produces with one that requires only a single file per entrypoint category (root loader, image/font/etc assets, blocks, extensions, and plain).
73
+
74
+ In addition to the improved loading performance and working as a vehicle for distributing improvements to the loading code across sites (even when the loading code is in unmanaged themes and plugins), it also provides a few minor enhancements over WordPress' own webpack wrapper:
75
+ - CSS versioning
76
+ - While WordPress *appears* to generate version hashes for CSS files, they aren't actually based on the contents of the CSS files
77
+ - Automatic filename conflict resolution
78
+ - This one isn't strictly necessary, but if you want to have both `view-script.ts` and `view-style.pcss`, this'll make it work!
79
+ - This conflict handling also extends to taking steps to avoid assets conflicting with ones from other plugins or themes
80
+ - Non-bundled asset versioning (images, fonts, etc)
81
+ - This is a standard webpack feature. It's just disabled by how WordPress's stuff
82
+
83
+ When combined with [`pnpx @plaudit/scaffold`](https://bitbucket.org/plaudit/scaffold/src/main/README.md), no manual configuration should be needed for 99% of client work.
84
+ However, if you need to do something unusual or just want to know what everything in the config file actually does, this guide is for you!
85
+
86
+ ## How to Read This Guide
87
+ ### General
88
+ - When in doubt, roll with the default
89
+ - Due to naming differences, you will sometimes see `Entrypoint` being used to refer to things in the `src` object
90
+ - For brevity, "assets" will be used in place of "scripts and styles"
91
+ - This guide assumes that you are using the most recent versions of the loader logic
92
+ - This guide is primarily informational, so you will be seeing the *every* flag, not just "recommended" ones
93
+ - If what you are looking at seems weirdly specific or excessively complicated, check if it's marked with **[Advanced]** or **[Legacy]**. There are a lot of highly situational and/or weird flags that are only useful when hyper-optimizing asset loading
94
+
95
+ ### Paths
96
+ - Any time that `src` is referenced in a path, it should be replaced with the value of `srcDir` in your WebPack file
97
+ - To be crystal clear, the value of `srcDir` *should be* `src`; however, this might not be the case in some inherited or older code
98
+ - Any time that `dist` is referenced in a path, it should be replaced with the value of `outputDir` in your WebPack file
99
+ - As with `src`, the value of `outputDir` *should be* `dist`; however, this might not be the case in some inherited or older code
100
+ - Keys in the `src` *object* are all assumed to be paths relative to `srcDir` if it is specified or the folder in which the `webpack.config.js` file is located if it is not specified
101
+ - Paths in values in the `src` *object* are all assumed to be paths relative to `outputDir` if it is specified or the folder in which the `webpack.config.js` file is located if it is not specified
102
+ - All file names are informational placeholders. They can be whatever you want provided that they are web-safe (basically, don't do things like calling the email address block "✉️" and you'll be fine)
103
+
104
+ ### Examples
105
+ - Any uses of `acme-my-plugin` should be replaced with your plugin or theme's kebab-case name (ex: `acme-my-plugin.wp-admin` => `plaudit-base.wp-admin`)
106
+
107
+ ---
108
+
109
+ ## Best Practices
110
+ ### Folder Structure
111
+ - All folder and file names should be in kebab-case
112
+ - Assets *should not* be in the root of the `src` folder. Assets that aren't block- or extension-bound should be in the `site` folder (or in a folder named after where they'll be used like, `admin` or `map-page`)
113
+
114
+ ### Blocks
115
+ - Block folder names *should* match the local portion of their name (ex: `plaudit-query-loop-maps/address-wrapper` should be stored in `address-wrapper`)
116
+
117
+ ### Extensions
118
+ - Extensions *should not* be repeated for multiple blocks. If you find that happening, move it to a site-level asset that gets loaded at the appropriate time.
119
+ - This can be done pretty easily via `pnpm dlx @plaudit/scaffold add site asset`
120
+ - Extensions *should not* be applied to site-specific blocks (basically, only use extensions for stuff that is from WordPress, pulled in via composer, or is from a 3rd party)
121
+
122
+ ### Plain Assets
123
+ - Plain assets *should be your last option*. They have the least amount of granularity in where they can be included, which can easily lead to serving bloated code.
124
+ - Just because you *can* have multiple folders doesn't mean that you *should*
125
+
126
+ ### Configuration
127
+ - A good configuration file is one that does not include any unnecessary configuration (ex: if you won't be manually enqueuing an asset or referencing it elsewhere, don't give it a named handle)
128
+
129
+ ---
130
+
131
+ ## Quick Start
132
+
133
+ ### 1. Create webpack.config.js
134
+ This is automatically created and populated when running any [scaffold](https://bitbucket.org/plaudit/scaffold/src/main/README.md) command.
135
+
136
+ The config tells webpack **what** to build and **where** to load it in WordPress.
137
+
138
+ ```javascript
139
+ module.exports = require("@plaudit/webpack-extensions/wordpress-scripts-wrapper")({
140
+ src: {
141
+ // Build all blocks in src/blocks/
142
+ "blocks": true,
143
+
144
+ // Build block extensions from src/extensions/
145
+ "extensions": {directoryLayout: 'extensions'},
146
+
147
+ // Auto-load in the head on frontend
148
+ "site/index-header.ts": {
149
+ locations: {
150
+ clientView: true,
151
+ registerScriptArgs: false
152
+ }
153
+ },
154
+
155
+ // Auto-load at the bottom of the body on frontend
156
+ "site/index-footer.ts": {
157
+ locations: {
158
+ clientView: true,
159
+ registerScriptArgs: 'lazy'
160
+ }
161
+ },
162
+ // Auto-load in admin
163
+ "site/wp-admin.ts": {
164
+ locations: {
165
+ admin: true
166
+ }
167
+ },
168
+ // Auto-load in admin
169
+ "site/wp-admin.pcss": {
170
+ locations: {
171
+ admin: true
172
+ }
173
+ },
174
+ // Auto-load in the block editor
175
+ "site/block-editor.pcss": {
176
+ locations: {
177
+ clientEditor: true
178
+ }
179
+ },
180
+ // Auto-load in the head on frontend
181
+ "site/public.pcss": {
182
+ locations: {
183
+ clientView: true
184
+ }
185
+ },
186
+ // A script that can be enqueued via its handle, but is not autoloaded
187
+ "site/manually-loaded.ts": {
188
+ locations: "plaudit-theme/manually-loaded-script"
189
+ },
190
+ // A script that will be inlined into the footer
191
+ "site/inlined-script.ts?inline=true": {
192
+ locations: "plaudit-theme/inlined-script"
193
+ }
194
+ },
195
+ useWebpackResourceFiltering: true, // Always use this!
196
+ extensionsVersion: 3,
197
+ plainEntrypointsVersion: 2,
198
+ srcDir: "src", // Always use this!
199
+ outputDir: "dist", // Always use this!
200
+ useUnifiedLoader: true, // Always use this!
201
+ variables: {
202
+ font_size: 16 // Required for pxAsRem to work; replace the 16 with your site's base font size
203
+ }
204
+ });
205
+ ```
206
+
207
+ ### 2. Set Up Your File Structure
208
+
209
+ **Blocks** (subdirectories with block.json):
210
+ - **Config:** `'blocks': true`
211
+ - **File Structure:** [See Here](#file-structure)
212
+
213
+ **Extensions** (flat files that modify existing blocks):
214
+ - **Config:** `'extensions': {directoryLayout: 'extensions'}`
215
+ - **File Structure:** [See Here](#file-structure-1)
216
+
217
+ **Other Files** (scripts, styles):
218
+ - **Config:** List each file individually in `src` object
219
+ - **File Structure:** [See Here](#file-structure-2)
220
+
221
+ ### 3. Include unified-loader.php in Your Plugin
222
+ After building, include the generated loader file in the plugin's main PHP file. [Scaffold](https://bitbucket.org/plaudit/scaffold/src/main/README.md) commands will offer to add this to the plugin file if needed.
223
+
224
+ **Example:**
225
+ ```php
226
+ <?php
227
+ /**
228
+ * Plugin Name: My Plugin
229
+ */
230
+
231
+ @include_once __DIR__ . '/dist/unified-loader.php';
232
+ ```
233
+
234
+ This file automatically:
235
+ - Registers all your scripts and styles
236
+ - Enqueues them in the right places
237
+ - Handles dependencies
238
+ - Sets up blocks and extensions
239
+
240
+ ### 4. Run Build Commands
241
+ While you *can* manually run these commands, using `theapp pack dev/watch/build` is preferred
242
+
243
+ ```bash
244
+ pnpm run watch # Development mode (watches for changes)
245
+ pnpm run build # Production build
246
+ ```
247
+
248
+ ---
249
+
250
+ ## Using Asset Handles in PHP
251
+
252
+ After building, each asset gets a handle you can reference in PHP.
253
+
254
+ ### Handle Format
255
+
256
+ **Plain:** `{prefix}.{filename}`
257
+ - Example: `acme-my-plugin.admin-editor`
258
+
259
+ **Blocks:** `{prefix}_blocks_{block-name}-{type}`
260
+ - Example: `acme-my-plugin_blocks_hero-banner-editor-script`
261
+ - Block handles are subject to runtime-change, so they cannot be safely referenced
262
+
263
+ **Extensions:** `{prefix}_block-extensions_{block-name}-{type}`
264
+ - Example: `acme-my-plugin_block-extensions_hero-banner-editor-script`
265
+ - Extension handles are subject to runtime-change, so they cannot be safely referenced
266
+
267
+ ### Finding Your Handles
268
+
269
+ **Best way:** Check the generated loader files after building:
270
+ - `dist/blocks/blocks-loader.php`
271
+ - `dist/extensions/extensions-loader.php`
272
+ - The first argument of the `wp_register_script` and `wp_register_style` calls in `dist/plain-entrypoints-loader.php`
273
+
274
+ ### Example: Manual Enqueue with Localization
275
+
276
+ ```php
277
+ <?php
278
+ // For manually-enqueued assets
279
+ add_action('admin_enqueue_scripts', function($hook) {
280
+ if ($hook === 'post.php') {
281
+ // Localize data first (optional)
282
+ wp_localize_script('acme-my-plugin.admin-editor', 'myData', [
283
+ 'ajaxUrl' => admin_url('admin-ajax.php'),
284
+ 'nonce' => wp_create_nonce('my_ajax_action'),
285
+ ]);
286
+
287
+ // Then enqueue
288
+ wp_enqueue_script('acme-my-plugin.admin-editor');
289
+ wp_enqueue_style('acme-my-plugin.admin-editor');
290
+ }
291
+ });
292
+ ```
293
+
294
+ ---
295
+
296
+ ## Common Patterns
297
+
298
+ ### Pattern 1: Frontend-Only Script
299
+
300
+ ```javascript
301
+ // webpack.config.js
302
+ src: {
303
+ 'site/public.ts': {
304
+ locations: {
305
+ clientView: true,
306
+ registerScriptArgs: 'lazy'
307
+ }
308
+ }
309
+ }
310
+ ```
311
+
312
+ ### Pattern 2: Conditional Loading (Manual Enqueue)
313
+
314
+ ```javascript
315
+ // webpack.config.js
316
+ src: {
317
+ 'post-editor.ts': {
318
+ locations: { register: true } // Don't auto-load
319
+ }
320
+ }
321
+ ```
322
+
323
+ ```php
324
+ <?php
325
+ // In your plugin
326
+ add_action('admin_enqueue_scripts', function($hook) {
327
+ if ($hook === 'post.php') {
328
+ wp_enqueue_script('acme-my-plugin.post-editor');
329
+ }
330
+ });
331
+ ```
332
+
333
+ ### Pattern 3: Admin-Only Styles
334
+
335
+ ```javascript
336
+ src: {
337
+ 'admin/styles.pcss': {
338
+ locations: { admin: true }
339
+ }
340
+ }
341
+ ```
342
+
343
+ ### Pattern 4: Block Editor Styles
344
+
345
+ ```javascript
346
+ // webpack.config.js
347
+ src: {
348
+ 'editor/custom-editor-styles.pcss': {
349
+ locations: { clientEditor: true }
350
+ }
351
+ }
352
+ ```
353
+
354
+ ---
355
+
356
+ # Reference
357
+
358
+ ## Root Options
359
+ | Option | Type | Default | Description |
360
+ |------------------------------------|-----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
361
+ | `src` | `object` | **Required** | Files/directories to process (see the next section for what you can put in here) |
362
+ | `srcDir` | `string` | `""` | Source directory (**Required** on new sites) |
363
+ | `outputDir` | `string` | `""` | Output directory (**Required** on new sites) |
364
+ | `useUnifiedLoader` | `boolean` | `false` | Generate unified-loader.php (always set to `true` on new sites!) |
365
+ | `useWebpackResourceFiltering` | `boolean` | `false` | Generates versioned copies of images, fonts, etc (always set to `true` on new sites!) |
366
+ | `plainEntrypointsVersion` | `1\|2` | `1` | Use 2 for new sites |
367
+ | `extensionsVersion` | `1\|2\|3` | `1` | Use 3 for new sites |
368
+ | `verbose` | `boolean` | `false` | Verbose logging |
369
+ | `variables` | `object` | Auto | CSS/JS variables. If a variables.js file is present, this will automatically load from that file |
370
+ | `onlyRunPostCSSOnPCSS` | `boolean` | `false` | If true, the PostCSS processor will not be run on CSS files. This is true for all new sites and can be safely enabled on most sites if desired. |
371
+ | `assumeGlobalizedPlauditLibraries` | `boolean` | `true` | **[Advanced]** When `false`, normally-externalized plaudit libraries will be included.<br>**DO NOT USE THIS. IF YOU SEE IT BEING USED, CONTACT JOSH** |
372
+ | `externals` | `object` | - | **[Advanced]** Allows dependencies to be marked as external. This prevents them from being included in the bundle under the assumption that they will be provided via an alternate mechanism |
373
+ | `targetHandlePrefix` | `string` | Auto | **[Legacy]** Prefix for handles. Auto-detected from composer.json if omitted. Do not set this unless absolutely necessary |
374
+
375
+ ---
376
+
377
+ ## Per-Entrypoint Options
378
+ This section covers the shared options for entrypoints. See the [Entrypoint Types](#entrypoint-types) section for options specific to individual types
379
+
380
+ ### Path Queries
381
+ - These are URL-style queries added to the end of entrypoint *source* paths and are used to set entrypoint-specific properties in Plain and Block contexts.
382
+ - At present, this is only being used to configure inlining, but expansion to other systems is being considered
383
+ - The available options are: `strategy`, `inline`, `in_footer`, `fetchpriority`, and `position`
384
+
385
+ ### Boolean-form
386
+ - This is only available if `outputDir` has been set
387
+ - The only supported value is `true` and only works for `blocks` and `plain` entrypoints. It means that every value will have its default value
388
+ - In the case of `plain` entrypoints, they will need to be manually enqueued, so using it is not advised - it's just *technically* possible
389
+ - The reason that it doesn't work for `extensions` entrypoints is that `extensions` are not reliably distinguishable from `blocks` and `blocks` is the default entrypoint type
390
+ - The output directory will be the same as the source directory except that it will be under the `outputDir`
391
+
392
+ ### String-form
393
+ - This is only available for `blocks` and `plain` entrypoints
394
+ - This is equivalent to `{destination: <value here>}`
395
+ - It is otherwise the same as the [Boolean form](#boolean-form)
396
+ - The value is treated as the output directory relative to `outputDir` if it is specified or the folder in which the `webpack.config.js` file is located if it is not specified
397
+
398
+ ### Object-form
399
+ - This is necessary for `extensions` entrypoints and the preferred form for `plain` entrypoints
400
+ - In general, `blocks` entrypoints should use either [Boolean](#boolean-form)- or [String](#string-form)-form
401
+ - `plain` entrypoints have additional options available. They can be found in its [entrypoint type section](#plain)
402
+
403
+ | Option | Type | Default | Description |
404
+ |------------------------------------|-----------------------------|----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
405
+ | `directoryLayout` | `blocks\|extensions\|plain` | Auto | This should only be set for `extensions` entrypoints |
406
+ | `destination` | `string` | Auto when `outputDir` is set, none otherwise | **[Required when `outputDir` is not set]** Sets the output path<br>**This should not be set when `outputDir` is set** |
407
+ | `bundleAnalyzer` | `boolean` | `false` | **[Advanced]** Enable bundle analyzer |
408
+ | `lazyLoader` | `string` | - | **[Advanced]** **For `blocks` and `extensions` entrypoints only**<br>Specifies the name of a function that must be called in order to load the entrypoint<br>See [The Locations Object](#the-locations-object) for how to achieve this for `plain` entrypoints |
409
+ | `assumeGlobalizedPlauditLibraries` | `boolean` | Root Value | **[Advanced]** When `false`, normally-externalized plaudit libraries will be included.<br>**DO NOT USE THIS. IF YOU SEE IT BEING USED, CONTACT JOSH** |
410
+
411
+ ---
412
+
413
+ ## Additional Dependencies
414
+
415
+ When WordPress registers or enqueues a script or style, it accepts a **dependencies** argument: an array of handles that must be loaded before the asset. This library discovers most dependencies from your imports; however, for any dependency that is not imported (i.e., a script provided by another plugin that your bundle expects to be present at runtime), you can declare **additional dependencies** so they are included in the generated loader.
416
+
417
+ You can specify additional dependencies in either of two ways (or both - they are merged).
418
+
419
+ ### In webpack.config.js (per entrypoint)
420
+
421
+ Set `additionalDependencies` on the entrypoint config. This applies to **plain** entrypoints (object-form) and any entrypoint type that supports the per-entrypoint options table above.
422
+
423
+ ```javascript
424
+ // webpack.config.js
425
+ src: {
426
+ 'site/checkout.ts': {
427
+ locations: { clientView: true },
428
+ additionalDependencies: ['axios', 'some-plugin/script-handle']
429
+ }
430
+ }
431
+ ```
432
+
433
+ Dependencies are WordPress script/style handles (strings). They will be passed through as the `deps` array when the asset is registered.
434
+
435
+ ### First-line comment in the entry source file
436
+
437
+ In the **first line** of the entrypoint source file (e.g., your `.ts` or `.js` file), you can use a special comment. If that line starts with `//ADDITIONAL_DEPENDENCIES:` (with no space after the colon in the prefix), the rest of the line is treated as a comma-separated list of dependency handles and added to the entrypoint’s additional dependencies.
438
+
439
+ ```javascript
440
+ //ADDITIONAL_DEPENDENCIES: axios, some-plugin/script-handle
441
+ import { doCheckout } from './checkout-helpers';
442
+ // ...
443
+ ```
444
+
445
+ This is useful when you want the dependency list to live next to the code that relies on it, or when different entrypoints are built from the same config and you want to vary dependencies per file.
446
+
447
+ If you use both methods for the same entrypoint, the dependencies from the config and from the first-line comment will be combined.
448
+
449
+ ---
450
+
451
+ ## Entrypoint Types
452
+
453
+ ### Blocks
454
+ This was first entrypoint type added, and, due to how it integrates with WordPress, it both has and needs the least amount of configuration.
455
+ In fact, under most circumstances, the proper configuration value is just `true`.
456
+
457
+ #### File Structure
458
+ Subdirectories with block.json files
459
+ ```
460
+ src/blocks/
461
+ ├── hero-banner/
462
+ │ ├── block.json
463
+ │ ├── index.ts
464
+ │ ├── style.pcss
465
+ │ └── template.php
466
+ ```
467
+
468
+ #### Notes
469
+ - Blocks **should** be created with `pnpm @plaudit/scaffold create block`
470
+ - template.php and setup.php files are automatically loaded; however, they can be manually specified if desired
471
+ - Script and Style files **must** be specified using the `file:./<path here>` syntax in the appropriate keys. See [WordPress' `block.json` reference](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/) for further details
472
+
473
+ #### Per-Entrypoint Options
474
+ The `blocks` entrypoint type doesn't have any.
475
+
476
+ ### Extensions
477
+ This is used to associate additional assets with blocks that are not in control of the current project. This most-commonly means built-in WordPress blocks, but it can be used with any block.
478
+
479
+ #### File Structure
480
+ [Specially named files](#file-naming) in a single subdirectory of `src`
481
+ ```
482
+ src/extensions/
483
+ ├── core-paragraph-view-script.ts
484
+ └── core-paragraph-editor-style.pcss
485
+ ```
486
+
487
+ #### File Naming
488
+ Filenames **must** follow the pattern: `{kebab-case-block-name}-{type}.{ext}`
489
+ - Valid values for `type` are:
490
+ - `script`, `editor-script`, `view-script`
491
+ - `style`, `editor-style`, `view-style`
492
+ - `script-module`, `view-script-module`
493
+ - `setup` (this allows for PHP code to be loaded only when certain blocks are enabled and is intended for use in plugins, not themes)
494
+ - `ext` **must** be for a [supported file type](#supported-file-types) and **should** correspond with the extension type (basically, don't enqueue a `.css` file as a script)
495
+
496
+ #### Notes
497
+ - In order to have a directory be treated as `extensions`, the config **must** include `directoryLayout: 'extensions'`
498
+ - Extensions **should** be created with `pnpm @plaudit/scaffold create extension`
499
+
500
+ #### Per-Entrypoint Options
501
+ The `extensions` entrypoint type doesn't have any.
502
+
503
+ ### Plain
504
+ These entrypoints both support and need the largest amount of configuration. While all options will be listed here, the only one that you should need in sites is `locations`.
505
+
506
+ While `plain` entrypoints *can* be used for directory-based loading, that is a deprecated feature and **must not** be used in new projects
507
+
508
+ #### File Structure
509
+ Files in arbitrary subdirectories of src
510
+ ```
511
+ src/
512
+ ├── admin/
513
+ │ ├── editor.ts
514
+ │ └── editor.pcss
515
+ ├── site/
516
+ │ ├── public.ts
517
+ │ └── public.pcss
518
+ ```
519
+
520
+ #### Per-Entrypoint Options
521
+ | Option | Type | Default | Description |
522
+ |--------------------------|--------------------------------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------|
523
+ | `locations` | `object \| string \| fn(string) => string` | - | Where/how to load the asset. See the [Locations Object](#the-locations-object) section below for how to use this |
524
+ | `additionalDependencies` | `string[]` | - | **[Advanced]** Used to specify additional assets that the entrypoint depends on by handle |
525
+ | `externalize` | `string[]` | - | **[Advanced]** Specifies the object path at which the exports of the entrypoint should be emitted. This is used for creating shared libraries |
526
+ | `withLegacyBlocksIn` | `string` | - | **[Legacy]** Used to load legacy blocks that predate our use of `block.json`. This should **never** be used on new sites. |
527
+
528
+ ##### The Locations Object
529
+ **String-form**:
530
+ - Equivalent to `{handle: <value here>}`. See the Object-form section below for more information
531
+
532
+ **Function-form**:
533
+ - Equivalent to `{handle: <function here>}`. See the Object-form section below for more information
534
+
535
+ **Object-form**:
536
+
537
+ This is the form that *should* be used. It has two categories of keys: control flags and location identifiers. As such, they have been split out into two blocks
538
+
539
+ **Control Flags:**
540
+
541
+ | Key | Type | Default | Description |
542
+ |----------------------|--------------------------------------------------------------------------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------|
543
+ | `handle` | `string \| fn(string) => string` | Auto | The handle by which the entrypoint will be referenced. The function form is passed the default handle for manual tweaking |
544
+ | `register` | `boolean \| number` | `true` | **[Advanced]** Whether the entrypoint should be registered at all or, if a number, the priority of the hook in which the registration will occur |
545
+ | `registerScriptArgs` | `boolean` \| `'lazy'` \| [`WordPressScriptArgs`](#wordpress-script-args) | Auto | The loading flags (strategy, in_footer, and fetchpriority) for the script.<br>'lazy' is an alias for `{strategy: 'defer', in_footer: true}` |
546
+
547
+ **Location Identifiers:**
548
+
549
+ All location identifiers can be either a `boolean` or `number`. If they are a number, it sets the priority for the hook that is used to *enqueue* the resulting asset
550
+
551
+ | Identifier | Hook | Purpose |
552
+ |----------------|-------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
553
+ | `clientView` | `wp_enqueue_scripts` | Enqueues the asset on every visitable webpage. Block- or extension-based registration should generally be preferred |
554
+ | `clientEditor` | `enqueue_block_editor_assets` | Enqueues the asset for use with the editor *shell*. Assets that should be used in the editor *content* must be enqueued manually (or be loaded by blocks) |
555
+ | `blockAssets` | `enqueue_block_assets` | Enqueues the asset everywhere that block assets are enqueued. This includes *both* visitable webpages *and* the editor *content* |
556
+ | `admin` | `admin_enqueue_scripts` | Enqueues the asset on every admin page; additionally supports `hook_name` mode (see below) |
557
+ | `login` | `login_enqueue_scripts` | Enqueues the asset on the login page |
558
+ | `analytics` | `plaudit_enqueue_analytics` | A special version of `clientView` that only fires if enqueuing analytics code is allowed. Requires the `Plaudit Analytics Integrations` plugin. |
559
+ | `customizer` | `customizer_enqueue_scripts` | **[Legacy]** Enqueues the asset on legacy customizer page. Don't use this one. |
560
+
561
+ **`hook_name` mode**
562
+ - Allows the "hook name" (while WordPress calls it "hook name", it's actually the admin page identifier) to be used as an additional qualifier on whether the asset gets enqueued.
563
+ - This is currently only supported for the `admin` location
564
+
565
+ ## WordPress Types
566
+ ### WordPress Script Args
567
+ **Boolean-form:**
568
+
569
+ If `true`, the script is emitted in the footer. Defaults to `false`.
570
+
571
+ **Object-form:**
572
+
573
+ | Option | Type | Default | Description |
574
+ |-----------------|-----------------------------------|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
575
+ | `strategy` | `'defer' \| 'async' \| undefined` | `undefined` | Allows the script loading to be delayed. See [WordPress' docs](https://developer.wordpress.org/reference/functions/wp_register_script/#delayed-script-loading) for more information |
576
+ | `in_footer` | `boolean \| undefined` | `false` | If `true`, enqueues the script at the end of the body. See [WordPress' docs](https://developer.wordpress.org/reference/functions/wp_register_script/#delayed-script-loading) for more information |
577
+ | `fetchpriority` | `'auto' \| 'low' \| 'high'` | `'auto'` | **[Advanced]** Allows direct control of the script's fetchpriority.<br>WordPress does not currently have documentation for this option |
578
+
579
+ ---
580
+
581
+ ## Supported File Types
582
+
583
+ | Group | Extensions |
584
+ |---------------------------|------------------------------------------------------------|
585
+ | **JavaScript/TypeScript** | `.js`, `.jsx`, `.ts`, `.tsx`, `.mjs`, `.mts` |
586
+ | **Stylesheets** | `.css`, `.pcss` (PostCSS), `.scss`, `.sass` |
587
+ | **Assets** | `.svg`, `.png`, `.jpg`, `.webp`, `.woff`, `.woff2` |
588
+ | **Special** | `block.json`, `template.php`, `template.twig`, `setup.php` |
589
+
590
+ ---
591
+
592
+ ## Need Help?
593
+
594
+ 1. Enable verbose logging: `verbose: true` in config
595
+ 2. Check generated files in `dist/` folder
596
+ 3. Look at config files: `dist/**/config.php`
597
+ 4. Check `dist/unified-loader.php` for registered assets
598
+ 5. Review the README.md for technical details
@@ -1,7 +1,7 @@
1
- import { Compilation, Compiler, type WebpackPluginInstance } from "webpack";
1
+ import { Compilation, Compiler } from "webpack";
2
2
  import { PseudoSemaphore } from "../utils/pseduo-semaphore";
3
3
  import type { VerifiedPlauditWordpressWebpackConfig } from "../utils/common-config-helpers";
4
- import { type ParsedAssetJsonProvider } from "../shared";
4
+ import { type ParsedAssetJsonProvider, WebpackPlugin } from "../shared";
5
5
  type TapWithAssetsJsonOptions = {
6
6
  name?: string;
7
7
  stage?: (typeof Compilation.PROCESS_ASSETS_STAGE_REPORT) | (typeof Compilation.PROCESS_ASSETS_STAGE_ANALYSE);
@@ -9,7 +9,7 @@ type TapWithAssetsJsonOptions = {
9
9
  };
10
10
  type TapWithAssetsJsonFn = Parameters<Compilation['hooks']['processAssets']['tapPromise']>[1];
11
11
  type TapWithParsedAssetsJsonFn = (parsedAssetJsonProvider: ParsedAssetJsonProvider, assets: Parameters<TapWithAssetsJsonFn>[0]) => Promise<void> | void;
12
- export declare abstract class AbstractBiPhasicGroupPlugin implements WebpackPluginInstance {
12
+ export declare abstract class AbstractBiPhasicGroupPlugin implements WebpackPlugin {
13
13
  protected readonly config: VerifiedPlauditWordpressWebpackConfig;
14
14
  readonly group: string;
15
15
  private readonly semaphores;
@@ -1,5 +1,6 @@
1
+ import { type WebpackPlugin } from "../shared";
1
2
  import browserSync, { type BrowserSyncInstance } from "browser-sync";
2
- import type { Compiler, WebpackPluginInstance } from "webpack";
3
+ import type { Compiler } from "webpack";
3
4
  export type PluginOptions = {
4
5
  reload: boolean;
5
6
  name: string;
@@ -7,7 +8,7 @@ export type PluginOptions = {
7
8
  injectCss: boolean;
8
9
  middlewareBuilder?: (options: browserSync.Options) => browserSync.Options['middleware'];
9
10
  };
10
- export declare class BrowserSyncPlugin implements WebpackPluginInstance {
11
+ export declare class BrowserSyncPlugin implements WebpackPlugin {
11
12
  private static isBrowserSyncRunning;
12
13
  private static browserSyncPluginOptions?;
13
14
  private readonly pluginOptions;