node-fetch: node-fetch 2.1.2 broken with webpack (node-fetch 1.7.3 works)
I put together a small repo: https://github.com/ilanc/node-fetch-webpack
Issue
With node-fetch 2.1.2 you have to use the ES6 module import form:
import fetch from 'node-fetch'
If you use the commonjs form:
const fetch = require('node-fetch')
then the resulting bundle won’t work properly:
node-fetch-webpack/bundle.js:103
fetch('https://google.com/').then(res => res.text()).then(body => console.log('success'));
^
TypeError: fetch is not a function
...
Workaround
Seems to work with both module load formats in node-fetch 1.7.3
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 20
- Comments: 17 (1 by maintainers)
Commits related to this issue
- Fix missing node-fetch when building using webpack * See https://github.com/bitinn/node-fetch/issues/450#issuecomment-387045223 — committed to jvliwanag/purescript-milkis by jvliwanag 5 years ago
- Fix node-fetch import See https://github.com/bitinn/node-fetch/issues/450 for reason. — committed to JupiterOne/jupiterone-client-nodejs by deleted user 5 years ago
- Update index.js My build uses Webpack and fails with `TypeError: fetch is not a function`. Webpack and `node-fetch 2.1.2` (in use here) will not use the CommonJS solution by default. Explanations... — committed to obax/bullet-train-nodejs-client by obax 5 years ago
- webpack issue Because serverless uses webpack to package scripts for Lambda (or any other FASS service), when using bitly4api the function errors out: `error: TypeError: fetch is not a function`. ... — committed to andreiashu/bitly4api by andreiashu 4 years ago
- Add workaround to fix node-fetch issue https://github.com/node-fetch/node-fetch/issues/450 — committed to omrilit/netsuite-suitecloud-sdk by omrilit 4 years ago
- Use .default for compatibility with webpack https://github.com/node-fetch/node-fetch/issues/450 — committed to cyph84/youtube-sr by cyph84 4 years ago
- Add workaround to fix node-fetch issue https://github.com/node-fetch/node-fetch/issues/450 — committed to salto-io/netsuite-suitecloud-sdk by omrilit 4 years ago
- Add workaround to fix node-fetch issue https://github.com/node-fetch/node-fetch/issues/450 (cherry picked from commit b95432749c10840d4cc86e910ccad39960ab9214) — committed to omrilit/netsuite-suitecloud-sdk by omrilit 4 years ago
- fallback to require('node-fetch').default due to https://github.com/node-fetch/node-fetch/issues/450 — committed to Flagsmith/flagsmith-nodejs-client by kyle-ssg 2 years ago
- Add workaround to fix node-fetch issue node-fetch/node-fetch#450 — committed to jeroni7100/zwift-memory-monitor by jeroni7100 2 years ago
I thought about this at lunch. There’s another workaround:
This is probably the best workaround because it supports:
node app.jssee https://github.com/ilanc/node-fetch-webpack/commit/36329770dbd2a175e404ceba0c13c8f5d0fa8539
Can you first explain what exactly you are doing with webpack if you are NOT bundling it for frontend?
Your issue has no actual error from webpack, so how are we going to troubleshoot this, as node-fetch should have no knowledge of the bundler you want to use.
Is not a workaround, it is what
export defaultmeans in commonJS terms. And, on the contraryconst fetch = require('node-fetch')would translate toimport * as fetch from "node-fetch"in ESM terms. the problem is not webpacks translation, (every transpiler will transpileexport default Xintomodule.exports.default = X, so importing withrequire().defaultis correct). The problem is assuming thatrequire === import, which it’s not, it’s not syntactic sugar, they literally mean different things.If @ilanc is bundling anyway, he could just use
importinstead of require?Edit; note that
module.exports = X(which would enableconst X = require()) does not have an equivalent in ESM! Which one might love or hate, but is not something webpack can be blamed for.The problem is that Webpack favors modules over CommonJS by default. This is different from Node which results in mixing
importandrequire.node-fetch provides 2 flavors: CommonJS, and Modules: https://github.com/bitinn/node-fetch/blob/master/package.json#L5-L7
When Node sees
require("node-fetch), it’ll pick themainconfig while Webpack picksmodule. You can reconfigure this inwebpack.config.js:This still doesn’t work though, because
mainreferenceslib/indexand the first extension that Webpack uses is.mjs. That can be changed as well:Now Webpack uses the same resolve algorithm as Node, and will pick up the CommonJS variant of node-fetch. Webpack does warn about the optional
encodingmodule. If you prefer you can hide that warning using this config inwebpack.config.js:All of the same benefits that you get from bundling in frontend dev apply equally to writing console and server-side code i.e. you can use the latest javascript language features without having to worry about the environment within which your code is deployed and you can ship a complete app.bundle.js which requires no npm install. Try doing some AWS Lambda dev if you want to see the benefits of using a bundler for node code.
I realise that maintaining a library must be a huge headache given the state of javascript ecosystem. I’ll see what I can do today to (1) fix the problem (2) come up with a unit test. However please appreciate that (1) is more my concern than (2) and I already have a workaround for (1) which is to use an older version of your library (i.e. v 1.7.3)
Hi @bitinn you need to add the
target: 'node'to the webpack config (e.g. see https://github.com/ilanc/node-fetch-webpack/blob/master/webpack.config.js) otherwise it defaults to webpacking for the web (i.e. a browser). There are also babel settings to consider as well (e.g. babel-preset-env, .babelrc).I tried looking through the node-fetch issues before filing this and didn’t see anyone with the same problem.
I can have a look at this tomorrow if you want a pull request. I thought I’d post here so that people who are googling for answers can find it. It seems to be something that broke recently because it works in 1.7.3.
I am going to close this as we still don’t know why webpack doesn’t take
export default function, which it should.If webpack expect ALL backend modules to add their config file then they are badly mistaken (which I believe they are smart enough to avoid).
Your issue is more on how to use webpack properly, than node-fetch having a “bug”.
Of course, if people got a good suggestion on why and how to mitigate this, then we may at least update our readme to give some pointers.
Hmmm the problem is the mixing of module types. 1.7.3 has commonjs and 2.1.2 has es6 modules:
Seems like this is an evolving area of node development - see here and here. I’m just going to stick on 1.7.3 for now - I thought there would be a quicker fix.
if webpack is used in the project, global.fetch won’t work. Add following library in app root level.( recommended for serverless-webpack / any other web pack for lambda codestart )
require('cross-fetch/polyfill');