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
453 stars 70 forks source link

Firefox 34 Syntax Error #15

Closed fynncfchen closed 4 years ago

fynncfchen commented 4 years ago

🐛 Bug Report

Firefox 34 got syntax error, the file compiled by Babel are not use older syntax.

SyntaxError: missing ; before statement

Compiled file:

const arr = [];
const each = arr.forEach;
const slice = arr.slice;

function defaults(obj) {
  each.call(slice.call(arguments, 1), source => {
    if (source) {
      for (var prop in source) {
        if (obj[prop] === undefined) obj[prop] = source[prop];
      }
    }
  });
  return obj;
}

To Reproduce

  1. Use i18next-xhr-backend for the first time with i18n.js
    
    import i18n from 'i18next';
    import Backend from 'i18next-xhr-backend';
    import LanguageDetector from 'i18next-browser-languagedetector';
    import { initReactI18next } from 'react-i18next';

i18n .use(Backend) .use(LanguageDetector) .use(initReactI18next) .init();


2. Open Firefox 34, the website is fine
3. Change to use `i18next-http-backend`

```javascript
import i18n from 'i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init();
  1. Open Firefox 34, got syntax error

Expected behavior

Use both i18next-xhr-backend and i18next-http-backend should be work fine.

Your Environment

adrai commented 4 years ago

ohhh.... old browser version... But I'm not able to reproduce it... I also tried v33... Can you create a reproducable example? Can you try a PR? Or propose a concrete code change?

fynncfchen commented 4 years ago

Found a possible cause:

I use Parcel as our bundler, and the order they're use are

https://github.com/parcel-bundler/parcel/blob/060db2e2c56f08e223e9a9075035f0998e249763/packages/core/parcel-bundler/src/Resolver.js#L295

Means that the resolver will use a not-bundled version of package (./lib/index.js)

https://github.com/i18next/i18next-http-backend/blob/9c6a73b0c51293995bc42dae3c3f6f4a2bbd6271/package.json#L17

which using a ES6+ syntax.

That's very different from the i18next-xhr-backend:

https://github.com/i18next/i18next-xhr-backend/blob/d9a3daa6fd199b93430cb81860d197030188806a/package.json#L6

which use a bundled version of package:

import _classCallCheck from '@babel/runtime/helpers/esm/classCallCheck';
import _createClass from '@babel/runtime/helpers/esm/createClass';
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import _typeof from '@babel/runtime/helpers/esm/typeof';

var arr = [];
var each = arr.forEach;
var slice = arr.slice;
function defaults(obj) {
  each.call(slice.call(arguments, 1), function (source) {
    if (source) {
      for (var prop in source) {
        if (obj[prop] === undefined) obj[prop] = source[prop];
      }
    }
  });
  return obj;
}

There's a solution to solve this problem: use a browser field in package.json to tell a bundler to use for browser:

https://parceljs.org/module_resolution.html#package.json-%60browser%60-field

I suggest to provide a migration notes in document for replacing the deprecated i18next-xhr-backend with a different Behavior.

adrai commented 4 years ago

A little question: Is your parcel setup not babeling the files? (I've never used parcel)

fynncfchen commented 4 years ago

AFAIK the current stable version (v1) of Parcel doesn't have the option to include some of the package should be compiled, which means we should assume that all packages in node_modules are bundled.

Another approach to solve this issue is to import the cjs version of this package explicitly:

import Backend from 'i18next-http-backend/cjs';
adrai commented 4 years ago

Ok, didn't know Parcel is not able to transpile it... ok... importing import Backend from 'i18next-http-backend/cjs'; is a valid solution 👍

fynncfchen commented 4 years ago

Unfortunately after some clean up and test, I found the solution from above not work anymore, even if I use

import Backend from 'i18next-http-backend/i18nextHttpBackend';

I think it might not to use any require in a bundled version CJS module, should be like i18next-xhr-backend do - bundle an internal AJAX inside.

because I got this new message:

TypeError: global.fetch is undefined

I'll go back to use i18next-xhr-backend anyway.

adrai commented 4 years ago

@fynncfchen if you create a reproducable example I can try to help. i18next-xhr-request will not get any more updates, so it would be better to fix this here...

fynncfchen commented 4 years ago

I found it's hard to reproduce by myself also, sorry..... I'll dig into my project to find the real problem and feedback to you, thanks for help!

adrai commented 4 years ago

This is my playground: https://github.com/adrai/parcel-example-i18next-http-backend maybe you can reproduce it there

fynncfchen commented 4 years ago

Good news! I finally can reproduce what I've got! https://github.com/fynncfchen/i18next-http-backend-issue You can yarn then yarn start and see if the dist folder has a getFetch.[hash].cjs, also check at i18next-http-backend-issue.[hash].js you can find some ES6+ syntax there. Open http://localhost:1234 on Firefox 34, you can see an syntax error just what I've reported.

adrai commented 4 years ago

This is because you’re importing like: import Backend from "i18next-http-backend"; Try: import Backend from "i18next-http-backend/cjs";

adrai commented 4 years ago

If you need a transpiled source (seems by default for parcel this is the case), you need to import /cjs

fynncfchen commented 4 years ago

I'm not sure what happened but after I deleted yarn.lock and re-install all packages, the /cjs version works on my project. Maybe the problem coming from the dependence tree....

adrai commented 4 years ago

In your example: https://github.com/fynncfchen/i18next-http-backend-issue you are not importing cjs

fynncfchen commented 4 years ago

I know, when I importing cjs in my example and it works, but in my real project it failed. I think the dependencies are different.

fynncfchen commented 4 years ago

I found that ^1.0.8 not work for cjs, but the latest version works!

adrai commented 4 years ago

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