Skip to Content
✨ WP Bones v2.0.3 is out! Check the Release Notes →
Documentation⬆️ Migrating to v2

Migrating from v1.x to v2.0

WP Bones v2.0 unifies the build pipeline around @wordpress/scripts and webpack, drops the old gulp + run-s + per-app-script approach, and standardises the developer commands across every plugin and boilerplate. This guide walks you through the upgrade.

TL;DR

For most plugins, the upgrade is a single command:

php bones migrate:to-v2 yarn install yarn build

That’s it. Everything under resources/assets/ is preserved, only the build infrastructure is swapped out. Read on for the full picture.

What changed

v2 is a hard break vs v1.x. If your plugin pulls wpbones/wpbones via dev-master, bump the constraint to ^2.0.0 after running the migrator.

Removed

  • gulpfile.js — the whole gulp pipeline is gone.
  • gulp, gulp-babel, gulp-clean-css, gulp-less, gulp-sass, gulp-typescript, gulp-uglify, gulp-watch, sass devDependencies.
  • npm-run-all — no more run-s orchestration.
  • Per-app scripts in package.json (build:apps, start:apps, build:widget, …). Webpack auto-discovers every entry now.

Added

  • webpack.config.js — a single file that scans resources/assets/ and builds everything.
  • tsconfig.json — TypeScript ready out of the box (JS still works).
  • .prettierrc, jest.config.js.
  • @wordpress/scripts ^31, typescript, glob, less-loader, webpack-remove-empty-scripts, @types/react*, @wordpress/jest-preset-default devDependencies.

Unified scripts

{ "scripts": { "dev": "wp-scripts start", "build": "wp-scripts build", "test": "wp-scripts test-unit-js", "test:watch": "wp-scripts test-unit-js --watch", "format": "wp-scripts format", "format:check": "wp-scripts format --check", "lint": "wp-scripts lint-js resources/", "lint:style": "wp-scripts lint-style 'resources/**/*.{css,scss}'" } }

Same shape in every v2 plugin and boilerplate. Once you know one, you know them all.

New bones commands

Package manager

v2 uses yarn. package-lock.json is deleted during migration; a fresh yarn.lock is generated by yarn install.

Running the migrator

Commit your work

The migrator rewrites several files. Starting from a clean git state makes rollback trivial.

git status git commit -am "snapshot before v2 migration"

Bump the framework constraint

Edit composer.json:

"require": { "php": ">=8.1", "wpbones/wpbones": "^2.0.0" }

Update dependencies

composer update

Run the migrator

php bones migrate:to-v2

You’ll see a y/N prompt summarising what it will touch. Say y.

Reinstall and build

The migrator deletes your previous lockfile (package-lock.json or pnpm-lock.yaml) so you can pick up a clean one. The “Next steps” it prints at the end use the package manager it detected in your project before deletion — yarn, npm or pnpm — so you don’t have to switch tools unless you want to. The snippets below assume yarn (the v2 default); see Using npm or pnpm instead of yarn if you use a different PM.

yarn install yarn build

Verify

Open the plugin’s admin page in WordPress. Any React app you had under resources/assets/apps/ should still mount.

yarn test # if you had tests

Using npm or pnpm instead of yarn

The v2 boilerplates are yarn-first — they ship a committed yarn.lock and the CLI’s “Next steps” default to yarn — but there is no technical lock-in on yarn:

  • package.json has no packageManager, engines or resolutions fields.
  • There is no .yarnrc.yml, .npmrc or .pnpmrc.
  • All scripts are wp-scripts <verb>, so npm run build, pnpm build and yarn build produce identical output.
  • php bones deploy --pkgm=<pm> already accepts yarn, npm or pnpm.

Why yarn-first?

The choice is pragmatic rather than technical: WP Bones and a few adjacent React/TS projects maintained by the same author (including the dedicated Mantine boilerplate) standardize on yarn so tooling, CI, and day-to-day commands stay consistent across the ecosystem. It is not a claim that yarn is technically superior — pnpm, for instance, has excellent benchmarks and strict dependency resolution. If community preference shifts, swapping the committed lockfile is a non-event and shipping multiple lockfiles as equally first-class remains on the table.

How to use a different PM

If you want to keep using the package manager you had in your v1.x plugin (or switch to a new one), the migrator has your back: it detects your lockfile (yarn.lock, pnpm-lock.yaml or package-lock.json) before deleting it, and the printed “Next steps” match the PM you were already using. Just run the commands it prints, and you’re done.

Starting from a freshly cloned boilerplate and want to use npm or pnpm instead of yarn? Delete the committed yarn.lock, then npm install or pnpm install. The scripts in package.json will work as-is with any of the three package managers.

Pick one PM per plugin and stick with it. Mixing lockfiles in the same repo (yarn.lock + package-lock.json) quickly leads to drift between what CI installs and what you get locally.

Migrating apps that used per-script entries

Migrating apps that used per-script entries

If your v1.x package.json had something like:

"build:apps": "wp-scripts build resources/assets/apps/app --output-path=public/apps/", "build:widget": "wp-scripts build resources/assets/apps/dashboard-widget --output-path=public/apps/dashboard-widget"

…you can delete them all. Just organise resources/assets/apps/ so each app is either:

  • A subfolder with index.{ts,tsx,js,jsx} — good for apps with components, e.g. apps/dashboard/index.tsx.
  • A single top-level file — good for tiny apps, e.g. apps/widget.tsx.

Webpack picks them up automatically. Output stays the same as before (public/apps/<name>.js + <name>.asset.php).

File extensions

v1.x boilerplates shipped app.jsx. v2 defaults to app.tsx because TypeScript is set up by default — but plain .js/.jsx still works. Rename at your leisure.

Custom gulp tasks

If your gulpfile.js had project-specific tasks (not the WP Bones defaults), they won’t be migrated automatically. Rewrite them as webpack plugins, a script in package.json, or a tiny shell command triggered by yarn dev.

Troubleshooting

”WPKirkMantine has already been declared”

A v1.x bug where withInlineScript double-enqueued inline code. Fixed in v2 framework. If you see it, make sure your vendor/wpbones/wpbones is at 2.0.0+.

The React app doesn’t mount

Check that the app name isn’t one of the reserved WordPress script handles. dashboard, post, jquery, etc. are owned by core and will silently replace your bundle.

”Class not found” when running composer update on a renamed plugin

This was a v1.x bootstrap issue that’s fixed in v2. If you still hit it on v1.x first, upgrade to at least WP Bones v1.11.1.

Rollback

If something doesn’t work, roll back via git and reinstall dependencies with your original package manager:

git reset --hard HEAD rm -rf node_modules vendor composer install yarn install # or: npm install / pnpm install

Then open an issue with the error output and we’ll help.

Last updated on