Skip to main content

Working With Workspaces

What you'll learn
  • how to use the workspaces run command in order to execute a single command on multiple packages in your Webiny project


Every Webiny project is organized as a monorepo and as such, it consists of multiple packages, or in the context of monorepos, multiple workspaces.

Depending on the project size, a single monorepo can contain anywhere from a couple to dozens of packages. When the latter point is reached, executing different commands on packages, one by one, simply becomes ineffective. That's why, the Webiny CLI introduces the workspaces set of commands.

Workspaces vs. Packages

Note that the terms workspace and package, essentially, refer to the same thing - an NPM package or in other words, a folder with a package.json file and some code. Check out the Workspaces vs. Packages section in the Monorepo Organization key topic to learn more.

The workspaces run command#

Webiny CLI provides the workspaces run (or ws run for short) command that enables you to run a single command across multiple workspaces at once. The common use case where this might be needed is local development, where you want to watch for code changes on multiple packages, and rebuild them accordingly.

For example, in order to establish a watch session across multiple packages, located in a specific folder, you can run the following command:

yarn webiny ws run watch --folder ./awesome/packages

On the other hand, if you wanted to build all of the packages, again, located in a specific folder, you can run:

yarn webiny ws run build --folder ./awesome/packages

When deploying your project applications, building of packages is done automatically for you, as explained in the Deploy Your Project tutorial.

How It Works#

Note that the workspaces run command runs the commands specified in the webiny.config.js file, and not the scripts that might've been defined in packages' package.json file, in its scripts section.

The webiny.config.js is almost always present in every package. For example, your React applications might have something like the following:

// webiny.config.js
const { startApp, buildApp } = require("@webiny/project-utils");
module.exports = {
commands: {
async start(args, context) {
// Start local development.
await startApp(args, context);
async build(args, context) {
// Bundle app for deployment.
await buildApp(args, context);

All of the commands are listed in the commands property of the exported object.

Specifying the Packages#

In the above shown examples, we've used the --folder argument, to instruct the workspaces run to run the command only for packages located in the ./awesome/packages folder. Instead of the --folder argument, you can also use the --scope argument, which enables you to filter the packages by their name. For example:

// Run the "watch" command on all packages whose name starts with "@webiny/".
yarn webiny ws run watch --folder @webiny/*
// Run the "build" command on packages "api-a", "api-b", and "api-c".
yarn webiny ws run build --folder api-{a,b,c}

Additional Arguments#

If a Webiny command you're trying to run expects additional arguments, you can pass them as usual. For example, for certain packages, the build command might expect the environment to be specified, via the --env argument. So, simply append it to the workspaces run command, like so:

yarn webiny ws run build --folder ./react-apps --env dev --custom-argument-1

How It Works#

Once executed, the workspaces run command first retrieves a list of all packages, specified via either the --folder or --scope argument. After that, the command requires the webiny.config.js


What happens if the command doesn't exist in one or more packages?#

If you're running a specific command for multiple packages, and some of the packages don't have it defined in its webiny.config.js, those packages will simply be ignored. Ultimately, for each package, the command gets executed only if it's actually defined in the webiny.config.js.

Can I add more commands in the webiny.config.js?#

Yes, you can. Feel free to expand it in any way needed.

Last updated on by Adrian Smijulj