Skip to content

Rebuild speed and style workflows (feedback) #2956

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sasxa opened this issue Oct 31, 2016 · 7 comments
Closed

Rebuild speed and style workflows (feedback) #2956

sasxa opened this issue Oct 31, 2016 · 7 comments

Comments

@sasxa
Copy link

sasxa commented Oct 31, 2016

I just finished rewriting my old gulp build tasks to work with CLI. Results are... interesting :) #1980

CLI

c:\project>ng s
** NG Live Development Server is running on http://localhost:4200. **
17976ms building modules
...
Time: 26259ms
...
webpack: bundle is now VALID.

webpack: bundle is now INVALID.
Time: 10887ms

webpack: bundle is now INVALID.
Time: 6893ms

webpack: bundle is now INVALID.
Time: 5964ms

webpack: bundle is now INVALID.
Time: 9595ms

Gulp

c:\project>gulp
[00:47:08] Requiring external module ts-node/register
[00:47:15] Starting 'watch'...
[brSync] Watching files...
[brSync] Access URLs:
       Local: http://localhost:3000
[00:47:18] Finished 'serve' after 2.14 s

[00:48:42] Starting 'ts'...
[00:48:43] all files 16.27 kB
[00:48:43] Finished 'ts' after 194 ms

[00:49:33] Starting 'ts'...
[00:49:33] Starting 'styl'...
[00:49:33] Finished 'styl' after 171 ms
[00:49:33] Finished 'ts' after 200 ms

[00:50:17] Starting 'ts'...
[00:50:17] Finished 'ts' after 57 ms

[00:51:52] Starting 'ts'...
[00:51:52] Starting 'styl'...
[00:51:52] Finished 'styl' after 274 ms
[00:51:52] all files 15.83 kB
[00:51:52] Finished 'ts' after 308 ms

1
2

Webpack is,, of course, much better at optimizing assets, while gulp can be optimized for really fast incremental builds. At this time I didn't do anything with vendor files, I'm just serving them with BrowserSync directly from node_modules - that's why there are so many requests and why load times are high. I also didn't bother with code splitting, AoT and other stuff Webpack and CLI already do - I just want fast dev builds; I'm definitely gonna use CLI for that stuff.

This is done at the same time in two terminal windows - first running Gulp watch and serving files with BrowserSync, second running webpack-dev-server. If you want to try it yourself, you can find full logs and files I used here: (Gist). Build works with CLI project with some modification - for index.html and system.config.js I used files from docs/quickstart and modified them to fit my project. Only other thing needed to make it work is to remove import './polyfills.ts'; from 'src/main.ts`.

OK, now the reason I'm writing this is to share what I learned while trying to make this work, hopefully it will be useful and help improve CLI.

Styling


  • It would be nice if workflow with style pre-processors was easier: I'm using stylus and I couldn't find any options to include some shared files and mixins. In my project I created src/styles/ folder where all my .styl files are and I'm importing them from src/styles.styl with @import 'styles/defaults'. I also have src/styles/variables.styl where I @import "C:/.library/styl/mixins.styl"... It would be nice if we had access to stylus to extend it, like I'm doing:
.pipe(__.stylus({
    include: [
      path.resolve(PATH.root, 'src'),
      path.resolve(PATH.root, 'src', 'styles'),
      path.resolve(PATH.lib, 'styl')]
  }))
  • Same goes for other modules (html-minifier, autoprefixer, csso...). Since I couldn't setup paths where stylus looks for imports, I had to use @import '../../styles/variables' in my component styles, which I had to remove in order to process styles with Gulp file.replace(/@import\s+'(?:\.\.\/)+/gmi, '@import \'').

  • Another nice feature would be to have separate file for inline styles, that would be injected directly in <head> while the rest are loaded normally, via <link>. I think I saw something like this in early versions with --mobile and/or --universal... I saw some improvements with styles workflows on master branch, nice! Hope to see more (;

Dev builds


  • Concerning module resolution, I'm using "compilerOptions.baseUrl": "." path mapping so I can use import {...} from 'app/core/service' instead of import {...} from '../../../../app/core/service' in my components. Might be useful to be there by default? I saw some issues/PRs/commits with import {...} from '@shared' - not sure what's the status of that, but aliasing app root is really useful for me.

  • While building my gulp tasks I noticed that rebuilding typescript files seams to be main reason for high rebuild times. I chose to use settings that give me fastest results

  • I'm not bundling files, my components/services/modules etc. are in separate files. This allows me to utilize gulp's caching, so it will only process changed files:

  return gulp.src(files, {
    since: gulp.lastRun('ts')
  })
  • I used "isolatedModules": true, compiler option to make this work. TypeScript now Unconditionally emit imports for unresolved files., which also speed things up.

  • I'm injecting everything in js file - templates, styles, sourcemaps. It's not ideal, and sourcemaps are not precise, but I usually know what I'm doing, so most of the time I can find errors quickly. And if not, I can always use different options to track down bugs. With 50-250ms rebuild times I work differently then when I have to wait 5-15s... For production builds and various optimizations I really don't mind waiting 30-90s.

  • While I don't think something like this should be default option for CLI, perhaps there are some things you could turn off, or do differently to speed things up. Maybe provide some flag to turn off some safety checks, not bundle everything each time and such. I'm not that familiar with webpack to offer any suggestions, but maybe something I mentioned can help (;

Finally, just to mention the dreadful systemjs... The way I have structured my modules and components is really, really painful to setup with systemjs. In fact, making it work took me almost as long as everything else... It was the reason why I was happy CLI switched to webpack. Working with CLI is soo much easier. If (or when!) CLI was 10x faster I would gladly forget everything about systemjs. Forever (:

@reco
Copy link

reco commented Oct 31, 2016

hey angular cli team. looks all amazing.

we are in the same situation. we have a custom gulp workflow. its crazy fast compared to angular-cli. app reload for js/ts changes is fine but styles should be injected like browser sync does it.

is this on the roadmap?

@ialexivy
Copy link

ialexivy commented Nov 1, 2016

Any updates ?
It's so slow , it's better to use Lite-Server, and lose all CLI benefits.

@sasxa
Copy link
Author

sasxa commented Nov 2, 2016

I've been working on this for past few days - exploring alternatives and tinkering with various options. It would be so much easier if documentation was better... I cleaned up some stuff, improved few things and got from 6-8 sec reload time to about 4 seconds. This is using SystemJS and serving all files from node_modules. Don't think things can get much better with this approach:

Image 1

Main reason is rxjs - Angular heavily depends on it and it's loading stuff from library everywhere. These 400+ requests in the image above are for rxjs stuff (almost 80% of them). The next thing I did was to bundle all angular modules, so they load rxjs from memory, instead of the network. That improved things somewhat, but my code was also calling rxjs alot. So I bundled rxjs too:

Image 2

Loading is faster and XHR requests are just for app code (almost 5x less). I ended up using rollup for angular and systejs-builder for rxjs - couldn't do better with my trial&error approach - configuring systemjs is still most painfull thing is all this process. I had to use System API to load modules from bundle, couldn't figure out how to set it up with System.config().

Bundling framework code seams to be the best approach. I've seen it in some other projects and seeds, and it's working well. Perhaps someone can do it for CLI too, using webpack. I believe this workflow would be beneficial. I'm not sure how things work internally with webpack, does it use umd bundles or es6 files?

I still have few things to do for my dev workflow. My goal is to get to about 1 second full reload times (without HMR). I think I can get there with http2. Also, to make it plug-and-play-nicely with CLI. If it turns out webpack isn't as fast, maybe this can become CLI add-on some day (;

@hiepxanh
Copy link
Contributor

hiepxanh commented Nov 3, 2016

wow this amazing, I feel really stress if everything just slow in current angular CLI version. If you have a big project, that is a disaster.

I vote for this solution

@sasxa
Copy link
Author

sasxa commented Nov 3, 2016

It seams things can't get much better then my last setup (Image 2). At least not without AoT. Image 3 shows the log of the same project built with ng build --prod and served with browser-sync from dist/ folder. Even though there's almost 5x less requests, reload time is only 0.5 seconds shorter.

Image 3

I tried to implement HMR and managed to connect to dev server, notify systemjs and reload modules as they are compiled, but didn't figure out what to do to update app itself yet.

@filipesilva
Copy link
Contributor

Heya @sasxa, thank for the the benchmarks and setup details. I'll address some of the issues raised here but am still closing this particular issue because it's essentially a dupe of #1980 as far as it being actionable goes, although your post was more informational and exploratory.

  • It's hard to beat a setup that doesn't recompile/bundle everything on every pass such as your Gulp-based one. We recognise that rebuild speed is super important for dev workflows and getting those down is one of our last remaining action items for a CLI 1.0.
  • As you noted, one of the things that was troublesome in your setup was SystemJS config - which was also the reason we moved to Webpack. The third party journey in Webpack is the most user-friendly at the moment.
  • Regarding preprocessor include functionality, there's already Passing additional options to node-sass #1791 and a implementation PR (feat(sass resolve paths) #2747), but it's a WiP.
  • There's been some talk of some way of inlining a few styles directly in index.html, but there isn't any issue or specific functionality for it right now. You can still directly write it in index.html mind you.
  • Sourcemaps are one of the things that slow down webpack rebuilds, yes. We might add an option to disable it though.

We've already merged some changes that dramatically affect build times and for the foreseeable future the plan is to make our Webpack-based builds as fast as possible.

Cheers for taking the time to give such detailed feedback, and if you want to share your results with more people I'd really advise posting it in #1980 so that everyone in the rebuild speed discussion gets it.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants