Closed drcampbell closed 8 months ago
This seems normal and expected. I do not even know how this could be fixed or handled on our part.
I would recommend to not bundle your servers.
Advantages to bundling your fastify apps: 1). Smaller image size which is less for Serverless compute to load and size in Storage 2). Smaller memory footprint.
If I run my application with TS-Node, it takes just over 600MB of memory.
If I build with esbuild and run the result, it takes just over 100MB of memory.
Deploying to Google Cloud Run with the unbuilt version requires a larger instance as I get a "heap error: out of memory" with the unbuilt version. I returned my app to being built and will try to find a different solution.
You can bundle, but then handle the copying of the files to the expected places yourself.
Adding onto @Uzlopak's comment, there's a popular esbuild plugin, esbuild-plugin-copy, which can handle this task. I'm personally bundling through esbuild and then compiling to a Docker image, so I added a COPY
directive in my Dockerfile.
Regardless of how you get the files into your final bundle, the location you'll want to copy from is node_modules/@fastify/swagger-ui/static
.
@arimgibson would you like to add a small guide in this repo on how to do this?
Thanks for the suggestions! I appreciate it.
@mcollina happily! Just straight into the README?
I'm at capacity right now but can submit that PR in ~1 week
@mcollina happily! Just straight into the README?
I'm at capacity right now but can submit that PR in ~1 week
Longest week of my life 😉
FYI I am getting 404
s for other assets besides the index.html
, swagger-initializer.js
, hook.js
when doing this.
Not sure if this gives any hints:
[reload] {"level":50,"time":1699515508346,"pid":21380,"err":{"type":"TypeError","message":"The \"original\" argument must be of type function. Received an instance of Object","stack":"TypeError [ERR_INVALID_ARG_TYPE]: The \"original\" argument must be of type function. Received an instance of Object\n at promisify (node:internal/util:343:3)\n at Object.
no clue
FYI I am getting 404s for other assets besides the index.html, swagger-initializer.js, hook.js when doing this.
I was having the same issue and I could only get it to work by applying the following patch:
// serve swagger-ui with the help of @fastify/static
fastify.register(fastifyStatic, {
- root: path.join(__dirname, '..', 'static'),
+ root: opts.baseDir || path.join(__dirname, '..', 'static'),
prefix: staticPrefix,
decorateReply: false
})
Then defining the baseDir
option
await server.register(fastifySwaggerUi, {
baseDir: process.env.ASSETS_ROOT ? path.resolve(process.env.ASSETS_ROOT) : undefined,
// ...
})
Copying the assets in my Dockerfile
COPY ./node_modules/@fastify/swagger-ui/static ./assets
ENV ASSETS_ROOT=/app/assets/
FYI I am getting 404s for other assets besides the index.html, swagger-initializer.js, hook.js when doing this.
I was having the same issue and I could only get it to work by applying the following patch:
// serve swagger-ui with the help of @fastify/static fastify.register(fastifyStatic, { - root: path.join(__dirname, '..', 'static'), + root: opts.baseDir || path.join(__dirname, '..', 'static'), prefix: staticPrefix, decorateReply: false })
Then defining the
baseDir
optionawait server.register(fastifySwaggerUi, { baseDir: process.env.ASSETS_ROOT ? path.resolve(process.env.ASSETS_ROOT) : undefined, // ... })
Copying the assets in my Dockerfile
COPY ./node_modules/@fastify/swagger-ui/static ./assets ENV ASSETS_ROOT=/app/assets/
Thank you! 😊
@davidjbng
Can you provide a PR please?
Can you provide a PR please?
Yes I will.
I noticed the Edit: Does not seem to be relatedcsp.json
is not available yet using my approach. Need to check that first.
For those still looking for a solution, I manage to get it working with this setup in a esbuild.config.js file. You'd add a build script in the package.json that calls node esbuild.config.js
// esbuild.config.js
import esbuild from "esbuild";
import { promisify } from "util";
import path from "path";
import fs from "fs";
const copyDir = async (src, dest) => {
const readdir = promisify(fs.readdir);
const mkdir = promisify(fs.mkdir);
const copyFile = promisify(fs.copyFile);
const stat = promisify(fs.stat);
// Create destination directory if not exists
await mkdir(dest, { recursive: true });
const files = await readdir(src);
for (const file of files) {
const srcPath = path.join(src, file);
const destPath = path.join(dest, file);
const stats = await stat(srcPath);
if (stats.isDirectory()) {
await copyDir(srcPath, destPath);
} else {
await copyFile(srcPath, destPath);
}
}
};
esbuild
.build({
entryPoints: ["src/index.ts"],
logLevel: "info",
outdir: "dist",
bundle: true,
platform: "node",
format: "cjs",
})
.then(() => {
copyDir("node_modules/@fastify/swagger-ui/static", "dist/static");
});
I have the assets copied to the dist/static
directory, but am getting 404 errors for some of the resources. The .css
, .js
, and .png
files are all returning 404, except index.html
, and swagger-initializer.js
are returning as expected.
I was able to get the esbuild bundle to work by replacing '..'
with '.'
in the lib/routes.js
file. The file expects the static folder to be in a parallel directory.
import { build } from 'esbuild';
import textReplace from 'esbuild-plugin-text-replace';
...
await build({
...
plugins: [
textReplace({
include: /node_modules\/@fastify\/swagger-ui\/lib\/routes\.js$/,
pattern: [
[`'\.\.'`, `'.'`]
]
})
]
You can bundle, but then handle the copying of the files to the expected places yourself.
Which files? That's the problem. Where are the default files?
Prerequisites
Fastify version
4.17.0
Plugin version
1.8.1
Node.js version
18.16.0
Operating system
macOS
Operating system version (i.e. 20.04, 11.3, 10)
12.6.5
Description
Attempting to run code built with esbuild, fastify, fastify-swagger-ui results in the error:
Supplying a valid logo will run the server, but the assets served at static will 404.
In the provided esbuild.config.mjs, we are defining filename and dirname for integration with commonjs libraries.
Steps to Reproduce
Clone repo
run
yarn start
and observe that it doesn't error runyarn buildandrun
and observe that it errorsExpected Behavior
No response