简体   繁体   中英

Compiling code from another workspace project in a nestjs api - Unexpected token 'export'

I'm trying to create a monorepo containing a NestJs API, a React app, and many other smaller projects shared between them

The monorepo is set up with yarn workspaces

The React app using Vite imports and compiles the common projects flawlessly, but the NestJs api never compiles, usually giving the SyntaxError: Unexpected token 'export' error.

I made a minimal repository with just a basic Nest project and a common folder to try to get a single function import working with the following structure:

.
├── common                  # Sample common project
│   ├── tsconfig         
│   ├── src        
│   │   └── test.ts         # The file called from the api
│   └── package.json   
├── api                     # NestJs API
│   ├── tsconfig      
│   ├── src        
│   └── package.json             
└── package.json            # Yarn workspace setup

The main package.json:

{
    "name": "mono",
    "workspaces": [
        "common",
        "api"
    ]
}

The common package.json

{
    "name": "@test/common",
    "version": "1.0.0",
    "main": "index.ts"
}

The common tsconfig

{
  "compilerOptions": {
    "module": "CommonJS",
    "allowSyntheticDefaultImports": true,
    "baseUrl": ".",
    "esModuleInterop": true,
    "composite": true,
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true
  }
}

And its complicated test function in src/test.ts

export const hi = () => 'Hello there';

And here's the main.ts file from which I call this function:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { hi } from '@test/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);

  console.log('All fine', hi());
}
bootstrap();

The api package.json

{
  "name": "api",
  "scripts": {
    "start": "nest start",
    ...other commands
  },
  "dependencies": {
    "@nestjs/common": "^9.0.0",
    "@nestjs/core": "^9.0.0",
    "@nestjs/platform-express": "^9.0.0",
    "@test/common": "*",
    "reflect-metadata": "^0.1.13",
    "rxjs": "^7.2.0",
    "webpack-node-externals": "^3.0.0"
  },
  "devDependencies": {
    ...nest deps
    "ts-jest": "29.0.3",
    "ts-loader": "^9.2.3",
    "ts-node": "^10.0.0",
    "tsconfig-paths": "4.1.1",
    "typescript": "^4.7.4"
  },
  "jest": {
    ...jest config
  }
}

And api's tsconfig

{
  "compilerOptions": {
    "module": "CommonJS",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
  },
  "include": [
    "../common",
    "./src/*"
  ],
  "references": [
    {
      "path": "../common"
    }
  ],
  "paths": {
    "@test/common/*": [
      "../common/*"
    ]
  }
}

When running yarn run start on the nest project, the produced dist folder seems to contain the correct file structure:

分布式结构

But leads to the same error again and again

C:\<path>\MonoNest\api>yarn run start
yarn run v1.22.19
$ nest start
C:\<path>\MonoNest\common\index.ts:1
export * from './src/test';
^^^^^^

SyntaxError: Unexpected token 'export'
    at Object.compileFunction (node:vm:360:18)
    at wrapSafe (node:internal/modules/cjs/loader:1088:15)
    at Module._compile (node:internal/modules/cjs/loader:1123:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Function.Module._load (node:internal/modules/cjs/loader:878:12)
    at Module.require (node:internal/modules/cjs/loader:1061:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at Object.<anonymous> (C:\<path>\MonoNest\api\src\main.ts:3:1)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

The minimal reproduction project is available on Github if you want to test it out

To make things clear, i'm trying to make a "real" monorepo, where the parent folder only contains paths the the different projects.

I'm not interested in the 'official' nestjs monorepo doc which makes the root repository include most nestjs packages and config that I do not want within my other projects

The error is thrown because you put @test/common in node_modules without compiling the ts files into js .

After you enter the command yarn run start , the engine compiles typescript files into javascript, for the packages inside node_modules the compilation is done before. more about publishing ts modules .

Therefore, after compilation, javascript sees there are some unknown syntaxes that were from typescript and not compiled into javascript.

So you need to compile your package and then use it.

You have some options to fix this:

  1. Change importing path in your main file into this:
// main.ts
import { hi } from '../../common';
  1. If you need the package to be a part of your dependencies, and it doesn't exist in npm, then you need to use Local paths .

As of version 2.0.0 you can provide a path to a local directory that contains a package.

It would be like this:

npm install --save ../path/to/mymodule

using yarn:

// relative path
yarn add file:./../your-project
// absolute path
yarn add file:/dev/your-project

Just to see how your project works, you can manually build the common module, change the value of key main in package.json to "main": "./path/to/index.js" and then move it into your node_modules . (not recommended, Just so you know. everything has to be javascript at the end to work properly.)

It is because you are trying to use a Pure ESM package within a project that is not Pure ESM. Sometimes there are workarounds such as using module name mappers (in Jest). Other times...there is not. You could attempt to make your package Pure ESM and that would work...but I am not familiar enough with that process to be any help with that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM