webpack2 - v3.5.x breaks `.use()` method #836

Closed
EvNaverniouk opened this Issue Nov 7, 2016 · 31 comments

Projects

None yet

5 participants

@EvNaverniouk
EvNaverniouk commented Nov 7, 2016 edited

After upgrading from v3.4.4 to v3.5.0, I am no longer able to run:

import i18next from 'i18next';
import LngDetector from 'i18next-browser-languagedetector';
i18next.use(LngDetector);

Which now returns:

main.js:90 Uncaught TypeError: _i18next2.default.use is not a function

Printing out i18next indeed shows that the default export method no longer has the use method exposed.

This does not occur on v3.4.4.

@jamuhl
Member
jamuhl commented Nov 7, 2016

argh...seems there was some update of a dependency of a dependency breaking the build to something useless (without warning)...

give me some minutes to figure out how to update those.

@jamuhl
Member
jamuhl commented Nov 7, 2016

could you try i18next@3.5.1

@EvNaverniouk

@jamuhl Unfortunately the problem persists with @3.5.1

@jamuhl
Member
jamuhl commented Nov 7, 2016

just tested in react-i18next and seems to work

do you use webpack 2?

@EvNaverniouk

Yes, using webpack 2.1.0-beta.25

@jamuhl
Member
jamuhl commented Nov 7, 2016

then the issue is related to having module defined in package.json which leads to the es scripts - not sure why webpack2 does not work with them while rollbar does

@jamuhl
Member
jamuhl commented Nov 7, 2016

webpack/webpack#1979 should be a correct export here (transpiled with es6 module system)...not sure why it fails.

@jamuhl
Member
jamuhl commented Nov 7, 2016

@mull any idea?

@jamuhl jamuhl changed the title from v3.5.0 breaks `.use()` method to webpack2 - v3.5.x breaks `.use()` method Nov 8, 2016
@jamuhl
Member
jamuhl commented Nov 8, 2016

@EvNaverniouk could you provide some sample code using webpack v2 so i could investigate?

honestly i not yet had time to try the upcoming version myself.

@EvNaverniouk

@jamuhl Here's a tiny reproducible test case: https://github.com/EvNaverniouk/i18next-836

@jamuhl
Member
jamuhl commented Nov 8, 2016

changed the sample to:

import i18next from 'i18next';

const logger = {
  type: 'logger',

  log: function(args) { console.log(args); },
  warn: function(args) { console.warn(args); },
  error: function(args) { console.error(args); }
}

console.warn(i18next)
console.warn('typeof use', typeof i18next.use)
i18next.use(logger);

i18next.init({
  lng: 'en',
  resources: {
    en: {
      translation: {
        "key": "hello world"
      }
    }
  }
}, () => {
  console.warn(i18next.t('key'));
})

and get:

main.js:13 typeof use function(anonymous function)
main.js:26 hello world

works at my env:
mac osx
node: 6.9.1
npm: 3.10.8

@EvNaverniouk

Ok, interesting. So after some more digging I see that:

  • Using import i18next with plain webpack2 works
  • Using require('i18next') with plain webpack2 doesn't work
  • Using import i18next with babel-loader and babel via webpack2 doesn't work
  • Using require('i18next') with babel-loader and babel via webpack2 doesn't work

I'm still inclined to believe this is an issue with i18next and not with webpack as this is so far the only module I've encountered with this behaviour. But I must admit, I don't understand why these results different so much.

Any ideas? Did something change with the module registration between v3.4.x and v3.5.0?

@jamuhl
Member
jamuhl commented Nov 9, 2016

well the only thing that changed:

before 3.5.0 there was no module definition in package.json - so webpack had to take the commonjs files as defined in main (no treeshaking). On 3.5.0 we introduced the module export like described here webpack/webpack#1979 which leads to the transpiled es files just leaving the module system (import/export) which is the correct thing to do...if module maintainers over es exports for rollbar/webpack2 they should not run through babel again - as you might not have the same source in your project as the module itself.

makes all sense to me (but might be someone with more webpack knowhow could enlight us?)

so 3.5.x leads webpack via module entry in package.json to files that are transpiles and use module export/import

so a) you can't require them as those are no commonjs compatible:

Using require('i18next') with plain webpack2 doesn't work
Using require('i18next') with babel-loader and babel via webpack2 doesn't work

as there is nothing imported at all:

the last one using import and babel-loader:

you import the file and transpile it to commonjs - webpack wants to import it - but it's no longer using the export statement but is a commonjs file - so import will fail:

Using import i18next with babel-loader and babel via webpack2 doesn't work

Or might be i'm wrong...but seems really correct for me. You should never need to run babel over node_modules

