Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better guidance for integrating Swagger UI >=4.6.x into webpack 5 based projects #7908

Closed
scottohara opened this issue Mar 12, 2022 · 3 comments
Assignees

Comments

@scottohara
Copy link
Contributor

scottohara commented Mar 12, 2022

Q&A (please complete the following information)

  • OS: macOS
  • Browser: chrome
  • Version: 99
  • Method of installation: npm
  • Swagger-UI version: 4.6.2
  • Swagger/OpenAPI version: Swagger 2.0

Content & configuration

To support the issue described below, I have created a minimal repro here:
https://github.com/scottohara/swagger-ui-webpack

  1. git clone https://github.com/scottohara/swagger-ui-webpack.git
  2. cd swagger-ui-webpack
  3. npm install
  4. webpack
  5. Open index.html in a browser

How can we help?

I have been successfully using Swagger UI (<= 4.5.x) for many years, in many different projects, including some that are built using webpack 5.

As of version 4.6.0, Swagger UI is itself also now built using webpack 5.

Because webpack 5 no longer includes node polyfills by default, and Swagger UI depends on some of these node polyfils (and this is unlikely to change), developers upgrading to Swagger UI 4.6.0 or later in their own webpack 5 based projects must now explicitly add these polyfills. This is already causing some issues for people that are unaware of this.

The existing webpack samples are now out of date and will not work for webpack 5.

With a view to (hopefully) contributing a fresh set of webpack samples that do work with webpack 5, I set out to create the most minimal webpack 5 + Swagger UI example possible. But I failed....

Starting from a known good base (Swagger UI v4.5.2)

Starting with Swagger UI v4.5.2 (prior to it's upgrade to webpack 5), my minimal package.json file includes just three dependencies:

{
  "devDependencies": {
    "swagger-ui": "4.5.2",
    "webpack": "5.70.0",
    "webpack-cli": "4.9.2"
  }
}

...and my webpack.config.js file simply sets the mode to development (to aid debugging):

module.exports = {
  mode: "development"
}

The src/index.js file just imports and uses Swagger UI as normal:

import SwaggerUI from "swagger-ui";

SwaggerUI({
  dom_id: "#app",
  url: "https://petstore.swagger.io/v2/swagger.json"
});

...and the index.html page is also quite minimal:

<html>
  <head>
    <link rel="stylesheet" href="node_modules/swagger-ui/dist/swagger-ui.css">
    <script defer src="dist/main.js"></script>
  </head>
  <body id="app"></body>
</html>

Running webpack using the above configuration produces a dist/main.js file; and opening the index.html file in a browser renders the Swagger Petstore API as expected. ✅

Upgrading to Swagger UI v4.6.2

The next step is to upgrade the version of Swagger UI to 4.6.2:

{
  "devDependencies": {
-   "swagger-ui": "4.5.2",
+   "swagger-ui": "4.6.2",
    "webpack": "5.70.0",
    "webpack-cli": "4.9.2"
  }
}

Running webpack at this point now yields errors relating to two missing node polyfills, and suggests installing buffer and stream-browserify:

{
  "devDependencies": {
+   "buffer": "6.0.3",
+   "stream-browserify": "3.0.0",
    "swagger-ui": "4.6.2",
    "webpack": "5.70.0",
    "webpack-cli": "4.9.2"
  }
}

Additionally, to silence the webpack errors, a fallback for stream has to be added to the webpack.config.js file:

module.exports = {
  mode: "development",
+ resolve: {
+   fallback: {
+     stream: require.resolve("stream-browserify")
+   }
+ }
}

Running webpack now finishes without error, and produces a dist/main.js bundle. ✅
However, reloading the index.html page in the browser, nothing is rendered and the following error appears in the browser console:

Uncaught SyntaxError: Invalid or unexpected token
    at Object../node_modules/swagger-ui/dist/swagger-ui-es-bundle-core.js (main.js:2042:1)
    at __webpack_require__ (main.js:2321:42)
    at eval (index.js:2:68)
    at Module../src/index.js (main.js:2168:1)
    at __webpack_require__ (main.js:2321:42)
    at main.js:2397:37
    at main.js:2399:12

Further experimentation was applied to the webpack.config.js, including :

  • adding resolve.fallback: { "buffer": require.resolve("buffer/") } as suggested by webpack
  • installing the process polyfill
  • new webpack.ProvidePlugin({ "buffer": ["buffer", "Buffer"] }
  • etc.

...but none of these resolves the Invalid or unexpected token error, and it is unclear exactly what is causing it.

Conclusion

I like to think that I'm not a complete Swagger UI + webpack novice, but I'm having difficulty getting a minimal example to work with webpack 5 + Swagger 4.6.2 (recall that it started out working perfectly for Swagger 4.5.2).

I can only imagine how first time users might also struggle to get Swagger UI 4.6.x working in their projects; and I believe it would greatly help if the webpack samples were refreshed to include a working webpack 5 configuration.

@scottohara
Copy link
Contributor Author

Update: As of [email protected] (in which the main feature addition was to expose a true ESM bundle), the error being thrown is now clearer:

Uncaught ReferenceError: Buffer is not defined
    at isSpecificValue (deep-extend.js:32:18)
    at eval (deep-extend.js:132:15)
    at Array.forEach (<anonymous>)
    at eval (deep-extend.js:110:20)
    at Array.forEach (<anonymous>)
    at module.exports (deep-extend.js:104:7)
    at lr (swagger-ui-es-bundle-core.js:201:310659)
    at eval (index.js:5:55)
    at Module../src/index.js (main.js:9689:1)
    at __webpack_require__ (main.js:10315:42)

This is despite the fact that my webpack.config.js file was also uplifted to include:

+ const webpack = require("webpack");

module.exports = {
  mode: "development",
  resolve: {
    fallback: {
      stream: require.resolve("stream-browserify"),
+     buffer: require.resolve("buffer/")
    }
  },
+ plugins: [
+   new webpack.ProvidePlugin({ "buffer": ["Buffer", "buffer"] })
+ ]
}

@char0n
Copy link
Member

char0n commented Mar 26, 2022

I've produced #7946 which should remedy this issue completely. No resolve.fallbacks and ProvidePlugin required anymore and the SwaggerUI will work with Create React App out of the box.

char0n added a commit that referenced this issue Mar 28, 2022
@char0n char0n self-assigned this Mar 28, 2022
@char0n
Copy link
Member

char0n commented Mar 28, 2022

Fixed in https://github.com/swagger-api/swagger-ui/releases/tag/v4.10.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants