DEV Community

Tarun Pai
Tarun Pai

Posted on • Edited on

Contributing to Open-Source - A beginner's guide

Before we begin: The "beginner" in the title is for open-source newbies. The article assumes some level of front-end knowledge; having said that, I'd encourage you to read-on nonetheless 🙂


What's going to be covered in this article?

This article aims to be a simplistic guide for people who want to get started with open-source contributions; it's to help newbies navigate through issues, the code base, etc.

We're going to,

  • Pick and Fork a repository (repo)
  • Pick an issue to solve
  • Build a fix (and refactor it)
  • Raise a pull request (PR)

Why am I writing this?

When I googled "How to get started with open-source contributions", I didn't find any solid how-to guides. Most articles or tips I could find were centered around making documentation changes for Hactoberfest, while those are great and they give you a good sense of how to get started with Github and PRs, they still did not offer enough of a platform to build on.


I've picked Vue as an example, but you could equate these steps to most open-source repositories.


Step 1 - The Issue

The first thing you'd want to do is go to the Github repo for VueJS, go to the issues tab and filter by label - "good first issue" and look for PRs that don't have the "has PR" label.

Alt Text

Note: These labels are pretty standard but they're not guaranteed to be the same if you're looking at a different project.

In the list of open "good first issues", we're picking the second one titled:

$http.delete shows warning "avoid using JavaScript unary operator as property name"

When you open the issue you'll find the following details,

Version
2.6.11

Reproduction link
https://codepen.io/frOracle/pen/vYOEEVW

Steps to reproduce
use $http.delete in @click

What is expected?
$http.delete is a function, not unary operator

What is actually happening?
a warning "avoid using JavaScript unary operator as property name"

Note: Issue logging is usually driven by a template that's decided by the project authors.

In this case Vue has decided that they want the person logging the issue to

  1. Provide a reproduction link
  2. Provide steps to reproduce

and answer a few questions around the behavior.

If you open the codepen link and open the console you'll see the following error,

"[Vue warn]: Error compiling template:

avoid using JavaScript unary operator as property name: 'delete()' in expression @click.prevent='$http.delete('/rest/close')'

1  |  <div id='app'>
2  |  <a href='#' @click.prevent='$http.delete('/rest/close')'>click</a>
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3  |  </div>

(found in <Root>)"
Enter fullscreen mode Exit fullscreen mode

Let's try to understand what's happening here; based on the issue description, the expectation is that Vue does not throw a warning when $http.delete is used as delete is a valid HTTP verb (others being GET, POST, PUT, PATCH).

Come to think of it, Vue shouldn't throw a warning when any form of .delete is used, either with $http or any other object as delete is a valid property name on objects. You can read more about property name limitations.


Step 2 - The Solution

So before we get to understanding the project structure and where we can make this change; this issue (and not all issues can be solved in this manner) can be solved as a generic JavaScript problem statement.

To solve this issue, we essentially need to check a string and not throw a warning in case delete() (or any other unary operator) was invoked as an object property.

For given string str,
We need to return a truthy value if the str has a . prefixing the delete keyword

The simplest way to solve this for the most basic case would be,

let unaryOp = 'delete';
let str = '.delete';

if (str.charAt[0] === '.' && str.match('delete')) {
  // continue and DO NOT throw a warning
}
Enter fullscreen mode Exit fullscreen mode

Now the above code is in no way ideal for a variety of reasons, some being:

  1. It caters to only the delete operator; we need to also take care of typeof and void for instance.

  2. It assumes the string str would always be of a particular format.

  3. Works only for . as a prefix; the logic is not flexible enough to add another prefix.

We need to write this in a more robust manner to cater to the problems mentioned above - as a rule of thumb (and not just for open-source projects), challenge or question the code you've written, because almost always, there's a better way to write it.

We can use the RegExp and the string match method for this!

Now like all experience developers, I too have the lowest level of proficiency with regular expressions, so I'm going to use one I found online.

let re = new RegExp(`
  \\bdelete\\s*\\([^\\)]*\\)|
  \\btypeof\\s*\\([^\\)]*\\)|
  \\bvoid\\s*\\([^\\)]*\\)
`);

// PS: this is the same regex being used in the Vue repo!

let matched = str.match(re);
let allowedPrefixes = ['.'];

if (matched && allowedPrefixes.includes(str.charAt(matched.index - 1))) {
  // continue and DO NOT throw a warning
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Finding the right file

To simplify testing and debugging, I created a minimal setup - a vue-oss-testing folder which resides in the same directory as the cloned vue repository folder.

Within this folder, we need to setup an example similar to the codepen link in the issue and refer to the local copy of the the Vue dev build.

Directory structure

.
+-- vue 
+-- vue-oss-testing
|   +-- index.html
|   +-- app.js
Enter fullscreen mode Exit fullscreen mode

index.html

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="test">
    <div>
      <button @click="obj.delete()">Click here</button>
    </div>
  </div>
  <script src="../vue/dist/vue.js"></script>
  <script src="app.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

app.js

let app = new Vue({
  data() {
    return {
      obj: {
        delete: function() {
          console.log('Calling delete function');
        }
      }
    }
  }
})

app.$mount('#test') // this is the entry point
Enter fullscreen mode Exit fullscreen mode

The quickest way to find the desired file is to use this complicated series of steps called "Find All" 😁

Just go to VS Code (or whatever editor you prefer) and search for the error,

avoid using JavaScript unary operator as property name

This led me to a file called errorDetector.js which had the following function which seems to be what we need to fix!

Alt Text

Pro tip: You can run your vue-oss-testing project and set a break-point at this line in the dist vue.js file in DevTools and go through the call stack to understand the execution flow right from the first app.$mount() function.

A quick glance at the function gives the notion that it allows for unary operators to be prefixed by $ only, so we need to extend this solution to allow for more than just $.

We could fix making the following changes (similar to what we did earlier),

const allowedPrefixes = ['.', '$']
if (keywordMatch && !allowedPrefixes.includes(stripped.charAt(keywordMatch.index - 1)))
Enter fullscreen mode Exit fullscreen mode

Nothing else changes in the function,

Alt Text

You can now run your code again and observe the console - Vue doesn't throw a warning anymore!


Step 4 - Write a test case

Now again, to find the right spec file, let's use our Cmd/Ctrl + Shift + F superpower! and we'll find this in the template.spec.js file,

Alt Text

Let's add our spec after this,

Alt Text

And that's it!

As the final step in the build/contribution step is to (raise a Pull Request)[https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request].

For this specific issue, there is already a PR in review with a very similar fix!


Recap

  • Go to any open-source repo of your choice
  • Filter through features or issues marked as "good first issue"
  • Clone the code and replicate the issue
  • Add a fix, refactor it to be robust!
  • Raise a PR and wait for review comments

Next Steps

Although I've covered a front-end repository here, I hope I was able to keep the steps generic enough for you to apply them to a language of your choice.

Here's a list of all open issues - labelled "good first issue" or "Hacktoberfest" - across all languages, so you can filter!


What more? ... Participate!

Another way to be involved is to participate in the community channels, interact with developers - there are a lot of really good people out there and there's a lot to learn!

Don't be afraid to ask questions, there's no such thing as a stupid question.

Link to the VueJS discord channel - https://chat.vuejs.org/


And finally, I would love to hear your thoughts on this article. ✌
PS: Shout out to all the light-theme coders!

Top comments (1)

Collapse
 
p_santosh_ profile image
P Santosh Kumar

Crisp and clear article, One should definitely follow the steps.