Skip to content

Editor: Add hover tooltips, intelligent completions, auto formatting, diagnostics #4720

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

Open
wants to merge 71 commits into
base: main
Choose a base branch
from

Conversation

justjake
Copy link

@justjake justjake commented Jun 2, 2022

This PR adds the following features based on tsserver to the Sandpack code editor.

  • Hover tooltips. These are styled similar to VS Code, and follow the Sandpack editor's syntax theme.

image

  • Format the current file: cmd-s, Shift-Alt-f
  • Tab completion, including auto-imports. For example, typing useSta<tab> should import useState and insert the rest of the word.
  • Diagnostics such as type errors as well as warnings like "unused variable".
diagnostic.autofix.mp4

This work is based on my improvements to @danilowoz's https://github.com/danilowoz/sandpack-tsserver

Implementation notes

We run tsserver in a Web Worker to avoid blocking the UI thread when asking for completions, etc. On every editor change, we send the new file state to the tsserver worker, and then ask for completions & linting at a throttled rate. Calls between the worker thread and UI thread are type-safe at the expense of some tricky types in ChannelBridge.

The type data used by tsserver is automatically downloaded from a Sandpack CDN, and are cached by the UI thread in localStorage. Dependencies in the web worker are loaded using importScripts from unpkg.com instead of bundled by Next, although I'm not sure this is the best call.

The codemirror plugin code that runs on the UI thread is factored into sub-extensions, so it should be able to disable unwanted features easily.

Mechanics TODOs

  • 🐛 Currently completion is cleared whenever Sandpack reloads to show a build error. This feels very buggy and annoying. I attempted to fix this with React.memo, but that didn't help after I rebased. ¯\_(ツ)_/¯ need to figure this out.
    • Appears to be a Sandpack issue with showInlineErrors, see comment below.
  • Test production build. Check for code size regressions, etc.
  • Evaluate normal dependency imports instead of importScript(...unpkg...)
    • This seems fine!
  • Evaluate sharing a single worker thread between all editors, which could reduce resource use.
    • This is complicated, but could work by creating a new TSServerWorker instance per editor and connecting the editor to a specific instance using the MessageChannel API. Each editor would get a reference to the global worker (react context?), create a channel, and then call globalWorker.makeNewEditor(channel). Could do as a follow-up or if maintainers feel strongly about it.
    • Make sure we actually need a worker??
      • Yep, it's janky without a worker.
  • Figure out how to draw tooltips over the sandbox iframe.
  • 🚮 Remove debugging statements and debug NPM dependency. Currently this branch spews colorful "jake.tl" messages into the console. (I will do this after all other tasks because the debugging is very helpful)
  • Evaluate pre-packaging common type definitions to avoid dynamic resolution from 3rd party CDN. Like, we know we want @types/react@18.X.X. We should resolve the file at or before build time instead of doing it once per editor on app boot.
  • Fix ts-libs cache: sore back the cache from ts-libs into localStorage.

UX/Policy TODOs

  • Tooltips, but ideally it would just be a sentence
    • A link to the beta docs, overriding the existing React typings that use the production docs.
  • Autocomplete shouldn't include a myriad of global browser APIs. They're not useful in 99.9% cases here.
  • tune linting
    • Import/export linting
    • Remove "unused variable" check.
    • Remove most type errors because most docs don't typecheck
  • Automatic formatting, but not on "save". It's not obvious "save" even works here. Maybe on Enter? It should preserve the cursor position.

@justjake
Copy link
Author

justjake commented Jun 2, 2022

@danilowoz showInlineErrors={true} causes autocompletion to dismiss when the line first detects an error. I haven't dug into why yet.

With showInlineErrors:

showInlineErrors.autocomplete.conflict.mp4

Removing that prop resolves the issue.

@harish-sethuraman
Copy link
Collaborator

Hey Great work! Would you like to fix the TS errors? So that the previews are built?

@justjake
Copy link
Author

justjake commented Jun 2, 2022

@harish-sethuraman yep.... been dealing with plane wifi preventing me from pushing 😱 turns out https git push works though.

@github-actions
Copy link

github-actions bot commented Jun 2, 2022

Size Changes

📦 Next.js Bundle Analysis

This analysis was generated by the next.js bundle analysis action 🤖

⚠️ Global Bundle Size Increased

Page Size (compressed)
global 105.5 KB (🔴 +20.84 KB)
Details

The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.

Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis

If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!

One Hundred Eighty-nine Pages Changed Size

The following pages changed size from the code in this PR compared to its base branch:

Page Size (compressed) First Load
/ 47.99 KB (🟡 +28 B) 153.5 KB
/404 47.09 KB (🟡 +28 B) 152.6 KB
/apis 47.88 KB (🟡 +28 B) 153.38 KB
/apis/createcontext 49.63 KB (🟡 +28 B) 155.13 KB
/apis/reactdom 47.82 KB (🟡 +28 B) 153.32 KB
/apis/render 49.86 KB (🟡 +28 B) 155.36 KB
/apis/usecontext 55.58 KB (🟡 +28 B) 161.09 KB
/apis/usereducer 55.22 KB (🟡 +28 B) 160.72 KB
/apis/useref 52.91 KB (🟡 +28 B) 158.42 KB
/apis/usestate 58.86 KB (🟡 +35 B) 164.37 KB
/blog/2013/06/02/jsfiddle-integration 57.9 KB (🟡 +28 B) 163.41 KB
/blog/2013/06/05/why-react 59.63 KB (🟡 +28 B) 165.14 KB
/blog/2013/06/12/community-roundup 59.33 KB (🟡 +28 B) 164.84 KB
/blog/2013/06/19/community-roundup-2 60 KB (🟡 +28 B) 165.5 KB
/blog/2013/06/21/react-v0-3-3 58.05 KB (🟡 +28 B) 163.55 KB
/blog/2013/06/27/community-roundup-3 60.37 KB (🟡 +28 B) 165.87 KB
/blog/2013/07/02/react-v0-4-autobind-by-default 58.67 KB (🟡 +28 B) 164.17 KB
/blog/2013/07/03/community-roundup-4 59.74 KB (🟡 +28 B) 165.24 KB
/blog/2013/07/11/react-v0-4-prop-validation-and-default-values 58.54 KB (🟡 +28 B) 164.04 KB
/blog/2013/07/17/react-v0-4-0 59.25 KB (🟡 +28 B) 164.76 KB
/blog/2013/07/23/community-roundup-5 60.13 KB (🟡 +28 B) 165.63 KB
/blog/2013/07/26/react-v0-4-1 58.02 KB (🟡 +28 B) 163.52 KB
/blog/2013/07/30/use-react-and-jsx-in-ruby-on-rails 58.62 KB (🟡 +28 B) 164.12 KB
/blog/2013/08/05/community-roundup-6 59.43 KB (🟡 +28 B) 164.93 KB
/blog/2013/08/19/use-react-and-jsx-in-python-applications 58.63 KB (🟡 +28 B) 164.14 KB
/blog/2013/08/26/community-roundup-7 59.59 KB (🟡 +28 B) 165.1 KB
/blog/2013/09/24/community-roundup-8 61.03 KB (🟡 +28 B) 166.53 KB
/blog/2013/10/03/community-roundup-9 59.96 KB (🟡 +28 B) 165.46 KB
/blog/2013/10/16/react-v0.5.0 59.65 KB (🟡 +28 B) 165.15 KB
/blog/2013/10/29/react-v0-5-1 58 KB (🟡 +28 B) 163.51 KB
/blog/2013/11/06/community-roundup-10 61.62 KB (🟡 +28 B) 167.13 KB
/blog/2013/11/18/community-roundup-11 60.7 KB (🟡 +28 B) 166.21 KB
/blog/2013/12/18/react-v0.5.2-v0.4.2 58.48 KB (🟡 +28 B) 163.98 KB
/blog/2013/12/19/react-v0.8.0 58.9 KB (🟡 +28 B) 164.4 KB
/blog/2013/12/23/community-roundup-12 60.36 KB (🟡 +28 B) 165.86 KB
/blog/2013/12/30/community-roundup-13 60.14 KB (🟡 +28 B) 165.64 KB
/blog/2014/01/02/react-chrome-developer-tools 58.4 KB (🟡 +28 B) 163.9 KB
/blog/2014/01/06/community-roundup-14 59.73 KB (🟡 +28 B) 165.24 KB
/blog/2014/02/05/community-roundup-15 60.95 KB (🟡 +28 B) 166.46 KB
/blog/2014/02/15/community-roundup-16 60.66 KB (🟡 +28 B) 166.16 KB
/blog/2014/02/16/react-v0.9-rc1 61.07 KB (🟡 +28 B) 166.57 KB
/blog/2014/02/20/react-v0.9 61.51 KB (🟡 +28 B) 167.02 KB
/blog/2014/02/24/community-roundup-17 60.38 KB (🟡 +28 B) 165.88 KB
/blog/2014/03/14/community-roundup-18 61.34 KB (🟡 +28 B) 166.85 KB
/blog/2014/03/19/react-v0.10-rc1 59.65 KB (🟡 +28 B) 165.16 KB
/blog/2014/03/21/react-v0.10 59.67 KB (🟡 +28 B) 165.18 KB
/blog/2014/03/28/the-road-to-1.0 59.79 KB (🟡 +28 B) 165.29 KB
/blog/2014/04/04/reactnet 58.43 KB (🟡 +28 B) 163.93 KB
/blog/2014/05/06/flux 58.55 KB (🟡 +28 B) 164.06 KB
/blog/2014/05/29/one-year-of-open-source-react 58.78 KB (🟡 +28 B) 164.28 KB
/blog/2014/06/27/community-roundup-19 60.32 KB (🟡 +28 B) 165.83 KB
/blog/2014/07/13/react-v0.11-rc1 60.71 KB (🟡 +28 B) 166.21 KB
/blog/2014/07/17/react-v0.11 61.96 KB (🟡 +28 B) 167.46 KB
/blog/2014/07/25/react-v0.11.1 58.91 KB (🟡 +28 B) 164.41 KB
/blog/2014/07/28/community-roundup-20 60.46 KB (🟡 +28 B) 165.97 KB
/blog/2014/07/30/flux-actions-and-the-dispatcher 60.1 KB (🟡 +28 B) 165.6 KB
/blog/2014/08/03/community-roundup-21 60.13 KB (🟡 +28 B) 165.64 KB
/blog/2014/09/03/introducing-the-jsx-specification 58.14 KB (🟡 +28 B) 163.64 KB
/blog/2014/09/12/community-round-up-22 60.61 KB (🟡 +28 B) 166.12 KB
/blog/2014/09/16/react-v0.11.2 58.91 KB (🟡 +28 B) 164.41 KB
/blog/2014/09/24/testing-flux-applications 62.09 KB (🟡 +28 B) 167.59 KB
/blog/2014/10/14/introducing-react-elements 61.04 KB (🟡 +28 B) 166.55 KB
/blog/2014/10/16/react-v0.12-rc1 61.01 KB (🟡 +28 B) 166.51 KB
/blog/2014/10/17/community-roundup-23 61.58 KB (🟡 +28 B) 167.08 KB
/blog/2014/10/27/react-js-conf 58.18 KB (🟡 +28 B) 163.69 KB
/blog/2014/10/28/react-v0.12 60.95 KB (🟡 +28 B) 166.45 KB
/blog/2014/11/24/react-js-conf-updates 58.57 KB (🟡 +28 B) 164.07 KB
/blog/2014/11/25/community-roundup-24 61.81 KB (🟡 +28 B) 167.31 KB
/blog/2014/12/18/react-v0.12.2 58.6 KB (🟡 +28 B) 164.1 KB
/blog/2014/12/19/react-js-conf-diversity-scholarship 58.99 KB (🟡 +28 B) 164.5 KB
/blog/2015/01/27/react-v0.13.0-beta-1 59.96 KB (🟡 +28 B) 165.46 KB
/blog/2015/02/18/react-conf-roundup-2015 61.94 KB (🟡 +28 B) 167.45 KB
/blog/2015/02/20/introducing-relay-and-graphql 61.1 KB (🟡 +28 B) 166.6 KB
/blog/2015/02/24/react-v0.13-rc1 60 KB (🟡 +28 B) 165.5 KB
/blog/2015/02/24/streamlining-react-elements 62.55 KB (🟡 +28 B) 168.05 KB
/blog/2015/03/03/react-v0.13-rc2 59.33 KB (🟡 +28 B) 164.84 KB
/blog/2015/03/04/community-roundup-25 60.29 KB (🟡 +28 B) 165.8 KB
/blog/2015/03/10/react-v0.13 60.61 KB (🟡 +28 B) 166.11 KB
/blog/2015/03/16/react-v0.13.1 58.43 KB (🟡 +28 B) 163.94 KB
/blog/2015/03/19/building-the-facebook-news-feed-with-relay 61.19 KB (🟡 +28 B) 166.69 KB
/blog/2015/03/26/introducing-react-native 58.33 KB (🟡 +28 B) 163.83 KB
/blog/2015/03/30/community-roundup-26 60.26 KB (🟡 +28 B) 165.76 KB
/blog/2015/04/17/react-native-v0.4 59.17 KB (🟡 +28 B) 164.68 KB
/blog/2015/04/18/react-v0.13.2 58.51 KB (🟡 +28 B) 164.01 KB
/blog/2015/05/01/graphql-introduction 63 KB (🟡 +28 B) 168.5 KB
/blog/2015/05/08/react-v0.13.3 58.4 KB (🟡 +28 B) 163.9 KB
/blog/2015/05/22/react-native-release-process 58.55 KB (🟡 +28 B) 164.05 KB
/blog/2015/06/12/deprecating-jstransform-and-react-tools 59 KB (🟡 +28 B) 164.5 KB
/blog/2015/07/03/react-v0.14-beta-1 60.51 KB (🟡 +28 B) 166.01 KB
/blog/2015/08/03/new-react-devtools-beta 59.11 KB (🟡 +28 B) 164.62 KB
/blog/2015/08/11/relay-technical-preview 59.18 KB (🟡 +28 B) 164.68 KB
/blog/2015/08/13/reacteurope-roundup 60.76 KB (🟡 +28 B) 166.27 KB
/blog/2015/09/02/new-react-developer-tools 58.53 KB (🟡 +28 B) 164.03 KB
/blog/2015/09/10/react-v0.14-rc1 64.22 KB (🟡 +28 B) 169.72 KB
/blog/2015/09/14/community-roundup-27 60.69 KB (🟡 +28 B) 166.19 KB
/blog/2015/10/01/react-render-and-top-level-api 59.66 KB (🟡 +28 B) 165.17 KB
/blog/2015/10/07/react-v0.14 64.7 KB (🟡 +28 B) 170.2 KB
/blog/2015/10/19/reactiflux-is-moving-to-discord 60.41 KB (🟡 +28 B) 165.92 KB
/blog/2015/10/28/react-v0.14.1 58.42 KB (🟡 +28 B) 163.93 KB
/blog/2015/11/02/react-v0.14.2 58.45 KB (🟡 +28 B) 163.96 KB
/blog/2015/11/18/react-v0.14.3 58.57 KB (🟡 +28 B) 164.08 KB
/blog/2015/12/04/react-js-conf-2016-diversity-scholarship 59.45 KB (🟡 +28 B) 164.95 KB
/blog/2015/12/16/ismounted-antipattern 59.05 KB (🟡 +28 B) 164.55 KB
/blog/2015/12/18/react-components-elements-and-instances 62.97 KB (🟡 +28 B) 168.47 KB
/blog/2015/12/29/react-v0.14.4 58.24 KB (🟡 +28 B) 163.75 KB
/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A 59.26 KB (🟡 +28 B) 164.76 KB
/blog/2016/01/12/discontinuing-ie8-support 58.07 KB (🟡 +28 B) 163.58 KB
/blog/2016/02/19/new-versioning-scheme 59.45 KB (🟡 +28 B) 164.95 KB
/blog/2016/03/07/react-v15-rc1 62.2 KB (🟡 +28 B) 167.71 KB
/blog/2016/03/16/react-v15-rc2 59.07 KB (🟡 +28 B) 164.57 KB
/blog/2016/03/29/react-v0.14.8 58.2 KB (🟡 +28 B) 163.71 KB
/blog/2016/04/07/react-v15 66.39 KB (🟡 +28 B) 171.89 KB
/blog/2016/04/08/react-v15.0.1 58.96 KB (🟡 +28 B) 164.46 KB
/blog/2016/07/11/introducing-reacts-error-code-system 58.67 KB (🟡 +28 B) 164.17 KB
/blog/2016/07/13/mixins-considered-harmful 66.82 KB (🟡 +28 B) 172.32 KB
/blog/2016/07/22/create-apps-with-no-configuration 62.15 KB (🟡 +28 B) 167.65 KB
/blog/2016/08/05/relay-state-of-the-state 62.19 KB (🟡 +28 B) 167.69 KB
/blog/2016/09/28/our-first-50000-stars 63.64 KB (🟡 +28 B) 169.14 KB
/blog/2016/11/16/react-v15.4.0 61.59 KB (🟡 +28 B) 167.09 KB
/blog/2017/04/07/react-v15.5.0 62.15 KB (🟡 +28 B) 167.66 KB
/blog/2017/05/18/whats-new-in-create-react-app 61.55 KB (🟡 +28 B) 167.05 KB
/blog/2017/06/13/react-v15.6.0 60.17 KB (🟡 +28 B) 165.68 KB
/blog/2017/07/26/error-handling-in-react-16 60.52 KB (🟡 +28 B) 166.03 KB
/blog/2017/09/08/dom-attributes-in-react-16 60.95 KB (🟡 +28 B) 166.46 KB
/blog/2017/09/25/react-v15.6.2 59.28 KB (🟡 +28 B) 164.79 KB
/blog/2017/09/26/react-v16.0 64.42 KB (🟡 +28 B) 169.92 KB
/blog/2017/11/28/react-v16.2.0-fragment-support 62.35 KB (🟡 +28 B) 167.85 KB
/blog/2017/12/07/introducing-the-react-rfc-process 58.87 KB (🟡 +28 B) 164.37 KB
/blog/2017/12/15/improving-the-repository-infrastructure 74.66 KB (🟡 +28 B) 180.16 KB
/blog/2018/03/01/sneak-peek-beyond-react-16 58.83 KB (🟡 +28 B) 164.33 KB
/blog/2018/03/27/update-on-async-rendering 64.07 KB (🟡 +28 B) 169.57 KB
/blog/2018/03/29/react-v-16-3 60.89 KB (🟡 +28 B) 166.39 KB
/blog/2018/05/23/react-v-16-4 61.03 KB (🟡 +28 B) 166.53 KB
/blog/2018/06/07/you-probably-dont-need-derived-state 64.69 KB (🟡 +28 B) 170.19 KB
/blog/2018/08/01/react-v-16-4-2 59.68 KB (🟡 +28 B) 165.18 KB
/blog/2018/09/10/introducing-the-react-profiler 61.29 KB (🟡 +28 B) 166.79 KB
/blog/2018/10/01/create-react-app-v2 61.76 KB (🟡 +28 B) 167.27 KB
/blog/2018/10/23/react-v-16-6 60.96 KB (🟡 +28 B) 166.47 KB
/blog/2018/11/13/react-conf-recap 58.68 KB (🟡 +28 B) 164.18 KB
/blog/2018/11/27/react-16-roadmap 64.87 KB (🟡 +28 B) 170.37 KB
/blog/2018/12/19/react-v-16-7 59.8 KB (🟡 +28 B) 165.3 KB
/blog/2019/02/06/react-v16.8.0 62.07 KB (🟡 +28 B) 167.57 KB
/blog/2019/02/23/is-react-translated-yet 61.63 KB (🟡 +28 B) 167.13 KB
/blog/2019/08/08/react-v16.9.0 64.56 KB (🟡 +28 B) 170.06 KB
/blog/2019/08/15/new-react-devtools 59.17 KB (🟡 +28 B) 164.67 KB
/blog/2019/10/22/react-release-channels 60.99 KB (🟡 +28 B) 166.49 KB
/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense 65.68 KB (🟡 +28 B) 171.19 KB
/blog/2020/02/26/react-v16.13.0 61.91 KB (🟡 +28 B) 167.41 KB
/blog/2020/08/10/react-v17-rc 68.19 KB (🟡 +28 B) 173.69 KB
/community 47.69 KB (🟡 +28 B) 153.19 KB
/community/acknowledgements 48.87 KB (🟡 +28 B) 154.38 KB
/community/meet-the-team 49.57 KB (🟡 +28 B) 155.08 KB
/learn 52.65 KB (🟡 +28 B) 158.15 KB
/learn/add-react-to-a-website 52.76 KB (🟡 +28 B) 158.27 KB
/learn/adding-interactivity 54.33 KB (🟡 +28 B) 159.84 KB
/learn/choosing-the-state-structure 60.05 KB (🟡 +28 B) 165.56 KB
/learn/conditional-rendering 52.28 KB (🟡 +28 B) 157.79 KB
/learn/describing-the-ui 51.5 KB (🟡 +28 B) 157 KB
/learn/editor-setup 48.96 KB (🟡 +28 B) 154.47 KB
/learn/escape-hatches 47.01 KB (🟡 +28 B) 152.52 KB
/learn/extracting-state-logic-into-a-reducer 57.69 KB (🟡 +28 B) 163.19 KB
/learn/importing-and-exporting-components 50.68 KB (🟡 +28 B) 156.19 KB
/learn/installation 48.29 KB (🟡 +28 B) 153.79 KB
/learn/javascript-in-jsx-with-curly-braces 50.76 KB (🟡 +28 B) 156.26 KB
/learn/keeping-components-pure 54.89 KB (🟡 +28 B) 160.39 KB
/learn/managing-state 53.61 KB (🟡 +28 B) 159.11 KB
/learn/manipulating-the-dom-with-refs 55.86 KB (🟡 +28 B) 161.36 KB
/learn/passing-data-deeply-with-context 55.41 KB (🟡 +28 B) 160.92 KB
/learn/passing-props-to-a-component 54.46 KB (🟡 +28 B) 159.96 KB
/learn/preserving-and-resetting-state 58.43 KB (🟡 +28 B) 163.93 KB
/learn/queueing-a-series-of-state-updates 52.25 KB (🟡 +28 B) 157.76 KB
/learn/react-developer-tools 48.25 KB (🟡 +28 B) 153.75 KB
/learn/reacting-to-input-with-state 56.87 KB (🟡 +28 B) 162.37 KB
/learn/referencing-values-with-refs 53.77 KB (🟡 +28 B) 159.28 KB
/learn/render-and-commit 50.75 KB (🟡 +28 B) 156.26 KB
/learn/rendering-lists 54.84 KB (🟡 +28 B) 160.35 KB
/learn/responding-to-events 53.78 KB (🟡 +28 B) 159.28 KB
/learn/scaling-up-with-reducer-and-context 51.82 KB (🟡 +28 B) 157.33 KB
/learn/sharing-state-between-components 52.9 KB (🟡 +28 B) 158.41 KB
/learn/start-a-new-react-project 49.32 KB (🟡 +28 B) 154.83 KB
/learn/state-a-components-memory 57.98 KB (🟡 +28 B) 163.48 KB
/learn/state-as-a-snapshot 51.56 KB (🟡 +28 B) 157.06 KB
/learn/synchronizing-with-effects 64.63 KB (🟡 +28 B) 170.13 KB
/learn/thinking-in-react 53.62 KB (🟡 +28 B) 159.12 KB
/learn/updating-arrays-in-state 55.85 KB (🟡 +28 B) 161.36 KB
/learn/updating-objects-in-state 55.58 KB (🟡 +28 B) 161.09 KB
/learn/writing-markup-with-jsx 51 KB (🟡 +28 B) 156.51 KB
/learn/you-might-not-need-an-effect 62.68 KB (🟡 +28 B) 168.18 KB
/learn/your-first-component 51.59 KB (🟡 +28 B) 157.09 KB
Details

Only the gzipped size is provided here based on an expert tip.

First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.

Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis

Next to the size is how much the size has increased or decreased compared with the base branch of this PR. If this percentage has increased by 10% or more, there will be a red status indicator applied, indicating that special attention should be given to this.

@justjake
Copy link
Author

justjake commented Jun 7, 2022

Typescript environments are now created on first interaction. There's an initial cost of ~60MB heap to boot the tsserver worker and create the first environment, and an additional ~30MB cost per additional environment. Numbers from my M1 Mac, Chrome 102.

Environments are dereferenced when their Sandpack editor is scrolled off-screen and returns to the "idle" state. Memory use can peak up to ~300MB, but dereferenced environments are cleaned up, so usage returns to around ~80mb on /learn/describing-the-ui if I scroll around and click on each editor to force Typescript environment (re)creation.

@justjake
Copy link
Author

Hello – I have some free time coming up that I'd like to use finishing this work. @gaearon @harish-sethuraman @danilowoz What are the blockers here that I need to resolve?

@gaearon
Copy link
Member

gaearon commented Jun 23, 2022

Is there an up-to-date summary of the exact features being added? Since we went back and forth a few times. There is a lot of code and I worry about how to balance the complexity being added vs the payoff. The things that seems most useful to me are autoformatting and possibility of doing TypeScript sandboxes (that works, right?) Can you show how it works with TS code?

@justjake
Copy link
Author

justjake commented Jun 24, 2022

@gaearon

JS Features

These apply to all the existing JS code examples:

  • Report syntax errors and import-related errors with red squiggles. Other kinds of errors, especially type errors, are ignored.
  • Intelligent type-ahead completion, including smart imports. Autocomplete doesn't suggest a bunch of random browser globals.
  • Hover tooltips for tokens that have documentation.
  • All tooltips (hover & import) show documentation and links to beta.reactjs.org/apis/name. Tooltips don't show Typescript syntax.
  • Auto-format the file (preserving cursor position) on newline, Cmd-S (muscle memory matches CodeSandbox.com & VS Code), or Shift-Alt-F (matches VS Code)

image

image

image

Optimizations

  • This system uses a single WebWorker, shared via React Context.
  • The worker is lazily instantiated when a user interacts with a Sandpack example for the first time
  • The worker creates new typescript environments for each example, and then dereferences them if the example is scrolled off-screen to conserve memory overall.

In my testing, these changes add ~55mb of Javascript heap once the user interacts with a code editor and while that editor remains on-screen. This brings total heap size from ~70mb to 125mb while editing a sandbox.

Typescript

Write App.tsx examples in Typescript, via ```typescript code fences. This automatically enables the following features:

  • Full type error reporting for Typescript code.
  • Build each .tsx file to JS, and show the JS as a tab.
  • The JS version stays in-sync with the TSX version until the user edits the JS version. Then, it's independent until the user presses "Reset".
  • When the JS version of a file is selected, it's used in the bundle instead of the JS version.
  • When the TSX version of a file is selected, it's used in the bundle instead of the JS version.
edit.in.either.language.mp4

justjake added 6 commits June 24, 2022 07:29
A fenced codeblock with the `tsx` langauge will produce App.tsx,
which is handled similarly to `js` langauge producing App.js.
Like App.js, App.tsx is the fallback active file.

A TODO for future commits is to auto-generate App.js from App.tsx,
and allow the user to pick which one to use by switching tabs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants