Webpack compiler inside Meteor (ES6 modules, hot reload and code splitting!)

@dbismut: Thanks for this. Did the trick.

Hi - I’m trying to load Dropbox zxcvbn library as an async module in a textfield component, as in:

componentDidMount() {
    require(['zxcvbn'], function (obj) {
       this.setState({zxcvbn: obj});
   });
}

While this works perfectly in development environment, in production the server crashes with ReferenceError: window is not defined. I understand this is an issue with SSR, and I believe window is used by zxcvbn but I’m not sure how to make this work…

I hope that this project will be maintained and even supported by MDG somehow. Webpack with Meteor is a way better dev experience in my opinion. I can create build paths without any barriers in the way I like and with tools I could find on Npm. (simple example: stylus, css modules, sourcemaps, postcss with autoprefixer and other plugins - no problem, one line config, all in one project. With oonly Meteor this is almost impossible)

Webpack is performance aware and I can configure it in many ways in the context of performance. When using Webpack with Meteor I am sure that I have very elastic codebase. And of course it is way better in code reloads (thanks to HotModuleReplacement)

I would like to read more about how this project evolving and I would like to read about apps based on it and dev opinions. Not only here. I hope that it will gain some more attention. (ps. let me know if there is any official website for this project).

I would like to see a Meteor branch with Webpack for devs who like some more control over the app and don’t afraid of Webpack. And also a standard Meteor branch with simple ES6 imports and Npm supports shipped as a simple to run box (as it will be from Meteor 1.3).

Awesome project. Keep it going.

4 Likes

After updating my project to the most recent config for FlowRouter, I am no longer allowed to do code splitting in the router. Something like this no longer works for me:

Landing.route('/', {
    name: 'welcome',
    action() {
        require.ensure([], require => {
            let Welcome = require('./pages/Welcome/Welcome.jsx');
            ReactLayout.render(LandingLayout, {
                children: <Welcome/>
            });
        });
    }
});
2 Likes

Nothing looks wrong to me. I’ll take a look when I have a few minutes.

1 Like

Here are the errors I’m getting in the console:

Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components).
and
Uncaught Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

So, my routes work when I import the components using es6 import at the top of my file. If I don’t use import and use let Component = require(‘path/to/file’) instead to import my components, it does not work and spits out those same errors. So, I actually think it’s not necessarily the code splitting that is broken, but with importing a component with require.

This is because since Babel 6, the default export is on .default. The import use it automatically but not the require.

You have to do:

require('module').default

It should work

1 Like

i have tried Meteor + Webpack for 1 week:

  • It’s freedom to use ES6 and npm module and nodejs style
  • Building code faster
  • reuse both package system: npm and meteor package

and much more. I tried meteor 1.3 beta too. it’s future but i have issues about install npm module that not specific to web browser.

I have just created an account only to tell @benoitt : thanks for your great work !

1 Like

Haha thank you. Stay tune for a huge improvement on the upcoming 1.0 release (in about 2 weeks) :smile:

9 Likes

I wait for your release with the same enthusiasm I used to have for Meteor releases.

2 Likes

What a great project :smile:

I have a few questions:

  • What are the known drawbacks of using this approach instead of Meteor 1.3?
  • Are there any more benefits than hot-reload in development, working SSR and code splitting (compared to Meteor 1.3)?
  • Does the hot-code-push still work in Cordova?
  • How does code splitting works in Cordova? Does it store the lazy required modules like the Meteor normal html, css y js and they work even if the user opens the app without connection or those lazy required modules are always send over the net and require connection?
  • What do we expect on the 1.0 release!?!?

Thanks!

This seems like a good explanation:
forums.meteor.com/t/why-is-the-meteor-install-1-3-api-better-than-webpack-in-meteor/14480/3

And this:
forums.meteor.com/t/why-is-the-meteor-install-1-3-api-better-than-webpack-in-meteor/14480/24

Still want to know more about the other questions :sweat_smile:

@benoitt I added webpack-font-awesome npm package and it works on development environment, but when I try to build for production I get the following error saying that window is not defined. I’ve also tried removing the font-awesome package, but I still get this issue. Is there some webpack cache somewhere that I need to clear? Any thoughts?

=> Exited with code: 8
W20160203-21:39:32.902(-5)? (STDERR)
W20160203-21:39:32.903(-5)? (STDERR) C:\Users\panw\AppData\Local\.meteor\packages\meteor-tool\1.1.10\mt-os.windows.x86_32\dev_bundle\server-lib\node_modules\fibers\future.js:245
W20160203-21:39:32.904(-5)? (STDERR)                                            throw(ex);
W20160203-21:39:32.904(-5)? (STDERR)                                                  ^
W20160203-21:39:32.904(-5)? (STDERR) ReferenceError: window is not defined

Someone succeed into having LESS or Stylus integrated with Webpack?

You need stylus-loader usage like:

(...)
cssLoader = 'style!css!stylus-loader'; 
{
  test: /\.styl$/,
  loader: cssLoader
}
(...)

or with css modules like:

(...)
cssLoader = 'style!css?modules&importLoaders=1&localIdentName=[name]__[local]__[hash:base64:5]!stylus-loader'; 
{
  test: /\.styl$/,
  loader: cssLoader
}
(...)

you can add stylus plugins in your webpack conf by:

(...)
stylus: function () {
  return [sGrid, Rupture]
}
(...)

you can even add postcss loader and use it like:

(...)
cssLoader = 'style!css?modules&importLoaders=1&localIdentName=[name]__[local]__[hash:base64:5]!postcss!stylus-loader'; 
{
  test: /\.styl$/,
  loader: cssLoader
}
(...)
stylus: function () {
  return [sGrid, Rupture]
},
postcss: function () {
  return [autoprefixer];
}
2 Likes

@juliancwirko Super nice. It works like a charm. I was piping ‘stylus’ instead of ‘stylus-loader’. Your sample set me on the right track. Thanks!

@benoitt,
Does code splitting in webpack mean that my app is no more served as a single js file?
I’d like to be able to split my app in two “parts”:

  • core meteor files, that don’t change and are cached on user’s browser
  • app-specific files, that change when I push updates for my app into production
    When user opens the app, he should only need to download the “second part”. Is that achievable with webpack?

Code splitting means your user don’t need to load your entire app as soon as he opens the first page. He can load just what he needs and request more only when he needs it.

If you want to split the code of the libraries you’re using vs your own, you can use a common chunk by using webpack.optimize.CommonsChunkPlugin.

You can read more on code splitting here.

1 Like

@benoitt Benoit, first of all, thanks for the great package! However, I miss the possibility to set the port through WEBPACK_PORT env variable. Could you please enable this possibility? I often run several meteor instances, so I have a script which finds free ports to run them, I would like to have the same for webpack dev server.