Open yeli19950109 opened 5 years ago
Hello @yeli19950109
Can you create an example that fails with ncc build
?
I'm experiencing the same issue, the path to the Swagger UI assets is no longer correct after building the app with ncc
.
After some playing around, however, I've seem to found a workaround: Serving the static
folder manually, after the Swagger setup. Here's a code snippet, I'm using /swagger
as the public URL:
// ...
SwaggerModule.setup('/swagger', app, document);
app.useStaticAssets(join(__dirname, '/static'), {
prefix: '/swagger',
});
// ...
Plus, I had to install fastify-swagger
although I'm just using express
in NestJS ... just wtf?
This all works for now, but surely is not a very pretty solution ...
The real issue is probably how swagger-ui itself gets built and served, and not necessarily how ncc
tries to bundle it up. Related issue: https://github.com/scottie1984/swagger-ui-express/issues/114.
Any updates on this one ??
p.s: @dominique-mueller I have tried your proposed solution and it seems that I might be missing something out. Could you be kind enough to help me out with this issue ??
@mohammadzainabbas Sure, I took the time to prepare a repository here: https://github.com/dominique-mueller/ncc-nestjs-swagger-experiment. It's a working example, so you can clone it and play around with it. I also wrote a quick explanation in the README about what has to be done to get Swagger working in an existing ncc-NestJS project. Hope it helps!
I have issues with swagger-ui-express
as well after using ncc
. @dominique-mueller, thank you for your example. I am wondering if it would be possible to achieve similar fix with express
only? I am not using nestjs
in my project.
So my understanding of the issue is that swagger-ui works like this:
When a browser requests the swagger documentation URL (e.g. https://example.com/swagger/
):
swagger-ui-bundle.js
, swagger-ui.css
etc.node_modules
available@nestjs/swagger
swagger-ui-express
SwaggerModule
in our code, which will require('swagger-ui-express'), which in turn has a dependency on:swagger-ui-bundle.js
, swagger-ui.css
etc.When the server is running and the browser visits the swagger URL (e.g. https://example.com/swagger/
):
https://example.com/swagger/swagger-ui-bundle.js
swagger-ui-dist
package in the top-level node_modules
folderNone: in this case we don't have access to node_modules/swagger-ui-dist
i.e. the reason to use ncc is that we don't need the large node_modules
folder.
So when we don't do anything special the swagger-html page will not work, because the requests for the
relative links in the dynamic HTML cannot be resolved (express will return a HTTP 404 - Not Found
error)
To fix this we must somehow provide these files. This requires 2 steps
This depends on your build tools: e.g. we use angular-cli, thus we can simply use assets to copy the relevant files, e.g.
"assets": [
{
"glob": "**/*.{js,css,html,png}",
"input": "./node_modules/swagger-ui-dist/",
"output": "./dist/assets/swagger-ui-dist/"
},
....
]
Where dist
is the ncc output dir (i.e. where the index.js
or main.js
file will be created)
When we use NestJs we can use this:
app.useStaticAssets(path.join(__dirname, 'assets/swagger-ui-dist/'), {
prefix: '/swagger'
});
where app
is our NestExpressApplication
.
So basically this just configures express to return the files in the assets/swagger-ui-dist/
folder when the URL starts with /swagger
: e.g. https://example.com/swagger/swagger-ui-bundle.js
This refers to the explanation in the ncc-nestjs-swagger-setup test project
I guess the reason is this:
When ncc analyses our code, it finds require('fastify-swagger')
in the SwaggerModule.
When the package is installed (i.e. exists in node_modules
), ncc will process it.
When the webpack-asset-relocator-loader
(used by ncc) will notice that the file prepare-swagger-ui.js needs the files in the static folder:
And thus it will copy these files to the static
folder in our dist
dir.
Now we could serve these files and the swagger URL may work.
I think this may not work reliably, because there is no guarantee that the swagger-ui-dist
version which is copied from the fastify-swagger
package is compatible to the version used by swagger-ui
.
So I think it's better to
fastify-swagger
/node_modules/swagger-ui-dist
I was experiencing the same issue. Fortunately I got it to work without ncc. My solution is a bit hacky. Check out my solution on stack overflow: https://stackoverflow.com/a/74708365/13701992
This is how I solved the problem. Deploying Platform: Vercel
I wrote a patch to solve this problem. use https://unpkg.com/swagger-ui-dist@5.6.2/ as publicUrl
diff --git a/node_modules/@nestjs/swagger/dist/swagger-ui/constants.js b/node_modules/@nestjs/swagger/dist/swagger-ui/constants.js
index 6f47648..8776139 100644
--- a/node_modules/@nestjs/swagger/dist/swagger-ui/constants.js
+++ b/node_modules/@nestjs/swagger/dist/swagger-ui/constants.js
@@ -1,8 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.jsTemplateString = exports.htmlTemplateString = exports.favIconHtml = void 0;
-exports.favIconHtml = '<link rel="icon" type="image/png" href="<% baseUrl %>favicon-32x32.png" sizes="32x32" />' +
- '<link rel="icon" type="image/png" href="<% baseUrl %>favicon-16x16.png" sizes="16x16" />';
+exports.favIconHtml = '<link rel="icon" type="image/png" href="<% publicUrl %>favicon-32x32.png" sizes="32x32" />' +
+ '<link rel="icon" type="image/png" href="<% publicUrl %>favicon-16x16.png" sizes="16x16" />';
exports.htmlTemplateString = `
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
@@ -10,7 +10,7 @@ exports.htmlTemplateString = `
<head>
<meta charset="UTF-8">
<title><% title %></title>
- <link rel="stylesheet" type="text/css" href="<% baseUrl %>swagger-ui.css" >
+ <link rel="stylesheet" type="text/css" href="<% publicUrl %>swagger-ui.css" >
<% favIconString %>
<style>
html
@@ -71,8 +71,8 @@ exports.htmlTemplateString = `
<div id="swagger-ui"></div>
-<script src="<% baseUrl %>swagger-ui-bundle.js"> </script>
-<script src="<% baseUrl %>swagger-ui-standalone-preset.js"> </script>
+<script src="<% publicUrl %>swagger-ui-bundle.js"> </script>
+<script src="<% publicUrl %>swagger-ui-standalone-preset.js"> </script>
<script src="<% baseUrl %>swagger-ui-init.js"> </script>
<% customJs %>
<% customJsStr %>
diff --git a/node_modules/@nestjs/swagger/dist/swagger-ui/swagger-ui.js b/node_modules/@nestjs/swagger/dist/swagger-ui/swagger-ui.js
index c067725..d60f616 100644
--- a/node_modules/@nestjs/swagger/dist/swagger-ui/swagger-ui.js
+++ b/node_modules/@nestjs/swagger/dist/swagger-ui/swagger-ui.js
@@ -55,6 +55,7 @@ function buildSwaggerHTML(baseUrl, swaggerDoc, customOptions = {}) {
.replace('<% explorerCss %>', explorerCss)
.replace('<% favIconString %>', favIconString)
.replace(/<% baseUrl %>/g, baseUrl)
+ .replace(/<% publicUrl %>/g, 'https://unpkg.com/swagger-ui-dist@5.6.2/')
.replace('<% customJs %>', toTags(customJs, toExternalScriptTag))
.replace('<% customJsStr %>', toTags(customJsStr, toInlineScriptTag))
.replace('<% customCssUrl %>', toTags(customCssUrl, toExternalStylesheetTag))
My swagger UI now shows with the correct CSS/JS after relocating it. But it still shows up as with the example "Petstore". Is there some kind of document (json) that's missing?
cant use with swagger for nestjs