Closed vcarel closed 7 years ago
Where is your handler.js located? In the service root directory?
The error only happens, if the plugin cannot find any handler file that matches handler.*
. Maybe you can post the result of ls -l
in your service directory.
If your handler is located in a subdirectory, your handler definition (functions.my_function.handler) should be mydir/someotherdir/handler.my_function
.
It's defined in my webpack configuration:
module.exports = {
entry: ['./src/server/handler.js'],
By the way, I'm using yarn to freeze dependencies. I noticed while trying several configurations that I can get the issue with 2.0.0 too. It looks like the problem appears with the upgrade of an inner dependency, somewhere.
Ok. I think the missing path in the function definition is the problem. The function definition should define the path - otherwise you'd also get issues with other plugins that need to find the handler. The problem is, that Serverless (the framework) is completely unaware of the handler location in your case.
So, please change the handler definition in your serverless.yml.
... and the good thing: With 2.2.0 you now do not have to set the entries manually anymore in your webpack config. Just use:
// webpack.conf.js
const slsw = require('serverless-webpack');
module.exports = {
entry: slsw.lib.entries,
...
output: {
...
filename: '[name].js',
...
}
};
Then you can add functions to your service without changing the config again.
This is the function definition you should set:
functions:
my_function:
handler: src/server/handler.my_function
I was searching how to define the path. I didn't put the serverless.yml is the same directory as the handler file, and that does not help.
Well, following what you said, I get another error:
Type Error ---------------------------------------------
Path must be a string. Received { 'src/server/handler': './src/server/handler.js' }
with
functions:
my_function:
handler: 'src/server/handler.my_function'
Ok, found. The problem is that slsw.lib.entries
does not contain an array, but the object
{ 'src/server/handler': './src/server/handler.js' }
If I just use the previous config, it works fine
module.exports = {
entry: ['./src/server/handler.js']
So, at the end, the fix was to set the path in the handler definition:
functions:
my_function:
handler: src/server/handler.my_function
Glad to hear that it now works 👍
Hey 👋 Apologies to reopen this, but I'm also seeing the same issue.
I'm trying to upgrade the serverless-babel-starter
repo to use 2.2.0
.
When I try to deploy, I get the error message:
Path must be a string. Received { 'src/handler': './src/handler.js' }
I've updated the webpack.config.js
to:
const nodeExternals = require('webpack-node-externals');
const slsw = require('serverless-webpack');
module.exports = {
entry: slsw.lib.entries,
target: 'node',
externals: [nodeExternals()],
module: {
loaders: [{
test: /\.js$/,
loaders: ['babel'],
include: __dirname,
exclude: /node_modules/,
}],
},
};
and the serverless.yml
to:
functions:
hello:
handler: src/handler.hello
events:
- http:
path: hello
method: get
# Ping every 5 minutes to avoid cold starts
- schedule:
rate: rate(5 minutes)
enabled: true
Do you have any suggestions? Would be great to get 2.2.0
working to be able to deploy a single function at a time.
Can you try to define an output section in your config? With lib.entries it is important that you set the output definition properly.
output: {
libraryTarget: "commonjs2",
path: path.join(__dirname, ".webpack"),
filename: "[name].js"
},
commonjs
should also work instead of commonjs2
if you prefer that.
It could be that there's a bug in the automatically generated output config if you omit it.
If that does not help, could you run the deploy with SLS_DEBUG=* set and post the callstack of the error? This might help to find the exact reason faster.
Thanks! My webpack config now looks like this:
const nodeExternals = require("webpack-node-externals");
const slsw = require("serverless-webpack");
const path = require("path");
module.exports = {
entry: slsw.lib.entries,
target: "node",
externals: [nodeExternals()],
module: {
loaders: [
{
test: /\.js$/,
loaders: ["babel"],
include: __dirname,
exclude: /node_modules/
}
]
},
output: {
libraryTarget: "commonjs2",
path: path.join(__dirname, ".webpack"),
filename: "src/handler.js"
}
};
But I'm now seeing this error associated with webpack:
throw new Error("Module '" + loader.path + "' is not a loader (must have normal or pitch function)");
Hmmm. we use webpack 3 here, there you have module.rules instead of loaders. I think since webpack 2 module.loaders changed to module.rules like this:
module: {
rules: [
{
// Process ES6 with Babel.
test: /\.(js|jsx)$/,
use: [
{
loader: "babel-loader",
options: {
presets: [ "node6", "stage-0" ],
plugins: []
}
}
],
}
]
}
Make also sure that you have defined the loaders and presets that you use in your package.json. Ours are:
"babel-loader": "^7.1.1",
"babel-preset-node6": "^11.0.0",
"babel-preset-stage-0": "^6.24.1",
"webpack": "^3.0.0"
We use node6 for all projects that deploy to node 6.10 lambdas.
You can safely use webpack ^3.0.0 as dependency. We didn't have any problems with that. Additionally you could use "[name].js" as filename in output, as that will dynamically adjust the handler name with each different handler used.
@lewisblackwood If it does not work, I can have a look tomorrow and if I have time I could prepare a PR for the babel-starter repo.
@HyperBrain thanks for all your help! I have a working set-up now:
const nodeExternals = require("webpack-node-externals");
const slsw = require("serverless-webpack");
const path = require("path");
module.exports = {
entry: slsw.lib.entries,
target: "node",
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["node6", "stage-0"],
plugins: []
}
}
]
}
]
},
output: {
libraryTarget: "commonjs2",
path: path.join(__dirname, ".webpack"),
filename: "[name].js"
}
};
and followed your suggestion of using webpack ^3.0.0
as a dependency.
I'll reach out to the maintainer of serverless-babel-starter
and see if they're open to a PR 👍
Thanks again!
Hmm, although it seems I've now broken the use of webpack-node-externals
.
Serverless: Packing external modules...
Serverless: Uploading service .zip file to S3 (9.46 MB)...
This takes 100 secs to deploy the whole project, and the same using single function deploy.
@HyperBrain are you using webpack-node-externals
in your set-up?
@lewisblackwood Yes, I do, and it works just by adding externals: [ nodeExternals() ],
to the config.
So serverless deploy
and serverless deploy function --f <xxxxx>
takes the same time for you? That sounds strange because the single function deploy should only package and deploy exactly one function.
To test you can try to run just the package phase of Serverless with serverless package --function=xxx
to see if it is Serverless' deployment that is broken or if it is something with the plugin's packaging.
Apologies, I think I made a mistake here. The deploy is still relatively slow, but it's actually just one of the functions that is both slow to deploy individually and slows deployment of the whole project.
@HyperBrain one last question if I can - are you using either of serverless-plugin-optimize
or serverless-optimizer-plugin
? Should they be compatible with serverless-webpack
?
I've included serverless-plugin-optimize
which significantly speeds up deployment, but once the functions are deployed they error with:
module initialization error: Error
.
🤔 No... I never used these two plugins and do not know if there are any issues. But it would be worth to have a look at it - and see why there are problems. Could you try to ask about that in the serverless forum? Maybe someone else has run into that and probably found a solution (or workaround). At least we might get more information to solve it.
After some thinking, I'm not really sure if any optimization plugins can add any value to the webpacked build and deployment. From the code and dependency side, everything is already optimized and only things that are needed are packaged (at least with the upcoming v3 version). I have to have a closer look into the plugin-optimize to see what exactly that does, and how it technically tries to speed up the deployment.
If you don't mind, you can experimentally try the v3.0.0-individual-packaging
branch - and use the optimize plugin there. I made some improvements there that target stability and compatibility with other plugins.
Will close this issue again now since there's no actual fail and you managed to deploy.
@HyperBrain thanks again for your help.
I've experimented further, using your v3.0.0-individual-packaging
branch and serverless-plugin-optimize
. Here's the repo.
Adding the plugin does reduce the time to deploy, but once deployed the Lambda errors with:
module initialization error: Error
at s (/var/task/_optimize/service-name-dev-hello/src/handler.js:1:683)
at /var/task/_optimize/service-name-dev-hello/src/handler.js:1:734
at Object.309../utils (/var/task/_optimize/service-name-dev-hello/src/handler.js:86857:174)
at s (/var/task/_optimize/service-name-dev-hello/src/handler.js:1:683)
at /var/task/_optimize/service-name-dev-hello/src/handler.js:1:734
at Object.308../hello (/var/task/_optimize/service-name-dev-hello/src/handler.js:86854:80)
It's probably that my configuration with serverless-plugin-optimize
is incorrect. Will try to get it working.
Hope that's useful 😬
I just upgraded from serverless-webpack 2.0.0 to 2.2.0 and got the following error. It was working perfectly with the previous version.
Is there anything wrong in my configuration?
FYI I'm on serverless latest (as of today: 1.18.1)