Create a Build Task

To create a component with a custom build task, you can create a Bit App Component:

bit create bit-app my-build-task
CopiedCopy

Alternatively, to add a build task to an existing component, create a new file to the component and name it with the *.bit-app.ts suffix. Add an async function named build that accepts AppBuildContext. Bit will execute it during build.
The following example shows how to add an esbuild task and saving results as part of the component artifacts:

// component-name.bit-app.ts
import type { AppBuildContext, AppBuildResult } from '@teambit/application';
import { build } from 'esbuild';

export async function build(context: AppBuildContext): Promise<AppBuiltResult> {
  const rootPath = context.capsule.path;
  const outputDir = join(rootPath, 'build');

  const result = await build({
    entryPoints: [rootPath],
    bundle: true,
    platform: 'node',
    outfile: outputDir,
  });

  return {
    errors: result.errors.map((error) => {
      return new Error(error.detail);
    }),
    artifacts: [
      {
        name: this.artifactName,
        globPatterns: [outputDir],
      },
    ],
  };
}
CopiedCopy

To run the build task:

bit compile
bit build component-name
CopiedCopy

Learn more on building app components.

Reusing build task between Bit Components

You can expose a build function from a Bit Component, making the task reuseable.

// Reuse in another Bit Component's "*.bit-app.ts" file
import { build } from '@acme/platform.tasks.my-build-task';

export default {
  build
}
CopiedCopy

Build tasks in Dev Environments

Build tasks defined in an Dev Environment run for components configured with that Dev Environment.
The build pipeline is defined in the *.bit-env.ts file, for example:

// env-name.bit-env.ts
class MyEnv extends NodeEnv {
  
  build() {
    return Pipeline.from([
      TypescriptTask.from({
        tsconfig: this.tsconfigPath,
        types: this.types,
        typescript,
      }),
      VitestTask.from({
        config: require.resolve('./config/vitest.config.mjs'),
      })
    ]);
  }
}
CopiedCopy

You can use any of the official build tasks in your pipelines:

Create a Dev Environment build task

Generate a new Bit Component with a basic build task:

bit create build-task my-build-task
CopiedCopy

In your Development Environment add the component as a dependency and add the task to any of the pipelines:

// env-name.bit-env.ts
import { MyBuildTask } from '@acme/tasks.my-build-task'
class MyEnv extends NodeEnv {
  
  /**
   * Regular build pipeline. In most cases you may want to use this option.
   */
  build() {
    return Pipeline.from([
      MyBuildTask
    ]);
  }

  /**
   * Running when releaseing a new semver for a component. This is usually for production releases.
   */
  tag() {
    return Pipeline.from([
      // MyBuildTask
    ]);
  }

  /**
  * Running when releasing component snap. Most teams use this for staging environments.
  */
  snap() {
    return Pipeline.from([
      // MyBuildTask
    ]);
  }
}
CopiedCopy

Building cross-component tasks

By default a task runs individually for each component. However, you can set a task to run for several components. Some tooling may benefit from such execution.
The below example shows how you gain access to the full list of components to build and operate on them.

import { BuildTask } from '@teambit/builder';

export class MyBuildTask implements BuildTask {
  readonly name = 'my build task';
  
  execute(context: BuildTaskContext) {
    const capsules = context.capsuleNetwork;

    // build components in parrlel 
    await Promise.all(capsules.map((capsule) => fs.write(/** example */) ))

    return {
      componentResults: [],
      artifacts: [],
    }
  }
}
CopiedCopy
Reference cross-component build tasks

Many existing plugins already benefit from this capability, for example TypeScript, Webpack, ESLint and Vitest.

Storing build artifacts

Build tasks may generate artifacts. You can store them as part of the component version.
For example:

async execute(context: BuildContext): Promise<BuiltTaskResult> {
    const capsules = context.capsuleNetwork.seedersCapsules;
    capsules.forEach((capsule) => {
      const componentName = capsule.component.id.name;
      fs.writeFileSync(
        path.join(capsule.path, 'output.my-artifact.txt'),
        `The component name is ${componentName}`
      );
    });

    return {
      artifacts: [
        {
          generatedBy: this.aspectId,
          name: this.name,
          // The glob pattern for artifacts to include in the component version
          globPatterns: ['**/*.my-artifact.txt'],
        },
      ],
    };
  }
}
CopiedCopy

Debugging build tasks

Get breakpoint debugging for build tasks by setting your IDE launch configuration, see Debugging backend components in Bit workspaces.

To use a build task, register to the build function of your env. One the task is registered, it will run as part of the build process of the components that use that env.

Run only the task you built by passing it's name:

bit build --tasks MyBuildTask
CopiedCopy
Running snap and tag build tasks

Use the --include-snap or --include-tag flags for the build command in case your task was register to any of these pipelines.

To skip capsule generation and repeating build tasks, use the --reuse-capsules flag (this can also be combined with the --tasks flag):

bit build --tasks MyBuildTask --reuse-capsules
CopiedCopy

See component build pipeline

Get a list of all tasks configured for a component with the following command:

bit build --list-tasks <component-id>
CopiedCopy

Learn more