A guide on implementing code sharing in NestJS using Yarn Workspaces

I'm currently working on a proof of concept for a basic monorepo application. To structure my packages, I've decided to use Yarn Workspaces instead of Lerna as it seems more suitable for my needs.

One of the packages in my setup is shared, which is meant to be used by both the frontend and backend. While I have successfully integrated it with the frontend using NextJS along with the NPM library next-transpile-module, I'm facing challenges with the backend. Despite searching online extensively, I couldn't find any relevant information or resources.

When attempting to start the API, I encounter the following error:

/Users/Alfonso/git/taurus/packages/shared/dist/index.js:1
export var PRODUCT_NAME = "ACME";
^^^^^^

SyntaxError: Unexpected token 'export'
    at wrapSafe (internal/modules/cjs/loader.js:1054:16)
    at Module._compile (internal/modules/cjs/loader.js:1102:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
    at Module.require (internal/modules/cjs/loader.js:1026:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (/Users/Alfonso/git/taurus/packages/api/dist/app.service.js:11:18)
    at Module._compile (internal/modules/cjs/loader.js:1138:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)

This error, similar to the one encountered in the client package, was resolved using the next-transpile-module NPM library. Hence, it appears to be related to transpilation issues, but I'm unsure how to proceed further!

Answer №1

Upon initial inspection, it appears that the issue lies in the compilation of the shared library. The conflict between ESM (ES Modules) and CJS (CommonJS) is likely causing the problem. ES Modules utilize the exports syntax, commonly used in front end libraries, while Node continues to rely on CommonJS with module.exports. This discrepancy causes Node to encounter an error when it encounters exports.

Answer №2

What could be the resolution to this issue?

Here's a proposed solution for the problem at hand. While utilizing yarn workspace allows transpilation of a shared typescript library for Next.js using "next-transpile-module" by executing "yarn workspace @project/app start", the same approach does not work for the backend Nest.js service. Trying to run "yarn workspace @project/service start" results in a "SyntaxError: Unexpected token 'export'".

To remedy this, it is essential to first build the shared library targeting "commonjs" and then configure the service to execute the built code instead.

project/packages/common/package.json

{
  "name": "@project/common",
  "version": "1.0.0",
  "main": "dist/index",
  "license": "MIT",
  "private": true,
  "scripts": {
    "build": "tsc",
    "start": "yarn build & node ./dist/index"
  },
  "devDependencies": {
    "typescript": "^4.8.4"
  }
}

project/packages/common/tsconfig.json

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "target": "es5",
    "lib": ["esnext"],
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "rootDir": "src",
    "outDir": "dist",
    "module": "commonjs",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "baseUrl": "./src",
    "noImplicitAny": true
  },
  "include": ["src"]
}

/project/packages/service/package.json

{
  "name": "@project/service",
  "version": "1.0.0",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "start": "nest start",
  },
  "dependencies": {
    "@project/common": "*",
    ...
  }
}

Ensure that the shared libraries are built to "commonjs" and utilize the built files accordingly. Exploring alternative methods beyond building may yield more efficient outcomes. It might be possible to leverage "ts-node" to transpile the shared library during runtime for improved performance.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Suggestions for managing the window authentication popup in Protractor when working with Cucumber and TypeScript?

I'm a beginner with Protractor and I'm working on a script that needs to handle a window authentication pop-up when clicking on an element. I need to pass my user id and password to access the web page. Can someone guide me on how to handle this ...

Upgrade Next Js to version 12 or even push it further to version 13

Query 1: I am in the process of updating our custom application from version 11.1.4 to 12.2.0 of Next.js, but encountering an issue as follows: Error - ./node_modules/@internationalized/date/dist/import.mjs:1:0 Module not found: Can't resolve ' ...

Sending data with an Http POST request in Angular 2

I'm having difficulty with a POST request that I am trying to make: sendRequest() { var body = 'username=myusername&password=mypassword'; var headers = new Headers(); headers.append('Content-Type', 'applicat ...

What is the best way to dynamically insert content into a PDF using pdfmake?

In my quest to dynamically generate PDFs using pdfmake, I've encountered an issue with creating dynamic rows based on data. To illustrate, here is a simplified version of the code: getDocumentDefinition(img: string, data: DataResponse, user: UserResp ...

Interpolation is not available for my Angular application

I am having trouble with using interpolation on my input in this code. I tried setting the value of the input to be the same as the User's username, but it doesn't seem to work. <ion-header> <ion-toolbar> <ion-buttons slot=&q ...

The host name specified in the _document.js file within a NextJS project

Is it possible to obtain the hostname in the _document.js file within nextJS without access to the window object during server-side rendering? I attempted to retrieve it from initialProps (context), yet the req in initialProps remained undefined. Are the ...

Assign the image source to the file path located in the data directory

Is there a way to dynamically set the src attribute of an <img> tag in an HTML file using a string path from a file? The path is retrieved from the cordova.file.dataDirectory Cordova plugin within Ionic2 (TypeScript) and it typically looks like this ...

Unable to display grid items in React material-ui grid list

export interface FlatsGridProps { flats: IClusterFlats[]; } export const FlatsGrid: React.StatelessComponent<FlatsGridProps> = (props: FlatsGridProps) => { if (props.flats.length === 0) { return (<div> empty </di ...

What steps can be taken to resolve the error message "Module '../home/featuredRooms' cannot be found, or its corresponding type declarations"?

Upon deploying my site to Netlify or Vercel, I encountered a strange error. The project runs smoothly on my computer but seems to have issues when deployed. I am using TypeScript with Next.js and even attempted renaming folders to lowercase. Feel free to ...

Tips for customizing the appearance of an active link in a mapped navigation bar

I am currently working on a Next.js page and I want to add some styling to the NavBar to indicate to the user which page they are on. Although I found this interesting solution on Stack Overflow - Target Active Link when the route is active in Next.js ... ...

Encountering Invalid Chai attribute: 'calledWith'

I am currently in the process of implementing unit tests for my express application. However, I encountered an error when running the test: import * as timestamp from './timestamp' import chai, { expect } from 'chai' import sinonChai f ...

Failure to implement Next.js 13 App Directory routing in a Spring Boot application

Recently, I came across a similar inquiry regarding integrating NextJS routing with a Spring Boot application without using any proxy I am currently working on setting up a Spring Boot application to serve a NextJS13 app Directory. The root page / (which ...

Tips on modifying the selected type key name through Pick?

I currently have this structure: type Product = { name: string } and I am looking to extract the name property and use it in a different type declaration like so: type NewProduct = Pick<Product, 'name'> Now, I want to rename name as new ...

Passing parameters in React classes is a crucial aspect of creating

Within a project I am currently working on, there is a const defined for the page header which takes in parameters and utilizes the information: interface UserProps { user?: { name: string, image: string }, loading?: boolean, error?: E ...

When running jest unit tests, an error is thrown stating that includes() and toLowerCase are not functions

MyComponent.js contains both toLowerCase and includes methods on the props. However, when attempting to perform unit testing on MyComponent, I encounter an issue where the functions toLowerCase() and includes() are not recognized as valid. Within MyCompon ...

Storing information from JSON into an object

I am encountering an issue regarding transferring data from JSON to an object. Although this solution is functional, it is not entirely satisfactory. Take a look at the service. Is there an improved method for handling data conversion from this JSON to an ...

Exclusive Vue3 Props that cannot be used together

How can a component be created that accepts either json with jsonParserRules or jsonUrl with jsonParserRulesUrl, but not both? It would be ideal if the IDE could provide a warning when both props are specified. Example of an Attempt that does not Work < ...

Is utilizing getStaticProps the best approach for handling offline data in Next.js?

My current project in Next.js involves offline static data for the webpage content. I am using an array to store the data for later mapping. Do you recommend using getStaticProps in this scenario? For example, here is a snippet of my code: import { data } ...

A guide on crafting a type definition for the action parameter in the React useReducer hook with Typescript

In this scenario, let's consider the definition of userReducer as follows: function userReducer(state: string, action: UserAction): string { switch (action.type) { case "LOGIN": return action.username; case "LOGOUT": return ""; ...

Using conditional statements to render content based on a certain condition within a

One of my requirements is to dynamically render a React component in the following manner: parent.ts ... <Parent> <Child/> <Parent> ... child.ts ... return (someBoolean && <Component/>) ... While ...