# Using temporal with nx monorepo

**URL:** <https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228>\
**Category:** Community Support\
**Tags:** typescript-sdk\
**Created:** [July 6, 2022, 1:10pm UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228 "2022-07-06T13:10:37Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![abadyan](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/abadyan/32/2370_2.png) [@abadyan](https://community.temporal.io/u/abadyan)\
**Post date:** [July 6, 2022, 1:10pm UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/1 "2022-07-06T13:10:37Z")

</div>

Hello,  
We are trying to use temporal inside an Nx monorepo with pnpm but encoutering issues that seem to be node\_modules related.  
We are using a webpack to package all worker related code with the worker being the entry point. When trying to start the worker, getting the following error:

```auto
Module not found: Error: Can't resolve './<omitted>/src/temporal/workflows.ts' in '/<omitted>/src/temporal' 
2022-07-06T07:46:20.137Z [ERROR] resolve './<omitted>/src/temporal/workflows.ts' in '/<omitted>/src/temporal' 
... 
Field 'browser' doesn't contain a valid alias configuration

```

Also tried passing in a `workflowBundle` which allowed the worker to start but when I try to start a new workflow, the error just happens then.

Created a minimal reproduction repo:

> **[GitHub - myZorroEng/nx-temporal-sample](https://github.com/myZorroEng/nx-temporal-sample)**
>
> Contribute to myZorroEng/nx-temporal-sample development by creating an account on GitHub.

To see the issue simply run:

```auto
npm i 
nx serve-temporal temporal

```

---

<div class="post-metadata">

**Author:** ![loren](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/loren/32/5099_2.png) [@loren](https://community.temporal.io/u/loren)\
**Post date:** [July 6, 2022, 3:10pm UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/2 "2022-07-06T15:10:06Z")

</div>

Why use webpack on all worker code?

The worker bundles workflow code using webpack, but in all our samples, the worker and activity code aren’t bundled.

---

<div class="post-metadata">

**Author:** ![abadyan](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/abadyan/32/2370_2.png) [@abadyan](https://community.temporal.io/u/abadyan)\
**Post date:** [July 6, 2022, 5:16pm UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/3 "2022-07-06T17:16:18Z")

</div>

The way that nx creates the project.json configuration is using webpack to package the app code.  
We placed the worker in the same project as the web app and so created a similar build configuration.  
Are you saying that this is the wrong way to go about it? Do the worker and activities (and workflows?) need to live in a separate location and be bundled differently? I would love to understand more about this.

Thank you.

---

<div class="post-metadata">

**Author:** ![loren](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/loren/32/5099_2.png) [@loren](https://community.temporal.io/u/loren)\
**Post date:** [July 6, 2022, 5:49pm UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/4 "2022-07-06T17:49:36Z")

</div>

Instead of the webpack executor, can you use this?

> **[@nrwl/js:tsc | Nx](https://nx.dev/packages/js/executors/tsc)**
>
> Builds using TypeScript.

You should be able to compile TS to JS and then run the worker with node. The equivalent in the hello-world sample would be:

```auto
# compiles src/*.ts to lib/*.js
npm run build
# runs worker
node lib/worker.js

```

> <https://github.com/temporalio/samples-typescript/blob/main/hello-world/package.json>

The Worker and Activities are loaded into that Node process, and the code at `./workflows` is bundled for you and run in vms when needed:

> <https://github.com/temporalio/samples-typescript/blob/main/hello-world/src/worker.ts#L3-L12>

---

<div class="post-metadata">

**Author:** ![bergundy](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/bergundy/32/900_2.png) [@bergundy](https://community.temporal.io/u/bergundy)\
**Post date:** [July 6, 2022, 11:52pm UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/5 "2022-07-06T23:52:40Z")

</div>

> [@abadyan](#):
>
> The way that nx creates the project.json configuration is using webpack to package the app code.

You can’t bundle the worker because it has binary (compiled) dependencies

---

<div class="post-metadata">

**Author:** ![abadyan](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/abadyan/32/2370_2.png) [@abadyan](https://community.temporal.io/u/abadyan)\
**Post date:** [July 7, 2022, 10:00am UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/6 "2022-07-07T10:00:56Z")

</div>

Using tsc worked for me, thank you.  
I am still having trouble using this in my original project which includes multiple projects with dependencies, but it does not seem to be a temporal issue anymore.

---

<div class="post-metadata">

**Author:** ![abadyan](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/abadyan/32/2370_2.png) [@abadyan](https://community.temporal.io/u/abadyan)\
**Post date:** [July 27, 2022, 8:04am UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/7 "2022-07-27T08:04:43Z")

</div>

Just a follow up:  
I was eventually able to run temporal on top of an nx monorepo, but it was very hard and had to use tips from here:

> **[Using Temporal.io inside a Nx Monorepo](https://andreas.fyi/writing/temporal-io-nx-monorepo)**
>
> A rough exploration of running Temporal.io within Nx Monorepos

And also use the bare “run-commands” executor to run the worker.

---

<div class="post-metadata">

**Author:** ![arthur\_pires](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/arthur_pires/32/3057_2.png) [@arthur\_pires](https://community.temporal.io/u/arthur_pires)\
**Post date:** [December 8, 2022, 12:32pm UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/8 "2022-12-08T12:32:06Z")

</div>

Hey @abadyan, I tried following the link you sent as a way of working around the issue, but I didn’t succeed, can you give more details about how you setup `project.json` and how to execute the worker after it’s built?

---

<div class="post-metadata">

**Author:** ![bnpnt](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/bnpnt/32/3689_2.png) [@bnpnt](https://community.temporal.io/u/bnpnt)\
**Post date:** [May 5, 2023, 3:16am UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/9 "2023-05-05T03:16:41Z")

</div>

Just in case someone in the future needs, here’s how you can use bundling with ESM and Nx:

In your `tsconfig.json`:

```json
{
  "extends": "@tsconfig/node18/tsconfig.json",
  "version": "5.0.4",
  "compilerOptions": {
    "strict": true,
    "module": "ESNext",
    "moduleResolution": "node",
    "target": "ESNext",
    "rootDir": "./src",
    "outDir": "./lib",
    "baseUrl": "."
  },
  "include": ["src/**/*.ts"]
}

```

The code to bundle has this general format:

```auto
import { bundleWorkflowCode } from '@temporalio/worker';
import { writeFile } from 'node:fs/promises';
import path from 'node:path';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';

const require = createRequire(import.meta.url);
const __dirname = fileURLToPath(new URL('.', import.meta.url))

async function bundle() {
  const { code } = await bundleWorkflowCode({
    workflowsPath: require.resolve('../src/workflows/workflows'),
  });

  const codePath = path.join(__dirname, '../lib/workflow-bundle.js');
  await writeFile(codePath, code);
  console.log(`Bundle written to ${codePath}`);
}

bundle().catch((err) => {
  console.error(err);
  process.exit(1);
});

```

The easiest way was to just recreate `require` to be honest… I’m open to ideas here if anyone wants to share!

In the worker, here’s how you can have bundling for production but loading workflows from a file in development:

```auto
import { Worker } from '@temporalio/worker';
import { URL, fileURLToPath } from 'node:url';
import * as activities from './activities.js';
import path from 'node:path';

function workflowOptions() {
  if (process.env.STAGE === 'production') {
    const workflowBundlePathURL = new URL('./workflow-bundle.js', import.meta.url)
    return {
      workflowBundle: {
        codePath: fileURLToPath(workflowBundlePathURL)
      }
    }
  }

  const workflowsPathUrl = new URL(`./workflows/workflows${path.extname(import.meta.url)}`, import.meta.url)
  return {
    workflowsPath: fileURLToPath(workflowsPathUrl)
  }
}

async function run() {
  const worker = await Worker.create({
    ...workflowOptions(),
    activities,
    taskQueue: 'hello-world',
  });
  await worker.run();
}

```

The `package.json` scripts look like this:

```json
{
    "test": "jest",
    "build": "tsc --build && npm run bundle",
    "bundle": "node --experimental-specifier-resolution=node --loader ts-node/esm scripts/build-workflow-bundle.ts",
    "build.watch": "tsc --build --watch",
    "worker": "nodemon --exec 'node --experimental-specifier-resolution=node --loader ts-node/esm' src/worker.ts",
}

```

Assuming this is under `packages/workflows` and that Nx is configured as a package-based monorepo, you can just run `nx run workflows:build`.

---

<div class="post-metadata">

**Author:** ![isaac99](https://avatars.discourse-cdn.com/v4/letter/i/839c29/32.png) [@isaac99](https://community.temporal.io/u/isaac99)\
**Post date:** [November 1, 2023, 2:59am UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/10 "2023-11-01T02:59:46Z")

</div>

Do you have a full example in git of this working?

---

<div class="post-metadata">

**Author:** ![bnpnt](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/bnpnt/32/3689_2.png) [@bnpnt](https://community.temporal.io/u/bnpnt)\
**Post date:** [December 18, 2023, 5:43am UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/11 "2023-12-18T05:43:27Z")

</div>

Hi Isaac!

Unfortunately, no. The above might still work, but I abandoned ESM because it was just too much of a hassle.

Hopefully, we’ll all be able to just use One Thing™️ in the future.

I can spin up an Nx + Temporal worker in Typescript example git repo, been using it for basically every single project in my company so far and it works quite well. I’ll link it here once I set it up.

But basic idea:

- create nx workspace
  - heavily suggest using the `integrated` setup. I can elaborate why if anyone cares.

- create an `@nx/node` app, put it in `apps/<your-app`
- create an `@nx/js` library called `workflows`, put it in `libs/workflows`
- inside your `apps/<your-app>/src/main.ts`, use `require.resolve('@your-nx-workspace-name/workflows')` as the `workflowsPath`

This leaves out bundling but in my git repo I’ll add the whole 9 yards 😄

Breaking up workflows as library is not necessary, you can put everything in the worker app if you want to. I just feel it creates a healthy separation, and allows you to test workflows separately, while also leveraging Nx’s task caching capabilities.

---

<div class="post-metadata">

**Author:** ![isaac99](https://avatars.discourse-cdn.com/v4/letter/i/839c29/32.png) [@isaac99](https://community.temporal.io/u/isaac99)\
**Post date:** [December 18, 2023, 7:42pm UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/12 "2023-12-18T19:42:02Z")

</div>

Thanks so much @bnpnt - this has already helped. I look forward to your example repo. I also need to go back and understand what was different about this setup from my original one which couldn’t resolve the workflowsPath.

---

<div class="post-metadata">

**Author:** ![bnpnt](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/bnpnt/32/3689_2.png) [@bnpnt](https://community.temporal.io/u/bnpnt)\
**Post date:** [December 19, 2023, 10:25pm UTC](https://community.temporal.io/t/using-temporal-with-nx-monorepo/5228/13 "2023-12-19T22:25:56Z")

</div>

[Here it is!](https://github.com/nubunto/nx-with-temporal) Let me know if you have any questions. I also check slack way more often!
