rxaviers / globalize-webpack-plugin

Globalize.js webpack plugin
Other
33 stars 27 forks source link

Error: No formatters or parsers has been provided, when production is 'true'. #10

Open harel opened 8 years ago

harel commented 8 years ago

Following the examples provided, using globalize-webpack-plugin 0.2 and globalize 1.1.0-rc.7 (as well as rc.5 and rc.6), when setting production:true I'm getting the following error below:

Config

new GlobalizePlugin({
    production: true,
    developmentLocale: 'en-GB', // locale to be used for development.
    supportedLocales: ['en-GB', 'en'], // locales that should be built support for. 
    output: 'i18n/[locale].[hash].js' // build output.
}),

Error at npm run build

> webpack --config webpack.prod.config.js --progress

 76% create chunk assets/home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/GlobalizeCompilerHelper.js:72
      throw e;
            ^
Error: No formatters or parsers has been provided
    at compiler (/home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/node_modules/globalize-compiler/lib/compile.js:175:9)
    at Object.compileExtracts (/home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/node_modules/globalize-compiler/lib/compile-extracts.js:59:9)
    at GlobalizeCompilerHelper.compile (/home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/GlobalizeCompilerHelper.js:63:33)
    at /home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/ProductionModePlugin.js:219:51
    at String.replace (native)
    at /home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/ProductionModePlugin.js:213:58
    at Array.forEach (native)
    at /home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/ProductionModePlugin.js:211:63
    at Array.forEach (native)
    at Compilation.<anonymous> (/home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/ProductionModePlugin.js:209:10)
    at Compilation.applyPlugins (/home/harel/dev/app/ui/node_modules/webpack/node_modules/tapable/lib/Tapable.js:26:37)
    at Compilation.<anonymous> (/home/harel/dev/app/ui/node_modules/webpack/lib/Compilation.js:558:8)
    at Compilation.applyPluginsAsync (/home/harel/dev/app/ui/node_modules/webpack/node_modules/tapable/lib/Tapable.js:60:69)
    at Compilation.seal (/home/harel/dev/app/ui/node_modules/webpack/lib/Compilation.js:525:7)
    at Compiler.<anonymous> (/home/harel/dev/app/ui/node_modules/webpack/lib/Compiler.js:397:15)
    at /home/harel/dev/app/ui/node_modules/webpack/node_modules/tapable/lib/Tapable.js:103:11
    at Compilation.<anonymous> (/home/harel/dev/app/ui/node_modules/webpack/lib/Compilation.js:445:10)
    at /home/harel/dev/app/ui/node_modules/webpack/lib/Compilation.js:417:12
    at /home/harel/dev/app/ui/node_modules/webpack/lib/Compilation.js:332:10
    at /home/harel/dev/app/ui/node_modules/webpack/node_modules/async/lib/async.js:52:16
    at done (/home/harel/dev/app/ui/node_modules/webpack/node_modules/async/lib/async.js:246:17)
    at /home/harel/dev/app/ui/node_modules/webpack/node_modules/async/lib/async.js:44:16
    at /home/harel/dev/app/ui/node_modules/webpack/lib/Compilation.js:332:10
    at /home/harel/dev/app/ui/node_modules/webpack/node_modules/async/lib/async.js:52:16
    at done (/home/harel/dev/app/ui/node_modules/webpack/node_modules/async/lib/async.js:246:17)
    at /home/harel/dev/app/ui/node_modules/webpack/node_modules/async/lib/async.js:44:16
    at /home/harel/dev/app/ui/node_modules/webpack/lib/Compilation.js:332:10
    at /home/harel/dev/app/ui/node_modules/webpack/node_modules/async/lib/async.js:52:16
    at done (/home/harel/dev/app/ui/node_modules/webpack/node_modules/async/lib/async.js:246:17)
    at /home/harel/dev/app/ui/node_modules/webpack/node_modules/async/lib/async.js:44:16
adros commented 8 years ago

+1, I'm facing the same issue

rxaviers commented 8 years ago

Hi, thanks for filing this issue.

I could not reproduce it. I have cloned git@github.com:jquery/globalize.git, chdir to examples/app-npm-webpack, ran npm install, then npm run build, which worked just fine.

Please, could you describe the steps you are taking in more details? Also, note that in the webpack config, we have the following code below, which is slightly different than the one you posted, which might suggest it's good to double check you have up-to-date example.

  new GlobalizePlugin({
    production: options.production,
    developmentLocale: "en",
    supportedLocales: [ "ar", "de", "en", "es", "pt", "ru", "zh" ],
    messages: "messages/[locale].json",
    output: "i18n/[locale].[hash].js"
  })
