简体   繁体   中英

Unexpected token "export" using babel in docker container with docker-compose and typescript monorepo

I have been struggling with the following issue over the last couple days and can't seem to track it down. I have a typescript monorepo with a shared package that I am trying to develop in docker using docker-compose. I can run them all directly from my local machine with yarn and everything boots up fine . However, once I dockerize them and spin them up with docker-compose, the api fails to start with the output:

/project/node_modules/@project/shared-components/index.ts:1
export * from './src';
^^^^^^
SyntaxError: Unexpected token 'export'

Which looks a lot to me like babel is failing somehow. The docker-compose file executes the identical command that I use from my local, and share all the same config files. I also set the volume of each docker container to the yarn workspace that contains my packages.

file structure

/project
  /packages
    /api
    /shared-components

command run from workspace root

yarn install
yarn run dev

/project/package.json

...
"workspaces": {
  "packages": [
    "packages/*"
  ]
},
"scripts": {
   ...
   "dev": "docker-compose build --parallel && docker-compose up --remove-orphans -d"
}

/project/docker-compose.yml

version: '3.8'
services:
  api:
    container_name: api
    environment:
      - NODE_ENV=development
    volumes:
      - './:/project'
    build:
      context: '.'
      dockerfile: Dockerfile.dev
    working_dir: /project/packages/api
    entrypoint: ['yarn', 'run', 'dev']
    ports:
      - '3000:3000'

/project/Dockerfile.dev

# configure container
FROM node:14
USER root

/project/packages/api/package.json

...
"scripts": {
    ...
    "dev": "set NODE_ENV=development&& set NEW_RELIC_ENABLED=false&& nodemon -e js,ts,json --exec babel-node --config-file ../../babel.config.json --extensions .ts,.js ./src/index.ts",
}

/project/packages/api/src/index.ts

require('@babel/register')({
  rootMode: 'upward',
  ignore: ['../../node_modules'],
  extensions: ['.js', '.ts'],
});

require('./server');

/project/babel.config.json

{
  "babelrcRoots": ["./packages/*"],
  "presets": [
    "@babel/preset-env",
    "@babel/preset-typescript",
    [
      "minify",
      {
        "builtIns": false,
        "evaluate": false,
        "mangle": false
      }
    ]
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "regenerator": true,
        "corejs": 3
      }
    ]
  ],
  "ignore": ["**/*.test.ts", "**/*.test.tsx", "**/*.test.js", "**/*.test.jsx"]
}

/package/tsconfig.json

{
  "compilerOptions": {
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "noImplicitAny": false,
    "allowSyntheticDefaultImports": true,
    "noEmit": true,
    "isolatedModules": true,
    "declaration": true,
    "downlevelIteration": true,
    "rootDir": ".",
    "baseUrl": ".",
    "outDir": "./.ts",
    "target": "ES5",
    "module": "ESNext",
    "moduleResolution": "node",
    "paths": {
      "@allido/*": ["./packages/*"]
    }
  },
  "include": ["./.storybook/main.tsx", "./packages/**/*"],
  "exclude": [
    "./node_modules",
    "./.storybook",
    "**/node_modules",
    "**/.next",
    "**/.lib",
    "**/out",
    "**/.ts",
    "**/*.test.ts",
    "**/*.test.js"
  ]
}

There's nothing in the shared components that stands out as relevant. An additionally weird part to this story is that in this same workspace I have a nextjs web app that shares the same shared-components package. It also shares the same babel.config.json, the same tsconfig file, and it works just fine in docker.

I think I've included all the relevant files, but please let me know if I missed anything that would be important to see. I am really baffled by the fact that this works just fine from my local with identical parameters, but fails in the most simple of dockerfiles with a shared volume.

I would really appreciate any help, or direction on how to pursue this issue. I have found almost nothing relevant online.

Thanks!

So, it turned out that the issue was running the apps inside a linux container, and attaching the windows compiled node_modules into it. So to get it working I had to install the dependencies from inside the container using an entrypoint script, and adjust my volume configuration to omit the node_modules from my local machine, but still allow for hot reloading when src files change.

/project/docker-compose.yml

version: '3.8'
services:
  api:
    container_name: capi
    environment:
      - NODE_ENV=development
    volumes:
      - './packages/:/project/packages'
      - /project/packages/api/node_modules/
    build:
      context: '.'
      dockerfile: Dockerfile.dev
    working_dir: /project/packages/api
    entrypoint: ['../../entrypoint.dev.sh']
    ports:
      - '3000:3000'

/project/entrypoint.dev.sh

#! /bin/bash
echo "install dependencies..."
yarn --cwd /project install

echo "starting node..."
yarn run dev

/project/Dockerfile.dev

# configure container
FROM node:14
USER root

RUN mkdir /project
RUN chmod -R 777 /project
RUN chown -R  node: /project

COPY ./*.json /project/
COPY ./.infrastructure/entrypoint.dev.sh /project/entrypoint.dev.sh

Just to share my experience to help. I had the same problem with a dockerized application with containers sharing a common config. I had only one container that was causing the error. I'm on MAC. For me it turns out to be a permission problem and I solved it by just changing execution permission of the entrypoint file from the containing folder like below:

 chmod +x entry-point.sh.

Hope this would help:)

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