Migration from Require.js to Webpack 2

Long story short, we have decided migrate our 4 years old project (x8 full time front-end developers) from Require.js to Webpack@2. I love Require.js, how it works, i feel like it is outdated right now.

Why moving out?

How Require.js works? For development it does not require build step (which takes around 2 minutes for me and i don’t want to wait another 2 minutes after each file save.) but instead every file and it’s dependencies will be loaded dynamically in browser. It’s good and bad. Works fine but…

When project grows and grows dynamic loading starts taking more and more… 20 seconds or even more. That’s not right.

There are few development server tools for Require.js which do caching but all of them are pretty old and do not support features we need such as tree shaking, hot reloading, code splitting etc.

Next step

Webpack@2 does support features we need and even more. So next part of the article will be focused on how we moved our Require.js code to Webpack.

Here is basic Require.js config we had (much shorter version)

Let’s start

This config can be logically split to 4 pieces:

  1. Vendor libraries which are in vendors folder, not node_modules
  2. Shimming libraries
  3. Packages support
  4. Different build targets support (enterprise, freemium etc)

Aliases

When any vendor file will be imported we want to use short name instead of full path. This works by default for node_modules but does not for our vendor folder. That is pretty straightforward — just using webpack alias.

So we are changing Require.js config

to Webpack config

Shimming libraries

If some libraries have dependencies they should be loaded first, in required order and be available for target library.

For shimming we used imports-loader, exports-loader and expose-loader.

imports-loader for import dependencies and make internal library this to be a window for some libraries.

exports-loader to make some libraries importable by exporting local library results.

expose-loader to push some libraries results to global window scope for some old libraries.

Packages support

Our UI uses packages or modules system so requiring widgets/users will load widget/users/main.js file.

That was easy — webpack supports packaging from the box. We were using main.js main file convention so just renamed all main.js files to index.js.

Different build targets

We have some packages and files replacement depends on build target (enterprise, freemium etc) so this should be done too.

Other

We need also to define root path (baseUrl for Require.js), modules folders and files extensions

Many of our files were using text!./file.hbs plugin for loading handlebars so we just installed text-loader and used resolveLoader to allow use shorthand loader syntax instead of text-loader.

And define compilers

Conclusion

That’s how we did our HUGE project migration from Require.js to Webpack 2, it took around 2 days for 1 developer. Hope this will be helpful.