Modularity and Packaging for Angular2 Applications – Pawel Kozlowski

Thanks for coming. I know, you want to
know what’s better, webpack or broswerify, right? This is what we are for, here. So my name is Pawel Kozlowski,
a longtime Angular contributor. I’m working for
[INAUDIBLE] company, behind the software for
the travel industry. We use Angular for
our projects at work, but most importantly, we are
contributing back to Angular. That’s why I can
spend most of my time actually pushing code to
Angular and to repository, which I think is kind of good
model for companies that use open source. Anyway, we are here today
for the ES2015 modules. And just a disclaimer, I can’t
pronounce ES2015 all the time. So for me it’s ES6 still. And I guess we’re all excited
and happy about the fact that we’ve got
modules, or syntax and semantics for modules. So here you can see
the simple engine class, which I can export. I could also export a
variable or some other thing. And later on, as soon
as it’s exported, someone else can consume it. So by [? consume ?] it
I mean I can import. And when I’m saying I
want to import something, I need to say what I want and
from where I want to have it. Right? This is very simple. It’s this new specification
[? and ?] [? see ?] all those browsers, like they–
these wars on formats. It kind of puts in the
past all this situation where each and every
framework had to come up with its own module format. It’s end up this fight
between CommonJS or UMD or all those formats. So for the very
first time, we’ve got a very creative
syntax and semantic that normally should work
in node.js and in a browser. And as much as we
are happy about it, and we all want to author
in this new format, the reality on the ground is
that we can’t load these things into today’s browsers. And what I mean by this is that
if you take this code snippet, and try to put it into today’s
browser, in the script dock you will face two problems. The first one will be the fact
that import, export and from, those are the
parts of the syntax that are not really
parsed or understood today by the browsers. So [? what ?] [? should ?]
you get a parse error. Now there’s much
bigger problem here, because we are saying
import from and give it a string, which looks
like a filename or a URL or something– a piece of
string that points to something else, some other module. Now the question is, how can
you use the string to [? fire ?] the code we [? depend upon? ?]
Should it be from a file engine.js, or engine.ts, or
maybe it’s packaged already in some other file, like my
application packet dot js, right? And what about if I’ve got my
code written in CoffeeScript? I want to transpile it before. So there are plenty
of those questions, like how do I get this
code into the browser? Now the situation is
even worse than this. I can tell you. So we’ve got this
ES2015 specification, which specified how to
author our code using the new ES6 module format,
so the import/export. What is the semantic of this? What happens when
I import things? What happens when I’ve
got cycling dependencies? This all was specified. But the loading part,
how to fetch the code, what should I use? Should I use XHR, or JSMP, or
maybe fetch, to get actually the code into browser? This part was left over. It wasn’t ready
for the prime time. And it’s not part of the
ES2015 specification. Now, it’s a work in progress
in a different standard, [? body. ?] So it came
as a really shock for me that we’ve got the
whole specification, how to write our code,
but we’ve got nothing in their specification
on how to load this code, how to consume this code. Pretty bad, right? So what I hope to
do, what I’m hoping to do today is to go over
different scenarios on how to set up a build and
packaging, provided that you still want
to use this ES6 module format to write your code. And obviously, there’s seldom
one size fits all solution, so the setups will be
different for a Plunker or quite different for huge
multi-modular applications. And as much as I would love
to have this talk being very prescriptive, a cook
book like, technically, if you use Plunker do this. If you write a huge
application do that. What we are going to see,
there are multiple solutions. There are multiple setups that
gives you the same effect. So this talk is
partly invitation to discussion in the
community, like what we can do, how we can set up
those things so they are easy and performing. Now, whatever our
setup is, we need to start with transpiling,
because once again, browsers don’t understand
import or export. The good news is that all
the major transpilers, so Babel, Typescript,
and Tracer, they all understand and can
transform the module format, ES6 module format. Now it seems like Tracer is
kind of losing steam recently. So the choice is really
between Babel and Typescript. And I guess your
particular choice will depend on your stance
on the optional types. Do you like them,
or if you hate them, you will be choosing
one of those things. So when we choose
a transpiler, we need to say it when we
execute the transformations. And it can be done either
during the run time, when we’re loading code
into the browser, or as part of the build step. Obviously the run
time transpilation is only good enough for very
simple experiment, [? plunks ?] or quick Hello World
type of applications. Most of the real life
setups will involve some kind of build step. And the final
choice that we need to make when
transpiling our code is, what should be
the target format? What is the module
format that we should take ES6 and transpile to? Now, there are many formats. There are well-known ones
like CommonJS or AMD. There are tool-specific formats,
and there’s a new format called System register. But I think today, the real
choice is only between CommonJS and System register,
because AMD is slightly going out of fashion. And we’ve got very rich
[INAUDIBLE] for CommonJS. And we’ve got this
System register format, which is slightly
artificial in the sense that it was created to
support full semantics of ES6, including circular dependencies. So it’s kind of hard
to figure out format, because you wouldn’t
author in it. You wouldn’t write code
using this module format. But you can still transpile
code to this format. Now, the choice of the
target transpilation format will partly dictate what we
can do with module loading. And once again, here the problem
space is open to choices. But I think in this
room, or in any room, you will have two camps. On one hand you will
have people saying, like, OK, I know
that we don’t have this specification
for the loader, but we know some
things about it. Certain things were discussed
and were partly specified, So I want to be
part of this future. I want to use
those things today. And the second part of
the room would say, like, what you are talking about? There’s no specification. I don’t know how to
load these things. I know my stuff. I was using
browserify for years. I know perfectly well
what I’m supposed to do, as long as you are
giving me the CommonJS output. So let’s explore those
two possibilities. First, let’s say you are
in this futuristic camp. So once again, there’s no
specification for the loader, but there was part of
the specification in ES6. So we’ve got this set of
projects called SystemJS and some other products in
this whole ecosystem, products from Guy Bedford,
which is trying to write the polyfill,
like a super-polyfill, for the module loader. And I’m putting
polyfill in the quotes, because once again,
it’s very hard to write the polyfill
for something that is not even specified. And I’m also– it’s saying
that it’s super-polyfill, because it’s far more
than just a polyfill. Those projects can load
modules in different formats. There is a packaging step,
and so on and so forth. Now, what this system
loader would give us? Well, it would give us
the import statement that you can see here
on the system namespace. And this import statement
allows us to give a URL and it returns, or gives
back, a promise that results to a module
that we are loading. Right? There are more into
the system loading, but this is kind of entry
point to the application. That’s why in many examples
today, on many setups, that you can see
with AngularJS, you are going to see system
loader being used and then the XHTML will
look along those lines. So obviously we need
to include SystemJS. We need to configure it. And once again this
would be loader-specific. This is not something that
is part of any specification. And then we can
import our entry point to bootstrap the application. Look at this line here, where
we are including AngularJS. Actually we provide
a bundle, which can be loaded by SystemJS loader. So once again, this is
another view of our files. We’ve got system loader, we’ve
got our application code, and there’s the
bundle that we’ve got as part of the
[? MPM ?] distribution. And this bundle includes
an Angular tool code. It includes our
[? exit ?] dependency, which is mandatory, plus
some mandatory polyfills. All right, so this
is one of the setups that you have probably seen
quite often in the community. Now, I’m sure that part of you
were listening to me, saying what this guy is talking about,
there’s no specification. We are building on sand. Once again, I know
my [? tool link, ?] and I want to use things
that I know perfectly. And it is true, as soon as
the transpiler can output CommonJS or AMD or
any other format that you’re used
to working with, you can use your existing tool. You can use your
existing infrastructure to setup a build. Now, obviously we didn’t
have one module format, so we don’t have one tool. We’ve got many choices. People are comfortable
with different tools, with different work
flows, and so on. So this is part of this
problem in the community. That is, we’ve got this
fragmented community, where you can read a blog post
where someone is saying, like, use webpack, or use
[? webbay, ?] well here’s my setup and so on. So I will do the same. I will say, OK, if
you use webpack, or if you like webpack, here’s
one of the possible setups with webpack. So this is how index HTML could
look like when using webpack for packaging. It’s simpler, right,
compared to SystemJS, because I don’t have to
configure the [? holder, ?] there’s no [? holder ?] –and
there’s no presentation. Oh, it’s back. It’s cool. So what we are doing here? We are using just
regular script tags, including [? color ?]
dependencies, and including the bundle. Now what is in this bundleJS? Well, the only
reasonable setup that you can have today– we still
talk webpack or browserify– is the approach where we bundle
everything like our application code, Angular code,
the dependencies, into one gigantic file. So once again, this index
HTML looks quite simple, but you need to understand that
you also need to choose a tool, configure, and have this. So this is like, minimal
webpack configuration that I was able to come up with. Now it’s good to have all those
options, and to go over them, and say what exists,
what doesn’t. But I’m sure that you came here
asking what should I use today? And unfortunately,
as much I’d like to give you one
definitive answer, it would be dishonest, because
the space is very fragmented today. But there are some
guiding principles. On one hand, if you are new
to this whole transpiling, setting up stuff, and you don’t
know exactly what to choose, what I would suggest is to use
System Loader plus the bundles that we deliver today. And I’m saying this
because this is what all the Plunkers
use, like small snippets, that you can share. This is what we’ve got
in the documentation. And this is what you’ve got in
the [? Tour ?] [? of Heroes, ?] our sample application. So we will keep
seeing those setups. Now, on the other
hand, if you are already familiar with webpack,
browserify, or some other tool, you feel comfortable
with them, you feel like you’re a
master of this workflow, by all means use them. And what we are going to do,
or are going to try to do, is to make sure that all
the work flows are possible, that we are not distributing
things in a way that makes your life harder. Now, I’m sure that many people
were coming here to this talk and say like, this guy
will come on the stage and say that webpack is kicking
ass and the rest is rubbish, or that JSPM is the
tool of the future and everyone should switch now. Unfortunately, I
was experimenting with those tools for
the few past weeks, trying different setups,
trying to get minimal bundle without code application, trying
to get a setup which is really easy to write and understand. And I couldn’t. There was always
something that didn’t feel quite right with those setups. And just before this conference,
during the speakers dinner, we’re sitting on a
bus going to the pub, like few members of
the Angular team, and we had extremely
interesting conversation about the preferred tools. And it was discussion saying
like, oh, webpack does this for me and it’s great. And there was another [? conf ?]
log, but it’s just too big, it does all those things for me. So even in the
team itself, we are kind of having still
the preferences. I’m sorry. So this is the
state of the union, and I’m going to stuff you with
some details they you probably never wanted to know
about, which might help you in the future to
do proper choices or at least to see
where we are heading with what might happen in the
future, in terms of packaging. Now, remember our simple
[? glass ?] like the car that’s [? taken ?] engine. And I started by
saying that there are two possible
transpilation formats, either CommonJS or
System register. Let’s look at the examples
of the transpiled code. Once again, I don’t want you
to read it or remember it. This is not something
you would write by hand. But it gives you the feel of
the overhead of the format, or how it looks like. As comparison, there
is the CommonJS output, and you can see it’s
much more concise. It probably also
looks more familiar, because this is what you’ve
been using on other projects. So why this System register
is so much bigger as compared to CommonJS? Well, there is a
very simple reason, is that the System register
was designed as the format that tries to be correct. And correct in the sense
that it should give you all the semantic of module
dependencies as specified in ES6. And most notably, it
knows how to deal properly with the circular dependencies. So it needs– you’ve got
this overhead [INAUDIBLE]. On the other hand,
CommonJS has less noise, and it has all this
rich tooling, right? Like webpack is
natively consuming CommonJS. t Browserify
was created to consume JS. We know we’ve got all
those to [? link. ?] We know all those workflows. On the other hand, System
register, if you look at it, you can see that this
is just a function code. It fills in the System
register repository, which means that if
I’ve got multiple files, and I want to bundle
them or package them, it’s as simple as
concatenating files. I can also use this
output in the script tag and just to [? prepopulate ?]
the registry. So both formats have
got their pros and cons. And even for the
Angular packaging, we are going back and forth. We started with the
System register output because we are afraid of
this circular dependencies, then we removed them
from the code base and we see, like, OK, the
overhead of System register is just too big for
what we are doing. And we are considering
producing CommonJS output. So there are trade offs here. Now, there are
many discussions– I’m trying to talk like–
in the past few weeks, I was trying to
talk to everyone who was willing to listen, or to
talk to me about those topics. And when I had those
conversations, what I realized is that we are going through
the confused mode, because we are using [? port ?] system,
which is massively overloaded in this problem space. So on one hand, it means
the system [? has ?] the name space for
the import, I thought that we used to have
in ES6 specification. System registers the name of the
format that we just saw before. We’ve got the SystemJS
project, which is kind of trying to act
as the loader, polyfill. And on top of this, we’ve got
the whole ecosystem around the SystemJS project,
which has its bundler, , and so on and so forth. So I’m just kind of
highlighting this, because when we’ve got
this conversation together, we need to be precise just
to avoid misunderstandings. Now, this is how
things look today. But this is the
problem space which is quite new, like
the ES6 modules were specified just–
like specification was finished just this year. And this is also the space
where there’s a lot of movement. So as we know from the
“Back to the Future” movie, those guys were pretty bad
at predicting future, right? We don’t have flying cars. There’s actually a blog post I
found yesterday, 20 lies “Back to the Future” told. It excludes hoverboard. So we are bad at
predicting future, but there are few things
that can probably happen, and those things
will change the way we think about the
packaging and bundling. So one of those things is
that webpack is in like– things [? near ?] sorted or that
webpack is having [? branch ?] for webpack 2, which
is the second version. Webpack will be consuming
ES6 input, other than just focusing on CommonJS. On the other hand,
there are new projects, like Rollup, which are
trying to do proper tree shaking or minimal bundling. Actually understanding
the whole source code, all the methods that you are
calling, and create a bundle that only has called what
you are actually using. Once again, those protocols
are using ES6 as the input, so the CommonJS is less
interesting in this context. As you saw during the keynote,
we are working on the Angular 2 CLI, for which we are
going to make choices– we will be forced to
make choices like, what is the module
that you are using? What is the setup
that you are using? So we’ll have to have definitive
answer in the near future. And not to mention things like
HTTP, where the whole packaging idea might just be
thrown out of the window. So there are many,
many things happening, and many people thinking
about what’s the best setup. So there will be a lot of
movement in this space. It’s not the end the story. So the quick sum up. I think we all love ES6 modules. We want to author code using
this new module format. But we know, we
perfectly understand, as the community, the
current situation is messy. There are many tools. There are many workflows. There are many possibilities. We are not ready
as the Angular team yet to commit to one ecosystem. We don’t say like, OK,
you should be using JSPM, or you should be using webpack. But what we want to
do is to make sure that whatever tool you’re using,
that we are not doing anything to prevent or stop you
from using those tools. So if you see what we
distribute with Angular 2, how we distribute Angular 2, or
the formats that you are using, if there is anything
that stops you from having a proper workflow
that you like, just talk to me. Talk to us. Open Github issues. Let’s have this
conversation together. So, once again, let’s make
sure that we’ve got something that works for everyone. Now, this is all I’ve prepared. Thanks for coming, once again. And also, on the slides,
I compiled a list of several starter kits,
starting with the very small official ones, like a Plunker. I’m maintaining two sets of
the minimal starter kits, the ones that have got
minimal configuration that you can understand. And there are also links to the
well-known, community-driven starter kits. And for the questions
and answers, we can meet in half
an hour, in room 2. Thank you. [APPLAUSE]

3 thoughts on “Modularity and Packaging for Angular2 Applications – Pawel Kozlowski

  1. Misophonia makes listening to this talk impossible. I'm sorry. A tip for the future is to please take a drink before and during your talks.

Leave a Reply

Your email address will not be published. Required fields are marked *