Folder structure for multiple servies with shared library?


#1

Lets say I have

-shared
    filea.js
-service1
     service.yml
-service2
     service.yml

Each service uses the same shared library.
In TypeScript I pull in the service using

 `import { ... } from '../shared'`

I have included the files in the yml include section.
The problem is that in the packed zip file the structure has changed to

-shared
service1.js

and service1 is then unable to require the library files.
What is the recommended structure for a case with a shared library ?

Edit: One option I can think of is to use webpack or similar to create a single file bundle.

Thanks


#2

Have you solved this? I am looking at sharing code between my functions and can’t make it work.


#3

I ended up using webpack to create a bundle per function. When using webpack set the library target to commonjs2.

	entry: {
		// save bundle is source location, this is required for serverless.yml
		'./server/webpackbundle1': path.join(__dirname, './server/test1'),
		'./server/webpackbundle2': path.join(__dirname, './server/test2'),
	},
	// use commonjs2 as output when creating a lambda bundle
	output: {
		libraryTarget: 'commonjs2',
		filename: '[name].js'
	},
	target: 'node',

then in yml I’m setting the function handler to e.g. webpackbundle1.handler.

I’m not sure this is the best approach, but at least it works for what I need.


#4

Ok thanks, I will give it a try if I can’t find another solution. Have you tried this module: serverless-shared-library?


#5

no I’m not aware of that module. If you do find another solution, maybe you can post it on this forum?


#6

I just use simple syntax like this to include another file:
var routehelper = require(’…/routes/routehelpers’);

Does that not work for you?


#7

I sure it will. I was no aware I can specify a path in the lambda handler, and without that the handler is placed at root level, meaning you cannot include files above.
If instead you change the folder structure to something like this

dist
    shared
        *.js
    serviceA
        fn1handler.js
        fn2handler.js
    serviceB
        handler.js
src
    shared
        *.js
    serviceA
        handler.js
        serverless.yml
    serviceB
        handler.js
        serverless.yml

and then define the handlers as

functions:
  fn1:
    handler: 'dist/serviceA/fn1handler.handler'
  fn2:
    handler: 'dist/serviceA/fn2handler.handler'

Then I’m sure it will work


#8

I solved this problem in a simple way: using symbolic links!

-common
  -libfile
-service1
  -file1
  -file2
  -libfile -> ../common/libfile
-service2
  -file3
  -file4
  -libfile -> ../common/libfile

Then, i just import libfile as usual inside any of the native services’ file and it works! When serverless zips the services it follows the links and actually creates a normal file, it works great.


How To Structure Multi-Service Codebase With Shared Library Code
#9

@polvoazul excellent solution, thank you!


#10

Here is my solution.

add below lines in pacakge.json

  "dependencies": {
    "common": "file:../common",
   ...
  }

The local package common will be copied to ./node-modules/common as other npm modules, when you run npm install.

Then you should be fine to reference the shared library as other npm modules

const common = require("common");

Reference: https://docs.npmjs.com/files/package.json#local-paths