i18next / i18next-http-backend

i18next-http-backend is a backend layer for i18next using in Node.js, in the browser and for Deno.
MIT License
454 stars 71 forks source link

SyntaxError in Internet Explorer 11 (IE11) #19

Closed jbanulso closed 4 years ago

jbanulso commented 4 years ago

🐛 Bug Report

Using the package in Internet Explorer throws a SyntaxError due to the use of non-transpiled ES6 syntax in the code.

To Reproduce

Use the package in a IE11 context.

Expected behavior

I know there is debate on whether dependencies should be shipped already transpiled or not, but even other packages of this project (i.e. i18next, react-i18next) are transpiled, so it would make sense for this one to be as well.

Temporary solution

For those facing the same issue, I modified my Webpack config and made babel-loader "un-ignore" the package like this:

{
  test: /\.js$/,
  use: 'babel-loader',
  exclude: /node_modules\/(?!i18next-http-backend)/
}
jbanulso commented 4 years ago

Sorry, I had missed #15, importing from i18next-http-backend/cjs solves the problem.

adrai commented 4 years ago

fyi: With the latest version importing with /cjs should not be necessary anymore.

jbanulso commented 4 years ago

That's excellent, thank you!

jbanulso commented 4 years ago

@adrai I've now realised something strange: updating to the latest version works fine during development with webpack-dev-server, but when serving a production bundle I still get a SyntaxError.

I think I've found the culprit to be the use of classes in the library node-fetch, which this package depends on - i.e. class Blob, class Headers, class Response and class Request. However I don't really understand why it happens with the production bundle but not the development one 🤔

PS: Using import i18next-http-backend/cjs doesn't work in this scenario either.

adrai commented 4 years ago

node-fetch should not even load on browser

adrai commented 4 years ago

maybe a strange configuration in your setup?

jbanulso commented 4 years ago

maybe a strange configuration in your setup?

I think I'm using a pretty standard setup, but something could be off...

node-fetch should not even load on browser

Maybe this is me not fully understanding how bundling works, but if you're requiring node-fetch (even if dynamically), Webpack will need to add the node-fetch code to the bundle in case it's needed, which will then be parsed by the browser (and thus breaking in IE11). In development it works because Webpack uses eval(/* your code as a string */) by default.

This is the part of my bundle that is defining the getFetch import, which is the one responsible for importing node-fetch:

/***/ "../../node_modules/i18next-http-backend/esm/getFetch.cjs":
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global) {var fetchApi
if (typeof fetch === 'function') {
  if (typeof global !== 'undefined' && global.fetch) {
    fetchApi = global.fetch
  } else if (typeof window !== 'undefined' && window.fetch) {
    fetchApi = window.fetch
  }
}

if ( true && (typeof window === 'undefined' || typeof window.document === 'undefined')) {
  var f = fetchApi || __webpack_require__("../../node_modules/node-fetch/lib/index.mjs")
  if (f.default) f = f.default
  exports.default = f
  module.exports = exports.default
}

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__("../../node_modules/webpack/buildin/global.js")))

/***/ }),
adrai commented 4 years ago

If you have any idea how to solve this, let me know... To fix this in userland, you probably need: https://www.npmjs.com/package/webpack-node-externals

adrai commented 4 years ago

btw: I created a minimal webpack example... => https://github.com/adrai/webpack-demo Is this also not working for you? For me it seems there is no node-fetch bundled in here: https://github.com/adrai/webpack-demo/blob/master/dist/main.js

jbanulso commented 4 years ago

If you have any idea how to solve this, let me know... To fix this in userland, you probably need: https://www.npmjs.com/package/webpack-node-externals

Not sure how to solve it - as a workaround I can use the externals field as you suggest and then it'll work just fine:

externals: {
  'node-fetch': 'node-fetch'
}

btw: I created a minimal webpack example... => https://github.com/adrai/webpack-demo Is this also not working for you? For me it seems there is no node-fetch bundled in here: https://github.com/adrai/webpack-demo/blob/master/dist/main.js

Just tried it, as you say there's no node-fetch in there... I wonder why 🤔

EDIT: there is node-fetch, but it's importing browser.js instead of index.js.

adrai commented 4 years ago

EDIT: there is node-fetch, but it's importing browser.js instead of index.js.

Which should not hurt, right?

jbanulso commented 4 years ago

Yeah, that's okay.

I found what was causing the issue. In my Webpack config I was having the following: mainFields: ['module', 'browser', 'main'], so the "normal" export was taking priority. Moving 'browser' to be the first element in the array means browser.js is loaded.

jbanulso commented 4 years ago

I found what was causing the issue. In my Webpack config I was having the following: mainFields: ['module', 'browser', 'main'], so the "normal" export was taking priority. Moving 'browser' to be the first element in the array means browser.js is loaded.

Maybe that'd be a good solution for this package as well, to separate the code that is browser-only from the rest.

adrai commented 4 years ago

nice you found the issue 👍