Hands up, despite being one of the maintainers of ts-loader (a TypeScript loader for webpack) I have not been tracking webpack v2. My reasons? Well, I'm keen on cutting edge but bleeding edge is often not a ton of fun as dealing with regularly breaking changes is frustrating. I'm generally happy to wait for things to settle down a bit before leaping aboard. However, webpack 2 RC'd last week and so it's time to take a look!
Let's take ts-loader's webpack 1 example and try and port it to webpack 2. Will it work? Probably; I'm aware of other people using ts-loader with webpack 2. It'll be a voyage of discovery. Like Darwin on the Beagle, I shall document our voyage for a couple of reasons:
- I'm probably going to get some stuff wrong. That's fine; one of the best ways to learn is to make mistakes. So do let me know where I go wrong.
- I'm doing this based on what I've read in the new docs; they're very much a work in progress and the mistakes I make here may lead to those docs improving even more. That matters; documentation matters. I'll be leaning heavily on the Migrating from v1 to v2 guide.
First of all, let's install the latest RC of webpack:
Let's look at our existing
There's a number of things we need to do here. First of all, we can get rid of the empty extension under resolve; I understand that's unnecessary now. Also, I'm going to get rid of
'.web.js'; I never used them anyway. Also, just having
'babel' as a loader won't fly anymore. We need that suffix as well.
Now I could start renaming
rules as the terminology is changing. But I'd like to deal with that later since I know the old school names are still supported at present. More interestingly, I seem to remember hearing that one of the super exciting things about webpack is that it supports modules directly now. (I think that's supposed to be good for tree-shaking but I'm not totally certain.)
Initially I thought I was supposed to switch to a custom babel preset called
<a href="https://www.npmjs.com/package/babel-preset-es2015-webpack">babel-preset-es2015-webpack</a>. However it has a big "DEPRECATED" mark at the top and it says I should just use
babel-preset-es2015 (which I already am) with the following option specified:
Looking at our existing config you'll note that for
js files we're using
options in the new world I understand) to configure babel usage. We're using query parameters for
ts files. I have zero idea how to configure preset options using query parameters. Fiddling with
options didn't seem to work. So, I've decided to abandon using query entirely and drop in a
<a href="http://babeljs.io/docs/usage/babelrc/">.babelrc</a> file using our presets combined with the
<a href="https://babeljs.io/docs/plugins/#plugin-preset-options">modules</a> setting:
As an aside; apparently these are applied in reverse order. So
es2016 is applied first,
es2015 second and
react third. I'm not totally certain this is correct; the
<a href="http://babeljs.io/docs/usage/babelrc/">.babelrc</a> docs are a little unclear.
With our query options extracted we're down to a simpler
In our example the
plugins section of our
webpack.config.js is extended in a separate process. Whilst we're developing we also set the
debug flag to be
true. It seems we need to introduce a
LoaderOptionsPlugin to do this for us.
As we introduce our
LoaderOptionsPlugin we also need to make sure that we provide it with
options. How do I know this? Well someone raised an issue against ts-loader. I don't think this is actually an issue with ts-loader; I think it's just a webpack 2 thing. I could be wrong; answers on a postcard please.
Either way, to get up and running we just need the
LoaderOptionsPlugin in play. Consequently, most of what follows in our
webpack.js file is unchanged:
LoaderOptionsPlugin we hardly new ya#
After a little more experimentation it seems that the
LoaderOptionsPlugin is not necessary at all for our own use case. In fact it's probably not best practice to get used to using it as it's only intended to live a short while whilst people move from webpack 1 to webpack 2. In that vein let's tweak our
webpack.js file once more:
Finally Karma. Our
karma.conf.js with webpack 1 looked like this:
We just need to chop out the
debug statement from the
webpack section like so:
We now have a repo that works with webpack 2 rc 1. Yay! If you'd like to see it then take a look here.
I thought I'd compare performance / output size of compiling with webpack 1 to webpack 2. First of all in debug / development mode:
Size and compilation time is not massively different from webpack 1 to webpack 2. It's all about the same. I'm not sure if that's to be expected or not.... Though I've a feeling in production mode I'm supposed to feel the benefits of tree shaking so let's have a go:
To my surprise this looks pretty much unchanged before and after as well. This may be a sign I have missed something crucial out. Or maybe that's to be expected. Do give me a heads up if I've missed something...