JS architecture (v3.7.0+)

Status: Decision locked 2026-05-13 in Phase 5 of plan_v3.7.0.md (issue #390). First consumer (toast notifications) shipped in v3.7.0.

Decision

JS modules are authored in simple-wp-helpdesk/assets/src/ and built via @wordpress/scripts to simple-wp-helpdesk/assets/dist/. Dist files are committed so WordPress.org ZIP users do not need Node.

Rationale

@wordpress/components ships Modal, Notice, Button, ComboboxControl, Popover — directly covers v4.0’s modal/drawer/command-bar/tabs gaps without a second component library. The .asset.php files auto-generated by wp-scripts auto-generate the wp_enqueue_script dependency array. WordPress 6.0 (the v4.0 minimum) already loads wp-element (React) for the block editor, so declaring it as an external dependency adds ~0 KB to the plugin bundle. Webpack rebuild speed (1–3s) is fine for this plugin’s JS surface area.

Source / build layout

simple-wp-helpdesk/assets/
├── src/                      # ES modules (authored)
│   └── toast/index.js        # v3.7.0 PoC consumer
└── dist/                     # webpack output (committed)
    ├── toast.js
    └── toast.asset.php       # auto-generated deps + version hash

Entrypoints are declared in package.json build scripts as <name>=<path> pairs passed to wp-scripts build. Example: toast=toast/index.js emits toast.js and toast.asset.php in assets/dist/.

Bundle-size budget

≤40 KB gzip per entrypoint, excluding WP-shipped externals (wp-element, wp-components, wp-i18n, wp-data).

Initial measurement (v3.7.0, toast entrypoint): 512 bytes gzip (1,021 bytes uncompressed). The toast module imports no externals.

PHP-side enqueue pattern

$asset_file = SWH_PLUGIN_DIR . 'assets/dist/<name>.asset.php';
if ( file_exists( $asset_file ) ) {
    $asset = include $asset_file;
    wp_enqueue_script(
        'swh-<name>',
        SWH_PLUGIN_URL . 'assets/dist/<name>.js',
        $asset['dependencies'],
        $asset['version'],
        true
    );
}

The swh_enqueue_toast_script() helper in includes/helpers.php encapsulates this for the v3.7.0 toast entrypoint.

Component primitives planned on top of @wordpress/components

The v4.x roadmap will add these custom primitives where @wordpress/components does not provide an out-of-the-box equivalent:

  • Drawer (quick-reply panel)
  • VirtualList (inbox)
  • CommandBar (Ctrl/Cmd+K palette)

Modal, Notice, Button, ComboboxControl, Popover come from @wordpress/components directly.

Migration path

simple-wp-helpdesk/assets/swh-admin.js is the legacy unbuilt admin JS bundle. It stays in place for now; new functionality goes through the build, and existing pieces migrate piece-by-piece across v4.x. In v3.7 only the toast renderer was extracted — settings tabs, canned responses, and the rest of swh-admin.js are unchanged.

The legacy bundle keeps working because assets/src/toast/index.js assigns the renderer to window.swhToast — the existing call site in swh-admin.js still resolves the function as before.

CI integration

make e2e-docker depends on make js-build, which runs npm install (one-time) and npm run build. PHP-only gates (make test-docker) do not require Node — they validate the committed assets/dist/ directly.

Release ZIPs are built by release.yml via zip -r ... simple-wp-helpdesk/, which includes assets/dist/ automatically. No workflow changes were required.