I built a vscode javascript repl - Why, how, and what I learned
Tags: webdev, javascript, vue, react
Published: 2019-10-29 18:37:49

Maybe, you have already seen Bret Victor's presentation [Inventing on Principle](https://vimeo.com/36579366) or the Light Table editor [In Action video](https://www.youtube.com/watch?v=52SVAMM3V78) or the [time travel](https://medium.com/the-web-tub/time-travel-in-react-redux-apps-using-the-redux-devtools-5e94eba5e7c0) in Redux Redux apps by using the [Redux DevTools](https://github.com/reduxjs/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](https://quokkajs.com/) 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/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](https://github.com/axilleasiv/JSMultiline) 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](https://github.com/axilleasiv/brackets-js-multiline) 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

{% youtube 3n0BgtKhBHY %}

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](https://github.com/lostfields/vscode-nodejs-repl) 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](https://code.visualstudio.com/api/references/vscode-api) and to have a better understanding of how a vscode extension is created.

### Bundling

Second stop, bundling. I was using [Browserify](http://browserify.org/) and [rollup](https://rollupjs.org/guide/en/) in the past but at this point, I was using [webpack](https://webpack.js.org/), 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](https://parceljs.org/) 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](https://github.com/axilleasiv/parcel) 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](https://nodejs.org/dist/latest-v13.x/docs/api/child_process.html) between parent and child process the new [Async Hooks api](https://nodejs.org/dist/latest-v13.x/docs/api/async_hooks.html) and the not so new [Worker Threads api](https://nodejs.org/dist/latest-v13.x/docs/api/worker_threads.html), the [Inspector api](https://nodejs.org/dist/latest-v13.x/docs/api/inspector.html) the [utilities](https://nodejs.org/dist/latest-v13.x/docs/api/util.html) of node.js api, how to run code within V8 Virtual Machine contexts with the [VM module](https://nodejs.org/dist/latest-v13.x/docs/api/vm.html) 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](https://github.com/patriksimek/vm2) that is a sandbox that can run code that you don't trust, securely.

### Babel

Next stop, [Babel](https://babeljs.io/) 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](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md) by Jamie Kyle, the [@babel/types](https://babeljs.io/docs/en/babel-types) documentation and the [AST explorer](https://astexplorer.net/) web tool by Felix Kling. So now, the Javascript-REPL extension uses the [transform-console-plugin](https://github.com/axilleasiv/babel-plugin-transform-custom-console) 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](https://www.peterfessel.com/2016/10/how-do-javascript-code-coverage-reports-with-instanbul-work/) and I had used [istanbuljs](https://github.com/istanbuljs/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](https://www.semantics3.com/blog/understanding-code-coverage-1074e8fccce0/). 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](https://github.com/axilleasiv/istanbuljs) of Istanbul for code coverage. One other resource that I found very interesting is the [c8 module](https://github.com/bcoe/c8) that uses the [node's built in](https://nodejs.org/dist/latest-v10.x/docs/api/cli.html#cli_node_v8_coverage_dir) feature that is based on v8's engine support for [code coverage](https://v8.dev/blog/javascript-code-coverage)

### Testing

Initially, for testing, I was using the standard environment that the official [Yeoman Generator](https://github.com/Microsoft/vscode-generator-code) had produced and is described in [this article](https://vscode.rocks/testing/). 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](https://medium.com/@soloydenko/end-to-end-testing-vs-code-extensions-via-jest-828e5edfeb75) and the repository of [vscode-prompt-debug](https://github.com/rozzzly/vscode-prompt-debug/tree/master/test) extension. As a result, in order to have e2e testing with Jest, I needed to run Jest programmatically and to create this [test environment](https://github.com/axilleasiv/jest-environment-vscode) 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](https://code.visualstudio.com/api/working-with-extensions/bundling-extension) from vscode documentation, that uses webpack as the module bundler. Finally, I used the [ncc tool](https://github.com/zeit/ncc) 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](https://github.com/axilleasiv/vscode-javascript-repl-docs/wiki) users can find the available documentation.

{% youtube Ef75DChLMO8 %}

- 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 ♡