Enigmatic-Smile / serverless-plugin-optimize

⛔️ DEPRECATED ⛔️ Bundle with Browserify, transpile and minify with Babel automatically to your NodeJS runtime compatible JavaScript
https://www.npmjs.com/package/serverless-plugin-optimize
MIT License
130 stars 54 forks source link

[TypeScript Plugin] ENOENT: no such file or directory 'node_mnode_modules/...' #54

Open darbio opened 6 years ago

darbio commented 6 years ago

When I set external in the serverless.yml options to be the name of two node modules (which exist) I get the following error:

ENOENT: no such file or directory, lstat '/Users/darbio/Repositories/tsz/tsz-serverless-api/.build/node_mnode_modules/nodemailer'

Function:

  wp-shared-email:
    handler: functions/workers/shared/email/handler.index
    optimize:
      external: [
        'nodemailer',
        'email-templates'
      ]
    events:
      - sns:
          topicName: ${self:custom.sns-topic-shared-email}
          displayName: SNS topic for sending email

Error:

192-168-1-101:tsz-serverless-api$ serverless deploy function -f wp-shared-email --aws-profile tsz-dev --stage dev
Serverless: Configuring serverless offline -> localstack
Serverless: Configuring serverless offline -> kinesis consumer
Serverless: Compiling with Typescript...
Serverless: Using local tsconfig.json
Serverless: Typescript compiled.
Serverless: Optimize: starting engines
Serverless: Optimize: tsz-serverless-api-dev-wp-shared-email

  Error --------------------------------------------------

  ENOENT: no such file or directory, lstat '/Users/darbio/Repositories/tsz/tsz-serverless-api/.build/node_mnode_modules/nodemailer'

     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Forums:        forum.serverless.com
     Chat:          gitter.im/serverless/serverless

  Your Environment Information -----------------------------
     OS:                     darwin
     Node Version:           6.9.4
     Serverless Version:     1.26.0
darbio commented 6 years ago

I did some analysis of the source code and found that the issues is the following:

const externalDir = externalEntry.substring(
            this.serverless.config.servicePath.length,
            externalEntry.lastIndexOf('node_modules/' + external)
          ) + 'node_modules/' + external

In my example, this gets evaluated as substring(77, 71) + 'node_modules/' + external which is incorrect (as my functions are built into a .build folder using typescript-plugin) hence the node_mnode_modules string.

This plugin doesn't seem to honour the sub-folder that the functions are built into, instead expecting them to be in the root folder.

Changing this to the following seems to solve the issue:

const externalDir = externalEntry.substring(
            externalEntry.lastIndexOf('node_modules/' + external),
            externalEntry.indexOf(external) + external.length
          )

I had some packaging issues after this fix with regards to external libraries not being able to be found. To fix this, I had to walk through the dependency tree of the external node_modules used by the packages and include any which have symlinks in the folder structure (particularly .bin).

goncaloneves commented 6 years ago

@darbio I never used TS with SLS. So this needs to be fixed.

Have you came to a externalDir code that works with TS? I can give it a test without TS.

darbio commented 6 years ago

@goncaloneves I got it working with the code above, however I never got around to doing a PR as we ditched the external library. The TS plugin transpiles to a ‘.build’ folder.

goncaloneves commented 6 years ago

@darbio are you still using TS plugin with optimize? Want to understand if the issue here is TS compatibility or specific only to those libraries. Thanks for taking the time to explain.

darbio commented 6 years ago

Still using the package.

The problem only manifested itself when I used the external config option.

The problem is that the TS gets transpiled to a folder (.build) which changes the substring dry algorithm in this plugin.

Changing the code as per my above post fixes the issue - however I haven't tested with non TS projects. It should work, but it needs to be tested.

The external library that I was using failed because it symlinked to other external packages that no longer existed at that symlink.

Another failed due to not being compatible with the minification process (not a problem with this project).

darbio commented 6 years ago

To clarify: With the code change I suggested above, I believe the issue is fixed.

goncaloneves commented 6 years ago

Awesome @darbio. I will give it a go in the next few days without TS 👍

shashikac commented 2 years ago

I'm having the same issue above. Any fix from the library distribution side?

shashikac commented 2 years ago

This one works fine in the Linux environment

MaLub commented 2 years ago

Same for me - is there any progress on this topic

OperationalError: ENOENT: no such file or directory, stat 'XXXX/server/.build/node_mnode_modules/swagger-ui-dist'] {
  cause: [Error: ENOENT: no such file or directory, stat 'XXXX/server/.build/node_mnode_modules/swagger-ui-dist'] {
    errno: -2,
    code: 'ENOENT',
    syscall: 'stat',
    path: 'XXXX/server/.build/node_mnode_modules/swagger-ui-dist'
  },
  isOperational: true,
  errno: -2,
  code: 'ENOENT',
  syscall: 'stat',
  path: 'XXXX/server/.build/node_mnode_modules/swagger-ui-dist'
custom:
  optimize:
    external: ['swagger-ui-dist']
x71c9 commented 2 years ago

This might help: https://github.com/serverless/serverless-plugin-typescript/issues/239#issuecomment-1313951913