I have an old React app which I'm trying to run locally, but I encountered some issues regarding querystring
and pollyfils. Here are my files:
packages.json:
{
"name": "test-immersion",
"version": "0.1.0",
"private": true,
"dependencies": {
"immersion-presentation": "^1.0.0",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-scripts": "5.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"pdf": "node ./node_modules/immersion-presentation/make-pdf"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
src/index.js:
import React from "react";
import ReactDOM from "react-dom";
import Presentation from "./Presentation";
// Not using React.StrictMode because of performance issues (renders everything twice)
const rootEl = document.getElementById("root");
ReactDOM.render(<Presentation />, rootEl);
if (module.hot) {
module.hot.accept("./Presentation", () => {
const NextPresentation = require("./Presentation").default;
ReactDOM.render(<NextPresentation />, rootEl);
});
}
src/Presentation.js:
import React from "react";
/* eslint-disable jsx-a11y/iframe-has-title, jsx-a11y/alt-text, */
/* eslint-disable no-unused-vars */
import { useState } from "react";
import {
AnimateSVG,
Morph,
m,
M,
Show,
Notes,
Portal,
timeline,
range,
themes,
} from "immersion-presentation";
import "immersion-presentation/dist/index.css";
import step from "immersion-presentation/dist/step.macro.js";
const {
Presentation,
Slide,
BibliographySlide,
TitleSlide,
TableOfContentsSlide,
SectionSlide,
QuestionSlide,
ConclusionSlide,
Figure,
List,
Item,
Cite,
Box,
Qed,
} = themes.modern;
function App() {
return (
<Presentation>
<Slide steps={[1, 2, 3]}>The step is {step}!</Slide>
</Presentation>
);
}
export default App;
I'm using node version 16.20.2 and npm version 8.1.0, and when I run yarn start
it throws the following error:
ERROR in ./node_modules/wikibase-sdk/lib/utils/build_url.js 7:19-51 Module not found: Error: Can't resolve 'querystring' in 'C:\Users\User\dev\test-immersion\node_modules\wikibase-sdk\lib\utils'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "querystring": require.resolve("querystring-es3") }'
- install 'querystring-es3' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "querystring": false }
I see the answer here with webpack
, but in my project I do not use webpack
, and not sure if this even helps given that the issue comes from a dependency of a dependency. Any ideas how to resolve this?
Considering that the only problem is querystring
that is used by wikibase-sdk
, the quick fix would be to install querystring-es3
polyfill and map querystring
to it, as it has been already suggested in the question.
The project uses CRA (react-scripts
), which uses Webpack internally. It's possible to modify Webpack config through third-party tools like Craco. The project needs to replace all occurrences of react-scripts
in scripts with craco
and provide custom config in craco.config.js:
module.exports = {
webpack: {
configure: (webpackConfig, { env, paths }) => {
webpackConfig.resolve.fallback = { querystring: require.resolve("querystring-es3") }
return webpackConfig;
},
},
};
The necessity to use Node.js polyfills in a browser build often indicates that things already went wrong, because the project uses a module that was intended to be used only in Node and not in a browser.
This was suggested by previously published error that mentioned fs
and module
. This may require to polyfill an unspecified amount of Node built-in modules and then the module will refuse to work because most of the polyfills are just stubs; a browser can't do what Node does.
This requires to isolate a dependency that causes this. In this case the nested dependency is:
immersion-presentation > citation-js > @citation-js/plugin-wikidata > wikidata-sdk > wikibase-sdk
This is a mistake on the behalf of the authors of the dependencies. wikibase-sdk@7
that the dependency graph is hardcoded to use is forced to use Node built-in modules despite it's built as UMD module that could run in a browser.
This can be fixed by overriding a troublesome dependency, considering that an override is compatible. The unnecessary dependency on Node builtins was presumably fixed in wikibase-sdk@8
. An override can be provided in package.json, the dependencies need to be completely reinstalled:
"overrides": {
"citation-js": {
"@citation-js/plugin-wikidata": {
"wikidata-sdk": {
"wikibase-sdk": "8"
}
}
}
}