harel commented 8 years ago

Hi @rxaviers I just omitted the optional messages key for now, but otherwise my config is the same - just with different locales. The error I'm getting is only when i run npm run build and the production flag is set to true.

I pasted my dependencies from packages.json. If it makes any difference, my build kinda stalls at around 50% for a good few seconds then continues until this error comes up. I also tried to do a build with just 'en' locale but no luck. This error is persistent. I've pretty much tried any configuration I can think of including different release candidates.

"dependencies": {
    "globalize-webpack-plugin": "^0.2.0", 
    "bluebird": "^2.9.34",
    "classnames": "^2.2.1",
    "cldr": "^3.2.0",
    "cldr-data": "^28.0.3",
    "globalize": "^1.1.0-rc.7",
    "history": "^1.13.0",
    "immutable": "^3.7.6",
    "jquery": "^2.1.4",
    "json-loader": "^0.5.4",
    "lodash": "^3.10.1",
    "react": "^0.14.3",
    "react-addons-clone-with-props": "^0.14.3",
    "react-addons-pure-render-mixin": "^0.14.2",
    "react-big-calendar": "^0.9.5",
    "react-dom": "^0.14.2",
    "react-intl-tel-input": "^2.0.2",
    "react-redux": "^4.0.0",
    "react-remarkable": "^1.1.1",
    "react-router": "^1.0.0-rc3",
    "react-widgets": "^3.1.3",
    "redux": "^3.0.4",
    "redux-logger": "^2.0.4",
    "redux-thunk": "^1.0.0",
    "semantic-ui": "^2.1.6",
    "superagent": "^1.3.0",
    "superagent-bluebird-promise": "^2.0.2"
  },
harel commented 8 years ago

Just in case, I tried with the messages key included. Still same result. @adros , I thought I was the only one, so bummer you're getting that error but I'm glad I'm not alone. Before I thought it might merit a ticket here I tried StackOverflow, but for some reason my question offended someone enough to downvote it: http://stackoverflow.com/questions/34360579/webpack-globalize-fails-build-when-set-to-production-mode-no-formatters-or-pars

harel commented 8 years ago

@rxaviers I just reread your comment - the problem is not with globalize itself. Its with my application and the use of globaalize webpack plugin. When I build MY application with production:true in the GlobalizePlugin config then I get that error. Globalize itself is fine I'm sure

adros commented 8 years ago

Well, I have probably found the issue: my code does not (yet) contain any formatters; code like this one:

Globalize.formatMessage("intro-1")()

(which is corresponding to the error message 'No formatters or parsers has been provided'.)

As soon as I add this code somewhere in the application, it starts working.

But when I use globalize with react (which is obviously also @harel's situation), my application may really not have any Globalize.formatMessage calls. Because I may just use Globalize as localizer for react-widgets (http://jquense.github.io/react-widgets/docs/#/i18n) or I may format messages using react-globalize module.

adros commented 8 years ago

But when I check the output in 'release' mode, maybe this plugin is not suitable for usage with react-globalize, because only those messages get to 'globalize-compiled-data', which are used directly by a Globalize method. Is it true?

adros commented 8 years ago

I have end up with the same issue when I use yours react-globalize-webpack-plugin set writeMessages: true, and there is no call for Globalize.formatMessage.

What I really want to do, is just use globalize with webpack. And I have not succeeded without yours plugin. But the plugin seems to do more than I want, it tries to analyse the code and extracts only used messages. Which makes unable to write code like this one:

var key="intro-1";  
console.log(Globalize.formatMessage(key)());

because the compilation fails... ReferenceError: key is not defined.

Is it possible to skip this advanced features?

harel commented 8 years ago

I can confirm the error goes away after using @adros trick of putting a formatMessage somewhere. The build completes without error. However, that means that 'messages' are not optional, they are required. As well, If I add a messages dir as per my config, and add one file per locale, I get json parsing errors unless i remove all spaces from the json file.

so this fails :

{ 
     "en-GB": {
           "message": "some message"
     }
}

but this works:

{"en-GB":{"message":"some message"}}

And as well, I don't get the i18n directory in my build/assets. Its just not there on build...

harel commented 8 years ago

The json parsing errors appear on dev as well.

> webpack --config webpack.prod.config.js --progress

undefined:2
    "en-GB": {
^
SyntaxError: Unexpected token  
    at Object.parse (native)
    at Object.module.exports.readMessages (/home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/util.js:42:17)
    at new DevelopmentModePlugin (/home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/DevelopmentModePlugin.js:17:42)
    at GlobalizePlugin.apply (/home/harel/dev/app/ui/node_modules/globalize-webpack-plugin/index.js:22:35)
    at Compiler.apply (/home/harel/dev/app/ui/node_modules/webpack/node_modules/tapable/lib/Tapable.js:164:16)
    at OptionsApply.WebpackOptionsApply.process (/home/harel/dev/app/ui/node_modules/webpack/lib/WebpackOptionsApply.js:62:18)
    at webpack (/home/harel/dev/app/ui/node_modules/webpack/lib/webpack.js:22:48)
    at processOptions (/home/harel/dev/app/ui/node_modules/webpack/bin/webpack.js:152:17)
    at Object.<anonymous> (/home/harel/dev/app/ui/node_modules/webpack/bin/webpack.js:192:1)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3

npm ERR! Linux 3.13.0-73-generic
npm ERR! argv "/usr/bin/node" "/usr/bin/npm" "run" "build"
npm ERR! node v0.12.9
npm ERR! npm  v2.14.9
npm ERR! code ELIFECYCLE
npm ERR! ui@1.0.0 build: `webpack --config webpack.prod.config.js --progress`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the ui@1.0.0 build script 'webpack --config webpack.prod.config.js --progress'.
npm ERR! This is most likely a problem with the ui package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     webpack --config webpack.prod.config.js --progress
npm ERR! You can get their info via:
npm ERR!     npm owner ls ui
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /home/harel/dev/app/ui/npm-debug.log
harel commented 8 years ago

Sorry, i had production flag set to false when I tested just now. I tested again with production set to true, and it works still. The message files get bundled up in my app.js file though and not in the i18n directory as I specified in the output property.

harel commented 8 years ago

Ok I resolved part of this: When specifying the output as "i18n_[locale].js" it does generate the files. As well, when specifying the output as the full path into the assets dir "assets/i18n/[locale].js" it does work as well and they are generated. There is still the problem where pretty json (with indentations) fails with invalid json error above. The same json as is, passes a json linter just fine as valid. So not sure why it fails here.

rxaviers commented 8 years ago

messages is optional considering you're not using it (i.e., not using formatMessage or messageFormatter). Please, could you provide a gist with a reduced example that I can use to reproduce the problem you are facing?

harel commented 8 years ago

the only thing I've done while having this problem is adding the plugin to my webpack config as described above, excluding the messages key. On dev mode it worked fine. But when setting production to true and running npm run build it failed. That is, until I tried the trick above which resolved it (i.e., adding messages and a formatMessage somewhere). Since then I've gone all in on globalizer and now am using the messages module and things are working fine. I'm not really sure how to dilute my app into a working 'failing' example at this point.

rxaviers commented 8 years ago

Gotcha, this error shows up when no Globalize code is being used in the source code. messages is optional and this issue should be fixed.

matthiasfeist commented 8 years ago

I'm having the same issue with a webpack and react project. It seems that the production mode of the plugin can't see that I'm using a formatter and then crashes with an error message...

matthiasfeist commented 8 years ago

It seems as if the globalize-compiler is not able to figure out which formatters are used when the JS code is actually compiled by babel...

rxaviers commented 8 years ago

@matthiasfeist if you have a formatter being used in your code, you have a different issue. Please, file a new issue with context. Also make sure you have Globalize 1.1.x in place.

matthiasfeist commented 8 years ago

Thanks for the response. It was actually the issue with a version conflict :+1: thanks for the heads up!

rxaviers commented 8 years ago

Excellent and you're welcome.

lochstar commented 8 years ago

I'm having the exact same issue. Using globalize with react-globalize. I am not using the message component.

rxaviers commented 8 years ago

@lochstar do you use any Globalize function or react-globalize component?

lochstar commented 8 years ago

The only Globalize function I'm using is Globalize.locale(). I'm also using FormatCurrency, FormatDate, FormatNumber & FormatRelativeTime.

rxaviers commented 8 years ago

Since you're using react-components this bug shouldn't affect you. You should set the default locale via your webpack config, not Globalize.locale(). That might be the reason.

lochstar commented 8 years ago

It's set via webpack config as well. I use Globalize.locale() in my code to change the locale via a select box.

If I remove the call, the error still persists when trying to build for production.

rxaviers commented 8 years ago

Hm, ok. So, please file a separate ticket providing a reduced example.

lochstar commented 8 years ago

I've determined the following:

include Globalize with reference in the code - production build passes include Globalize with no reference in the code - production build fails include Globalize and react-globalize with no reference in the code - production build fails include Globalize and react-globalize with reference in the code - production build passes

So production build works fine in both cases, as long as there's a direct call to Globalize in the source. I shouldn't need to include this as I have react-globalize components.

Any ideas? Is this a react-globalize issue?

brenwell commented 8 years ago

+1 same here

rxaviers commented 8 years ago

I really want to help you all, but it seems we're collecting so many different things for this issue.

This issue is supposed to track a bug that shows up when trying to use the plugin while no Globalize code is being used in the source code.

PS: react-globalize uses Globalize under the hoods, so using react-globalize messages and/or Globalize messages (.formatMessage) is equivalent.

rxaviers commented 8 years ago

If you have problems with the react-globalize-plugin, please file an issue on rxaviers/react-globalize-webpack-plugin. I have provided a react-globalize example here, so please use this example as a baseline for yours. File the issue with an example in place (feel free to file a PR with the example then).

rxaviers commented 8 years ago

If you have problems with this plugin (globalize-plugin) and it isn't the bug defined by this issue (using this plugin while no Globalize or react-globalize code is being used in the source code), please file a separate issue including an example. You can use this example as a baseline for yours.

If you are experiencing the bug defined here, PRs are welcome. The fix shouldn't be hard. I can provide assistance.

EXC-BAD-ACCESS commented 8 years ago

it also appears that in production mode that the require literally needs to be tied to a variable named "Globalize" in order for this error message to not appear. i.e.:

var Globalize = require( "globalize" ); Globalize.formatMessage( "Success" );

will succeed, but:

var i18n = require( "globalize" ); i18n.formatMessage( "Success" );

will fail with the "Error: No formatters or parsers has been provided" message

rxaviers commented 8 years ago

@AppSorcery you're correct, but this is a separate issue. The globalize-compiler is still pretty naive on that regard. It simply checks for Globalize (code) instead of the name declared in the import (in which case the compiler would have to keep a table of the scopes and variable names to check for).

rxaviers commented 8 years ago

@lochstar, @brenwell, @AppSorcery, you could have experienced this bug react-globalize-webpack-plugin#14.

aliry commented 8 years ago

I've also had the same issue with production build $\node_modules\globalize-webpack-plugin\GlobalizeCompilerHelper.js:72 throw e; ^ Error: No formatters or parsers has been provided

It will work if I add the following somewhere in the app!

Globalize.formatMessage("someMessage");

Its actually very annoying issue since the workaround basically means we have to add lines in the code to call to formatMessage API for every single entry in our .JSON files Otherwise the those entries will not exist in the compiled .js files in i18n folder.

FYI: we are not using react-globalize

matteoantoci commented 8 years ago

Hi! Any new on this issue? I have the same problem

gehsekky commented 7 years ago

Sorry for beating a dead horse, but we are seeing this issue as well when building our app using webpack with production flag set to true:

Our app doesn't use messaging and just uses the number parsing feature of globalize.

Error: No formatters or parsers has been provided

We are including globalize with:

import Globalize from 'globalize';

Any suggestions?

rxaviers commented 7 years ago

This definitely needs fix. PRs are welcome. I can provide assistance.

gehsekky commented 7 years ago

@rxaviers hey, thanks for the quick reply. I see that dynamic locale loading has been brought up relating to this issue and was curious if you have a recommended way of doing that in an npm-webpack environment. The current example app with npm and webpack is really just good for one language but doesn't really do anything for those of us with use cases involving language pickers, etc. You've mentioned writing a custom {cldr: fn()} in the webpack config but does that mean if we want to select between 5 locales in the language picker, we'd need to pre-load all 5 locales in globalize?

kolesnikova-tavi commented 7 years ago

Error: No formatters or parsers has been provided

I have the same problem.

EXC-BAD-ACCESS commented 7 years ago

@gehsekky no you wouldn't pre-load all 5 locales (into the browser all at once), you would look at the request headers (accepts language, e.g.) or some parameter you define in your request and load just that one locale (which would contain all of your localized messages including the localized text options for your language picker).

then if the user selects a different locale you change the header or parameter and perform a new request (you could try and do something clever and fetch the new language bundle from a cdn over ajax and completely update the client without hitting the server...but i haven't tried it yet).

darincardin commented 7 years ago

Same EXACT issue with my code. If set to production mode, you get the error mentioned in the title. Seems like they are not going to fix this; apparently the issue has been around for two years now.

casey-speer commented 7 years ago

Same problem, I am using globalize-webpack-plugin in a client app that references our own home-grown react formatter components, which in turn use our custom formatters library that calls Globalize directly. No direct mention of Globalize in the client app however. Any way around this? I prefer the idea of having webpack build only the formatters that are ultimately used, but globalize plugin can't yet handle this indirection.

rxaviers commented 7 years ago

This is the most annoying issue :)

Perhaps we could simply catch that exception (thrown by globalize-compiler) and console.warn it in here instead. PRs are welcome... What are the potential impact? Warn (instead of throwing) on cases where this plugin is being used uselessly?

diligiant commented 7 years ago

@darincardin and @casey-speer, may you push a sample repo with your issue at hand? I'll be happy to take a look and fix it.

casey-speer commented 7 years ago

What I'd like to happen is that if globalize is used indirectly, globalize-webpack-plugin would be able to find that usage and extract/compile formatters for it. E.g., in my client code I have

import NumberFormatter from 'myFormatterComponents/number';

const myComponent = ({number}) => (<span> Look at this number: <NumberFormatter value={number} /></span>);

and in a separate npm module myFormatterComponents/number.jsx I have

import numberFormatter from 'myFormatters/number';

export const NumberFormatter = ({value}) => (<span>{numberFormatter(value)}</span>);

finally in another npm module myFormatters/number.js:

import Globalize from 'globalize';
export const numberFormatter = (value) => { return Globalize.formatNumber(value) };

I just want to drop in globalize-webpack-plugin in my client app and and have it extract/compile the necessary globalize formatters for my entire app bundle, regardless of how they are included in the bundled code. (Kind of a contrived example, but having a separate formatters library is currently a requirement of our applications for various reasons).

Does this make sense or is it unreasonable? I think for this case it's not a 'useless' inclusion of the plugin, just that the globalize formatters don't appear in first-party code from the perspective of the client app. I'd still want those formatter instances to be extracted/compiled. Maybe I'm misunderstanding some limitations here? Thanks!

diligiant commented 7 years ago

@casey-speer I get it. May you create a q&r sample repo? It will be much easier.

rxaviers commented 7 years ago

Hi @casey-speer, this requires extra smarts to the globalize-compiler. Feel free to express your thoughts on how you think that could be doable. Specially, please read this https://github.com/globalizejs/globalize-compiler/issues/10.

Having said that, that seems a different topic and should be discussed elsewhere, not in this thread. Feel free to file an issue in globalize-compiler with your thoughts. Thanks.

casey-speer commented 7 years ago

@diligiant @rxaviers Yes I think this does turn out to be off-topic. I've read through that issue and a lot of the globalize, gloablize-compiler, and globalize-webpack-plugin code and I have a better understanding of how all this works. My solution is going to be to generate a statically-analyzable set of formatters and either precompile them along with the runtime per locale or else feed them to the webpack plugin. Thanks for your help.

Moxh3 commented 6 years ago

Having kind of the same issue as well..

node_modules\globalize-webpack-plugin\GlobalizeCompilerHelper.js:77 throw e; ^ Error: No formatters or parsers has been provided

However, adding a formatting function like Globalize.formatMessage("someMessage"); does not help. My webpack config looks like

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractCSS = new ExtractTextPlugin('allstyles.css');
const GlobalizePlugin = require("globalize-webpack-plugin");

module.exports = {
    entry: {
        main: './wwwroot/source/app.js',
        vendor: [
            "globalize",
            "globalize/dist/globalize-runtime/number",
            "globalize/dist/globalize-runtime/currency",
            "globalize/dist/globalize-runtime/date",
            "globalize/dist/globalize-runtime/message",
            "globalize/dist/globalize-runtime/plural",
            "globalize/dist/globalize-runtime/relative-time",
            "globalize/dist/globalize-runtime/unit"
        ]
    },
    output: {
        path: path.resolve(__dirname, 'wwwroot/dist'),
        filename: 'bundle.js',
        publicPath: 'dist/'
    },
    plugins: [
        extractCSS,
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            Popper: ['popper.js', 'default'],
            //Globalize: 'globalize'
        }),
        new GlobalizePlugin({
            production: true, // true: production, false: development
            developmentLocale: "en", // locale to be used for development.
            supportedLocales: ["en", "nl", "fr"], // locales that should be built support for.
            output: "globalize-compiled-data-[locale].[hash].js", // build output.
            tmpdirBase: ".", // optional for non create-react-apps
        }),       
    ].concat([
            new webpack.optimize.UglifyJsPlugin()
        ]),
    module: {
        rules: [
            {
                test: /\.css$/,
                use: extractCSS.extract({
                    fallback: 'style-loader',
                    use: 'css-loader?minimize'
                })
            },
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            },
            {
                test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                loader: "url-loader?limit=10000&mimetype=application/font-woff"
            },
            {
                test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                loader: "file-loader"
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192
                        }
                    }
                ]
            }

        ]
    }
};

Versions: