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

While the Meteor community was hacking projects this weekend, I was also hacking but the Meteor build system :smile:. You can now seamlessly integrate Webpack within your Meteor application.

Why should you do this?

  • Hot-reload with React (probably doable with others): The amazingly fast hot-reload with no page refresh. This is a killer feature. Works with Cordova!
  • ES6 modules: this will be introduced in Meteor in the future but with Webpack, you can be in the future!
  • Bundle your assets for you when you require them
  • Code splitting: you can actually make people only load a part of your application and dynamiclly load the rest when they need it. This is actually great for admins and stuff you donā€™t want everyone to download no matter where they are.
  • Support Cordova!

You can configure your Webpack config on the server and on the client by using exactly the same syntax as anyone using Webpack. Obviously, it has been simplified because it needs to be built inside Meteor so it will override a few configs.

You can try it by cloning the kickstart-simple project (simple example for simple app or learn) or the kickstart-hugeapp project (include code splitting, very interesting for big applications).

I think having this inside the Meteor build is a big leap forward. Let me know what you guys are thinking!

@SkinnyGeek1010 @ccorcos @lai @jedwards @imkost @none @mats @brajt @sikanx @timfletcher youā€™ve used the previous verision I would like your opinion on this :smile:

76 Likes

Dude, this is amazing! @benoitt, youā€™re that man! I really hope you won the hackathon. +100

This link for anyone to see how it was built:
https://github.com/thereactivestack/meteor-webpack/tree/master/plugin

Well done. Iā€™m impressed you were able to able to do this entirely through a package, but it makes sense. Looks like the Meteor build system is more flexible than I thought. If only meteor had formal documentation for it!

Hereā€™s an idea to take it a step further. Would it be possible to create an api so so we can add webpack.client.js and webpack.server.js to individual packages like coffeescript or jsx to configure webpack just as we do with any other package? This would ease some the webpack learning curve. I think MDG would be all behind that.

3 Likes

wow youre amazin <3. Have you personally switched your production app to this new setup yet?

1 Like

Using the CommonsChunkPlugin to optimally share common code between different entry points.

https://github.com/thereactivestack/meteor-webpack/blob/master/plugin/WebpackCompiler.js#L136

This is really a well-done. Thank you do much.

1 Like

Thanks, it would be amazing considering I am not registred haha. I donā€™t think :stuck_out_tongue: It took me 4 days morning to night to get this right.

Iā€™m not sure I understand your idea. Do you mean instead of configuring JSX inside Webpack you could add wepback:jsx and it would include JSX inside Webpack automaticlly? I think itā€™s a good idea. I want to keep the flexibility of editing your own config file because everyone want a different build process. I think itā€™s worth considering, at least for beginners.

Not yet but it is on itā€™s way. I donā€™t see any reason why I would not. It makes the deployment and the build so much easier to deal with.

I was really focused on optimizing your Webpack config out-of-the-box so it made sense :smile:


My kickstart projects are missing unit tests and integration tests. Then I will be satisfied :smiley:

1 Like

Hi @benoitt, On Windows I get error message:

events.js:72 throw er; // Unhandled ā€˜errorā€™ event
Error: Cannot find module ā€˜exposifyā€™ from ā€˜/C/Users/username/AppData/Local/.meteor/packages/reactrouter_react-router/0.1.9/npm/ā€™ .

Also, to note, when trying to delete the kickstart project i get error message ā€œFile name too longā€
(there seem to be some quite long file/path).

Greets and thanks

I can not test it right now, but do source maps work = important for debugging? I just skimmed the repo and that really looks like a clean awesome implementation.

I havenā€™t tested it with Windows yet but Iā€™ll be doing this today.

Thatā€™s weird. You should try to delete your folder /C/Users/username/AppData/Local/.meteor/packages/reactrouter_react-router and build again. The symbolic link for node_modules might be problematic too. Iā€™ll be testing Windows today.

This is a typical NPM problem. Here is a solution.

1 Like

YES I did worked a great deal to make sure the source map Webpack is generating is sent to Meteor build system. You will have a clean call stack / line numbers! :smile:

1 Like

I just got home :grin: checking it out right now. Seems to work flawlessly. Your webpack:webpack implementation is incredible close to what I started -> kicking out the meteor build process instead of servering files back and forth from a shadow directory.

I am looking for a flawless TypeScript integration with modules to better server enterprise application structures without pre-compilation. Wondering now if meteor-webpack already plays along with the TypeScript loader https://github.com/TypeStrong/ts-loader

1 Like

Probably most people will prefer this way of doing things, though Iā€™m wary of having the system automatically decide what to inject into my Webpack config ā€“ I want full control over that. Iā€™m more into flexibility than ease of use. For instance I would prefer to get to use 0.0.0.0 as the host instead of localhost, so that I can debug on mobile devices over LAN.

function prepareConfig(target, webpackConfig, usingDevServer) {
  if (usingDevServer) {
    webpackConfig.entry = ['webpack-hot-middleware/client?path=http://localhost:' + WEBPACK_PORT + '/__webpack_hmr', webpackConfig.entry];
  }

There is already a perfect, standardized location for dev server settings in the Webpack config files ā€“ I would recommend just reading the host and port from config.devServer.host and config.devServer.port instead of e.g. a WEBPACK_PORT environment variable.

The commons chunk thing is convenient if it fits oneā€™s use case, but sometimes people want multiple commons chunks too.

When I had tried to write something like this, if I killed Meteor and restarted it without changing the source files, isobuild doesnā€™t invoke the build plugins again. So I wasnā€™t getting my Meteor compiler to re-run until I changed the webpack.config.js files again. Did you find some workaround? Also I was using a hack to get it to restart the server when the server-side webpack bundles were rebuilt, did you find some elegant way to do it?

1 Like

I will happily do that. I think it is important that people keep a complete control over how the build process is done.

For the common plugin, I agree we also need a way to disable that. Maybe it should be by default. I will be looking into that.

1 Like

Yes! You can add any loader to your Webpack configs. You just add ts-loader to packages.json and the loader to your webpack.conf.js on the client and on the server. I havenā€™t tested it yet but I would be surprised it didnā€™t work.

1 Like

Thanks.

Just in case anyone has a problem deleting folders on windows, this is how I delete the npm_modules folders:

npm install rimraf -g

cd packages\npm-container\.npm\package
rimraf node_modules

cd ..\..\..\..
cd .meteor\local\isopacks\npm-container\npm
rimraf node_modules

Well, one of the benefits of meteor is simply ā€œconvention over configurationā€ - developer experience as first priority. So not really a good place to ask for full control in general.

But Iā€™ll agree regarding some flexibility. Maybe there should be a well balanced default set-up but enable overwrites by dropping them into the app folder - having the build system pick them up when available.

I personally value highly quick developer on-boarding instead of set-up and training in tooling.

1 Like

Cool, thanks! Once enough flexibility is possible with your project Iā€™ll probably ditch mine and start using yours :slight_smile:

1 Like

Iā€™m very excited, and want to follow this thread. A repo is a great start - a tutorial / video even better :)ā€¦ Iā€™m curious - when do you use ā€˜importā€™ - and when do use ā€˜requireā€™ - require only on server Iā€™m guessing ?

1 Like

Yes, both have value for sure. To some degree the tools could check the Webpack config for overrides, but I think some overrides would have to live outside the Webpack config (for instance preventing some plugins from automatically getting added).

But I also have to say, weā€™re all using Webpack because we donā€™t like the Meteor conventions of global variables, no importing, etc.

2 Likes

Also @benoitt will this work with code splitting caused by async requires (rather than commons chunks)?