Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

esbuild: new experimental option for web builds #24487

Merged
merged 7 commits into from
Sep 1, 2021
Merged

esbuild: new experimental option for web builds #24487

merged 7 commits into from
Sep 1, 2021

Conversation

sqs
Copy link
Member

@sqs sqs commented Aug 31, 2021

esbuild is an alternative to Webpack for building client/web (the web app). Its usage on our codebase is EXPERIMENTAL and optional.

To use esbuild instead of Webpack, set the env var DEV_WEB_BUILDER=esbuild:

DEV_WEB_BUILDER=esbuild enterprise/dev/start.sh

Comparison vs. Webpack:

  • esbuild: faster initial build (esbuild ~3s vs. Webpack ~53s)
  • esbuild: faster recompilation (esbuild ~900ms vs. Webpack ~5000ms)
  • esbuild: smaller total asset size in dev (Chrome devtools network resources size for /search: esbuild ~24.1MB vs. Webpack ~64.1MB)
  • esbuild: faster DOMContentLoaded (on /search: esbuild ~1.2s vs. Webpack ~2.3s)
  • Webpack: fast refresh (not supported/implemented yet in esbuild, so you need to manually reload the page after each change)

Notes:

  • It's probably possible to configure Webpack to be faster and produce smaller dev bundles, so consider these comparisons as reflecting the current state, not the hypothetical ideal state after more optimization.
  • Webpack is still used for all other web builds (including storybooks and the browser extension).
  • esbuild is not configured to make a production build. Just use it for local dev for now.

Questions or problems with esbuild? Ask in #frontend-platform and mention @sqs (who is responsible for this esbuild experiment).

@sqs sqs added the frontend-platform Issues related to our frontend platform, owned collectively by our frontend crew. label Aug 31, 2021
@sqs sqs requested a review from valerybugakov August 31, 2021 23:54
@sourcegraph-bot
Copy link
Contributor

sourcegraph-bot commented Aug 31, 2021

Notifying subscribers in CODENOTIFY files for diff bb633afbddc1029c13f834f954ee92c9b617b8f3...e1c7bbc2c2441ae86f925ddbce5eaccb62111c2a.

Notify File(s)
@christinaforney doc/dev/background-information/web/build.md

@sqs
Copy link
Member Author

sqs commented Sep 1, 2021

@valerybugakov This is almost all new/separate code, not code that touches our current Webpack build. The parts that touch our current Webpack build are:

  • Factoring out options for the monaco-editor Webpack plugin
  • Gulp commands (switching based on the value of DEV_WEB_BUILDER)
  • app.html tags for <script> and <link rel="stylesheet">

I tested this branch and confirmed all of the following build variants work:

  • with Webpack in dev mode (using the Webpack dev server)
  • with Webpack in a production build
  • with esbuild in dev mode

Copy link
Member

@valerybugakov valerybugakov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for bringing the esbuild experiment to life! The speed gains are impressive. It's always good to have an alternative, especially isolated as good as esbuild development server. 🎉

I left some comments mostly on consistency and planned extraction of the development server logic into a separate workspace. The only blocking issue I noticed during local testing is related to CSS recompilation on file change: some CSS changes are not picked — the cached stylesheet is served instead. See the comment below in the stylePlugin.ts diff.

A couple of less important issues:

  1. It seems that autoprefixer is not applied to some stylesheets:

ESBuild output:

Screenshot 2021-09-01 at 10 10 00

Webpack output:

Screenshot 2021-09-01 at 13 31 23

This issue causes some visual bugs:

Screenshot 2021-09-01 at 10 10 12

  1. Clicking Find references on the HoverOverlay results in an uncaught exception:

Screenshot 2021-09-01 at 13 29 03

Looking forward to getting this merged and trying it for day-to-day development!

Comparison vs. Webpack:

- esbuild: faster initial build (esbuild ~3s vs. Webpack ~53s)
- esbuild: faster recompilation (esbuild ~900ms vs. Webpack ~5000ms)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to double-check: does it take ~5s to recompile Typescript change with Webpack for you locally?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Is it faster for you?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, recompilation is around 2s on the first file change. It goes down to 1s if I make consequent changes to the same file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. For example, if I add an x literal text to the JSX in UserProfileFormFields, it takes ~5s each time to recompile. This is on a big Linux workstation. Maybe I've just been experiencing slower recompiles than everyone else all along, thus my particular desire for esbuild?


- esbuild: faster initial build (esbuild ~3s vs. Webpack ~53s)
- esbuild: faster recompilation (esbuild ~900ms vs. Webpack ~5000ms)
- esbuild: smaller total asset size in dev (Chrome devtools network resources size for `/search`: esbuild ~24.1MB vs. Webpack ~64.1MB)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ESM 💪

@valerybugakov valerybugakov added dx Issues and PRs related to developer experience concerns dx-announce Tag PRs with this label to include it in the monthly DX email update web server labels Sep 1, 2021
@sourcegraph-bot sourcegraph-bot mentioned this pull request Sep 1, 2021
28 tasks
Copy link
Member

@eseliger eseliger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 🚀 Love the performance. Thank you for investing so much time here!

Tested it briefly locally: Overall it works great. Some little things I found:

  • yaml syntax highlighting in monaco is broken (json works)
  • The icon issue that Valery already posted about
  • For some reason image assets have a very high TTFB for me, around 1s.
  • Something around styles must be off, the nav bar isn't responsive anymore

As a side-note, I think we should be cautious as long as we ship webpack bundles to not have a too high adoption of esbuild in our dev team, so we still catch things that are broken/different in the webpack version. Also, as long as this isn't super stable, we should also encourage people to try webpack locally before filing a bug they find in their dev env.

@sqs sqs mentioned this pull request Sep 1, 2021
3 tasks
@sqs
Copy link
Member Author

sqs commented Sep 1, 2021

@eseliger:

Thanks for checking it out!

Overall it works great. Some little things I found:

yaml syntax highlighting in monaco is broken (json works)

Hmm, I fixed it by adding yaml as a language in the monaco-editor webpack plugin settings (which are shared with esbuild). It was omitted before. 🤷

The icon issue that Valery already posted about

Added to https://github.com/sourcegraph/sourcegraph/issues/24518

For some reason image assets have a very high TTFB for me, around 1s.

This is "by design" in esbuild's dev server. Instead of watching or polling, it actually executes a complete rebuild for each page load. The way this is implemented is that it caches a rebuild for 250ms, which it assumes is long enough for all assets to load. This usually works, but it doesn't remain cached when navigating to other pages after the initial page load, so you need to wait ~1s for the full rebuild again. I think a different impl would be better for esbuild's dev server, but I understand why it is this way for now (it's simpler and reduces the risk of getting a stale asset).

Something around styles must be off, the nav bar isn't responsive anymore

Hmm, I see it being responsive. Noted at https://github.com/sourcegraph/sourcegraph/issues/24518 and will follow up later.

@sqs
Copy link
Member Author

sqs commented Sep 1, 2021

@valerybugakov Thank you for the review!

It seems that autoprefixer is not applied to some stylesheets:

Fixed (my invocation of postcss(...) was incorrect). Unfortunately, this adds ~500ms to the initial build time (likely autoprefixer and other postcss plugins actually running on the big SCSS file).

sqs added 7 commits September 1, 2021 12:12
[esbuild](https://esbuild.github.io/) is an alternative to Webpack for building `client/web` (the web app). Its usage on our codebase is **EXPERIMENTAL** and optional.

To use esbuild instead of Webpack, set the env var `DEV_WEB_BUILDER=esbuild`:

``` shell
DEV_WEB_BUILDER=esbuild enterprise/dev/start.sh
```

Comparison vs. Webpack:

- esbuild: faster initial build (esbuild ~3s vs. Webpack ~53s)
- esbuild: faster recompilation (esbuild ~900ms vs. Webpack ~5000ms)
- esbuild: smaller total asset size in dev (Chrome devtools network resources size for `/search`: esbuild ~24.1MB vs. Webpack ~64.1MB)
- esbuild: faster DOMContentLoaded (on `/search`: esbuild ~1.2s vs. Webpack ~2.3s)
- Webpack: [fast refresh](https://www.npmjs.com/package/react-refresh) (not supported/implemented yet in esbuild, so you need to manually reload the page after each change)

Notes:

- It's probably possible to configure Webpack to be faster and produce smaller dev bundles, so consider these comparisons as reflecting the current state, not the hypothetical ideal state after more optimization.
- Webpack is still used for all other web builds (including storybooks and the browser extension).
- esbuild is not configured to make a production build. Just use it for local dev for now.

Questions or problems with esbuild? Ask in [#frontend-platform](https://app.slack.com/client/T02FSM7DL/C01LTKUHRL3) and mention `@sqs` (who is responsible for this esbuild experiment).
@sqs
Copy link
Member Author

sqs commented Sep 1, 2021

@valerybugakov:

Clicking Find references on the HoverOverlay results in an uncaught exception

Fixed, thanks! It ended up being a problem whereby we were importing some rxjs/internal/... stuff, which caused a different (and instanceof-incompatible) variant of rxjs to be loaded alongside the usual one. Hacked it with 2 packageResolution entries (eg 'rxjs/internal/OuterSubscriber' -> require.resolve('rxjs/_esm5/internal/OuterSubscriber')) for esbuild. I'm curious as to why this wasn't needed for Webpack and whether it's an esbuild bug or just a Webpack do-what-I-mean feature.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
dx Issues and PRs related to developer experience concerns dx-announce Tag PRs with this label to include it in the monthly DX email update frontend-platform Issues related to our frontend platform, owned collectively by our frontend crew. web server
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants