Open robblovell opened 2 years ago
probably because of ESM/CJS issues. Think esbuild plugins may be expected in CJS
Interesting idea... Experimenting around with ESM/CJS and changing the helloPlugin.ts CJS style also fails:
module.exports = {
name: 'hello',
setup(build: any) {
console.log('Hello World')
},
}
with serverless.ts:
const helloPlugin = require('./helloPlugin')
const serverlessConfiguration = {
...
This still results in:
ERROR: [plugin: hello] Plugin is missing a setup function
helloPlugin.js
const helloPlugin = {
name: 'hello',
setup(config) {
console.log('Hello World')
},
}
exports.helloPlugin = helloPlugin;
serverless.js
const { helloPlugin } = require('./helloPlugin')
const serverlessConfiguration = {
frameworkVersion: '3',
service: 'hello-world',
plugins: [
'serverless-esbuild',
'serverless-offline',
],
custom: {
esbuild: {
entryPoints: ['app.js'],
platform: 'node',
target: 'node16',
bundle: true,
outdir: '.esbuild/.build',
plugins: [helloPlugin],
},
'serverless-offline': {
host: "localhost",
httpPort: 3005
},
},
provider: {
name: 'aws',
runtime: 'nodejs16.x',
},
functions: {
'hello-world': {
handler: 'app.api',
events: [{
http: {
path: 'hello',
method: 'get',
},
}],
}
}
}
module.exports = serverlessConfiguration
serverless offline start
β [ERROR] [plugin hello] Plugin is missing a setup function
esbuild.config.js
const { helloPlugin } = require('./helloPlugin.js')
const { build } = require('esbuild');
const options = {
entryPoints: ['app.js'],
platform: 'node',
target: 'node16',
bundle: true,
outdir: '.esbuild/.build',
plugins: [helloPlugin],
}
build(options)
.then(result => {
console.log('Esbuild result:', result);
})
.catch(error => {
console.log('Esbuild error:', error);
})
node esbuild.config.js
Hello World
Esbuild result: { errors: [], warnings: [] }
If the serverless.js is converted to a serverless.yml, a clue is given:
frameworkVersion: '3'
service: hello-world
plugins:
- serverless-esbuild
- serverless-offline
custom:
esbuild:
entryPoints:
- app.js
platform: node
target: node16
bundle: true
outdir: .esbuild/.build
plugins:
- helloPlugin
serverless-offline:
host: localhost
httpPort: 3005
provider:
name: aws
runtime: nodejs16.x
functions:
hello-world:
handler: app.api
events:
- http:
path: hello
method: get
The error now is:
β [ERROR] Plugin at index 0 must be an object
Which might mean the problem is related to how the configuration is handled by the serverless framework itself, not the serverless-esbuild plugin.
I have raised this in the serverless framework main repo to see if there are any insights that can be found there: https://github.com/serverless/serverless/issues/11388
Hey have you seen how we're asking you to set it up in the documentation? That might solve your issue https://github.com/floydspace/serverless-esbuild#esbuild-plugins
I tested it using serverless.ts.
As a prerequisite, importing the esbuild plugin directly into serverless.ts didn't work. So, referring to the documentation, I changed it as follows.
custom: {
esbuild: {
bundle: true,
minify: false,
sourcemap: true,
exclude: '*',
target: 'node16',
define: { 'require.resolve': undefined },
platform: 'node',
concurrency: 10,
plugins: 'esbuild-plugins.ts',
},
},
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { nodeExternalsPlugin } = require('esbuild-node-externals');
module.exports = () => {
return [nodeExternalsPlugin()];
};
Interestingly, even though the files we load are TypeScript, we can still deploy with this configuration.
However, the esbuild-plugins.ts
file must be written in CommonJS format. Otherwise you will get an error like:
Error:
Error: "plugins" must be an array
at Object.buildOrServe (/home/<User>/Projects/<Sample>/node_modules/esbuild/lib/main.js:1125:17)
at /home/<User>/Projects/<Sample>/node_modules/esbuild/lib/main.js:2110:17
at new Promise (<anonymous>)
at Object.build (/home/<User>/Projects/<Sample>/node_modules/esbuild/lib/main.js:2109:14)
at build (/home/<User>/Projects/<Sample>/node_modules/esbuild/lib/main.js:1956:51)
at bundleMapper (/home/<User>/Projects/<Sample>/node_modules/serverless-esbuild/dist/bundle.js:69:50)
at /home/<User>/Projects/<Sample>/node_modules/p-map/index.js:57:28
However, this configuration method is not intuitive, so I think it would be better if we could use the writing style suggested by @robblovell.
Im also getting the same error when attempting to use "esbuild-plugin-copy";`
import { copy } from "esbuild-plugin-copy";
....
esbuild: {
bundle: true,
minify: false,
sourcemap: true,
exclude: ["aws-sdk"],
target: "node16",
define: { "require.resolve": undefined },
platform: "node",
concurrency: 10,
plugins: [
copy({
resolveFrom: "cwd",
assets: {
from: ["src/templates"],
to: ["templates"],
},
}),
],
},
β [ERROR] [plugin plugin:copy] Plugin is missing a setup function
/home/kay/checkpoint/email-service/node_modules/esbuild/lib/main.js:798:16: 798 β throw new Error(`Plugin is missing a setup function`);
@kaito3desuyo Thanks so much for that tip π
Describe the bug
When attempting to use any esbuild plugin, the following error occurs:
node_modules/esbuild/lib/main.js:786:16: ERROR: [plugin: plugin:copy] Plugin is missing a setup function
To Reproduce
This error occurs with any plugin.
Here's a git repo that demonstrates the problem in both javascript and typescript: plugin-missing-setup-function
Example:
app.ts
helloPlugin.ts
serverless.ts
package.json
Independent esbuild.config.ts
Expected behavior
Expect serverless to build and run using esbuild with plugins and not crash.
Versions (please complete the following information):
Additional context
It looks like any function passed into the esbuild config fails.
For instance, if you pass a function to the watch option, it is removed.
Is there some sort of marshalling/un-marshalling happening where functions are inadvertently deleted?