@xiwc
xiwc commented Nov 9, 2016

Meet the same trouble. Back to 3.4.x work fine.

@jamuhl jamuhl referenced this issue in webpack/webpack Nov 9, 2016
Closed

Will/does Webpack support "module" field? #1979

@jamuhl
Member
jamuhl commented Nov 9, 2016

i placed a question over at webpack...hope we get some information there. But basically i still hope it's allright - as explained above - do not babel transpile files in your node_modules folder.

@zewa666 zewa666 referenced this issue in aurelia/i18n Nov 9, 2016
Closed

Issue with i18n and webpack #172

@jamuhl
Member
jamuhl commented Nov 9, 2016

for the sake of getting this semver compatible:

3.5.2 -> removed the module entry point and will work as used
4.0.0 -> adds the entry point module for webpack2

4.0.0 works with webpack2-beta under following conditions:

  • you only use import import i18next from 'i18next';
  • you do not run babel over that files
@EvNaverniouk

Unfortunately, 4.0.0 is still giving me troubles.

import i18next from 'i18next';
console.log(i18next);
// => {default: {loggers: {...}, modules: {...}, observers: {...}, options: {...}, services: {...}}};
i18next.use();
// => Uncaught TypeError: _i18next2.default.use is not a function(…)
@jamuhl
Member
jamuhl commented Nov 10, 2016 edited

the use function is on the prototype...do you still run babel over the node_module?

can you please extend your sample https://github.com/EvNaverniouk/i18next-836 so it fails?

@jamuhl
Member
jamuhl commented Nov 10, 2016

really seems you run babel over it:

console.log(i18next);
// => {default: {loggers: {...}, modules: {...}, observers: {...}, options: {...}, services: {...}}};

import i18next from 'i18next' should be importing the default if not transpiled again.

try import { default } from 'i18next' -> should work => you transpiled it to commonjs

@EvNaverniouk

https://github.com/EvNaverniouk/i18next-836 has been updated to use v4 and babel.

Babel is running over my application code (in this case main.js), but node_modules is ignored.

@jamuhl
Member
jamuhl commented Nov 10, 2016 edited

reading https://gist.github.com/sokra/27b24881210b56bbaff7

specially update: https://gist.github.com/sokra/27b24881210b56bbaff7#gistcomment-1842602

changing your babel.rc to:

{
    "presets": [ [ "es2015", { "modules": false } ] ]
}

enables treeshaking by not converting import/export to commonjs style - makes it work.

@EvNaverniouk

Thanks for all your work @jamuhl. Changing the babel preset to disable modules did the trick and didn't cause any other issues in our application. Really appreciate the support!

@jamuhl
Member
jamuhl commented Nov 10, 2016

great...glad we found a solution

@jamuhl
Member
jamuhl commented Nov 11, 2016

and...if you ever feel to support i18next more - give locize.com a try:

https://www.youtube.com/watch?v=uO30Jm8TSy4

It directly supports the future development of i18next.

@rosskevin
rosskevin commented Nov 11, 2016 edited

I just upgraded to the 4.0.0 release.

@EvNaverniouk did you have to remove node_modules from the ignore? I've made the .babelrc change but I still am seeing:

application.js:4412Uncaught TypeError: _i18next2.default.use is not a function(…)

Where usage is:

import i18next from 'i18next'
i18next
  .use(logger)
  .use(Backend)
  .use(Cache)
  .use(LanguageDetector)
  .init(options)

Any thoughts?

@rosskevin

Ugh, it seems like I didn't npm prune and it was picking up the old version. I have 4.0.0 confirmed working as well.

@luisherranz

I'm having the same default.use is not a function error with webpack 1.13.3 and i18next 3.5.2 when webpack is used with -p.

I tried going back to previous versions (3.1.0, 3.2.0...) but that didn't work either. Is there some cache I should purge?

Oh, and I can't disable modules in my app ({ "modules": false }) because that breaks other parts.

@luisherranz

Strange thing is that if I modify my node_modules/i18next/index.js and I add a console.log it works:

console.log('3.5.2');
module.exports = require('./dist/commonjs/index.js').default;

I added it to see if I was using the correct version (and not a cached version) but now it turns out that if I leave that console.log, it works, but if I remove it, it breaks again. Same version 3.5.2.

@luisherranz
luisherranz commented Nov 18, 2016 edited

It looks like adding any random code is enough to make this work:

This fails:

module.exports = require('./dist/commonjs/index.js').default;

This works:

var a;
module.exports = require('./dist/commonjs/index.js').default;

Is this a i18next or a webpack problem?

@luisherranz

I've opened a new issue to discuss it, so this one can remain closed: #841

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment