I built a vscode javascript repl - Why, how, and what I learned
Achilleas Kiritsakas
Posted on October 29, 2019
Maybe, you have already seen Bret Victor's presentation Inventing on Principle or the Light Table editor In Action video or the time travel in Redux Redux apps by using the Redux DevTools. About all these resources I feel, that we are on the right path that eventually will guide us to integrate all these tools inside our editors and with a single click all the visual or runtime information that we need during the development process to be available besides our code.
The same feeling I had, when I saw the Quokka plugin in action inside the vscode editor, I liked it. The only thing that I didn't like was the information window about a pro version for import support when I was trying to print the values of an imported JavaScript file in a React project. So at this point, I think that a new journey has already started inside my mind. I wanted to create something like that, but mostly I know that I wanted to learn all these things that I needed to know to do it.
Some info
Back in 2013, my choice editor was Sublime text, so in a company's custom SPA framework, we were saving some Html data, in a JavaScript file, that was working like template literals. There was the choice to have this Html data as a single line but it was not so convenient to make edits or to review the changes in git, so we kept these parts of data as multiline strings.
For this reason, I created a sublime plugin that was making the process of copying Html data inside a Javascript file, and formatting it, as javascript multiline string, easier. After that, I built the same plugin for Brackets editor.
Also, in some projects, we needed to debug the Javascript code in SPA that was running as iPad applications through the Adobe Flex. The debugging process was difficult, so I created a custom console logger that could be activated during the development process, and was supporting touch events, previous commands history and autocomplete for Window interface and Dom selectors. A preview of this can be shown on youtube
What I am trying to say with all these, is that I really enjoy to create developer tools and especially whatever has to do with logging or debugging.
Learning process
It was not as simple as I thought at the beginning, to make something similar. Maybe at some steps I spent more time than I needed because I am the type of dev who feels better, when they know how it works the underlying code of a library, maybe at some times I have over-engineered in order to feel safer that later I can add easily a new feature but I am sure that I would not avoid spending time to some key steps during development.
First stop, a GitHub search for something that looks like it and is open-sourced. The only project that I found was the following extension that was only focused on node.js and wasn't supporting imported or required files. I started to play with it, read the VS Code API and to have a better understanding of how a vscode extension is created.
Bundling
Second stop, bundling. I was using Browserify and rollup in the past but at this point, I was using webpack, but I have never checked the internal code of a bundler so I started to study the source code of webpack and plugin development with it. At some point, I realized that with webpack, it would be more difficult for me to work so I checked the source code of the Parcel bundler. I liked the code style, the caching of already generated files and the zero-configuration support feature that Parcel provides. So I studied, studied and studied Parcel's source code :) I wrote a mini bundler based on this to better understand the functionality that it was not clear to me how it works and I decided to use a modified version of Parcel as the layer that will handle bundling.
Node.js api
Next stop, node.js api. These years, I was mostly focused on front-end technologies. However, I had the chance to create some services in node.js and use express.js, koa.js or some other node.js libraries but I didn't have the chance to examine the node.js' api in detail. During this extension development, I had the chance to dive deeper in the api and learn more about things like the communication between parent and child process the new Async Hooks api and the not so new Worker Threads api, the Inspector api the utilities of node.js api, how to run code within V8 Virtual Machine contexts with the VM module and some more. Finally, I would like to share a library that I discover during this step and I love but finally, I didn't use within the extension the vm2 that is a sandbox that can run code that you don't trust, securely.
Babel
Next stop, Babel and babel plugin development. To provide logging, I was sure, that I need to rewrite the code that the user types, especially the console.log() statement. The problem was, that I had never created a babel-plugin, so I started to read about it. Three great resources that helped me are the Babel Plugin Handbook by Jamie Kyle, the @babel/types documentation and the AST explorer web tool by Felix Kling. So now, the Javascript-REPL extension uses the transform-console-plugin to rewrite some of the code that is needed when the users are typing in the vscode editor.
Coverage support
Next stop, code coverage support. I had read an article in the past like this and I had used istanbuljs for code coverage. But how it works? In a few words, Istanbul reads the AST for every file, keeps an object with every expression and statement with their information(line, column) inside your code and adds custom code, besides all these expressions. This custom code is some counters that are increased during the runtime, so in the report, Istanbul knows for example how many times a function has been called based on these counters. If you want to read more about this, check this article. The truth is that if I had not read about the abstract syntax trees or if I had not seen during debugging a babel visitor to visit a path and change a Node's properties during the babel-plugin creation, I would worry much more about this step. I knew that I mostly need the runtime information collection, so after experiments, I used a modified version of Istanbul for code coverage. One other resource that I found very interesting is the c8 module that uses the node's built in feature that is based on v8's engine support for code coverage
Testing
Initially, for testing, I was using the standard environment that the official Yeoman Generator had produced and is described in this article. The standard environment by default uses the Mocha test framework, but I used to have Jest in React projects, so I searched, how I could it. The resources that helped me with this are this article and the repository of vscode-prompt-debug extension. As a result, in order to have e2e testing with Jest, I needed to run Jest programmatically and to create this test environment for Jest.
Build
In order to build and bundle the extension my first thought was to do this with the parcel-bundler but due to lack of a feature that I wanted to ignore certain node_modules or files from the bundle, I tried my second option that is described in the following guide from vscode documentation, that uses webpack as the module bundler. Finally, I used the ncc tool from Zeit that under the hood works with webpack but supports out of the box dynamic requires that I have used inside my source code.
Javascript REPL preview
Javascript REPL is a javascript playground for Visual Studio Code with live feedback(logs or errors) as you type, besides your code, in a log explorer, or an output channel. It supports Javascript, TypeScript, CoffeeScript and it can be used for development in Node.js projects or with front-end frameworks like React, Vue, Angular, Svelte. On wiki pages users can find the available documentation.
- Logs through comments or by using console.log
- Show or copy the value of an expression, without add comments or console.logs
- Logs explorer at the left
- Output window with all the logs
- Live code coverage
- Coverage number of times
- Imported files support
- Easy install for missing modules
- Multi files loggings or errors per project
- async results rendering
- JavaScript, TypeScript and CoffeeScript support
You can find the extension in the marketplace at the following url:
🎉 https://marketplace.visualstudio.com/items?itemName=achil.vscode-javascript-repl
So, if you are using vscode and want to try it, any feedback is appreciated ♡
Posted on October 29, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.