It will be most helpful if you're just finishing learning the core language and want to find out what exists in the world of web development. Feel free to contradict and correct me.
1. All Theory And No Practice
Get over with that college student attitude of reading chapter upon chapter of dull text and not writing a single line of code. And by code, I don't mean the example code snippets. Go out there on Github and Reddit and search for beginner problems statements. Creating a simple TODO list or displaying the top posts on Reddit frontpage via their API doesn't require any deep knowledge.
2. Build Tools
I made the mistake of assuming I knew everything about the language once I finished my guidebook. The reality was far from it. Language is just one little part of the puzzle of mastering any programming stack. There are many support tools that I didn't care to explore back then. For example, there's something called as a build tool.
In an organizational setting, you don't start a project by creating an
index.html and then linking it with your
main.js. Instead, you make use of build tools (See Webpack or Grunt) to compile your code into a form understood by new and old browsers alike, bundle all of your code together and make it production ready. A basic understanding of build tools will go a long way and come in handy when making your next hobby project shine.
Modularization, in simple English, means separating parts of your code that work similarly. Just like we sleep in our bedroom, bath in our bathroom and cook food in the kitchen, code the does similar things should be separated into different files and functions/classes.
fetch() API calls in one file, little utility functions/hacks in another, DOM manipulation functions in another and event listeners separately. This is one of the many ways of doing it. See what works best for you. Remember that your frustration level two weeks later while finding a bug in your code is inversely proportional to the number of files and functions you separated your source code in.
The importance of modularization strikes only when you feel the pain in your back scrolling up and down and sideways finding a particular section of a function responsible for something. You'll have to take a leap of faith here to learn this lesson the easy way.
var_names mixed all over the place. This is not limited to just syntax or micro stuff. On a broader level, follow the same style for everything. If you return a Promise from an API service function, then stick to that style. Don't interchangeably return promises and data, for example. And don't mix imperative, object-oriented and functional coding styles randomly. Make conscious calls on what is right for the situation, and document appropriately.
The less you think about the language semantics, the more you can think about the problem you're trying to solve. And consistency will definitely reduce a lot of the unnecessary load of deciphering your own code.
Another task deserted of any love in the realms of software engineering. No one likes to document code, take it from me. But the difference between a rookie and a master is knowing when and why something must be done irrespective of his affection towards the job. Write comments, doc strings. Decorate your projects with nice READMEs and fancy "build passing" and "codecov" badges. No, you're not doing it for others. You're doing for yourself because you know it is right. You want to know your thought process two months later when you read the code to make some changes. It is like an "enable time machine access to this point in time?" button in your code, which you reply with a "deny" if you decide to not document your code.
6. Think, Think, Think And Then Write Code
This is one of my personal favorites. I'll start coding 0.006 seconds (number might be slightly inaccurate) after hearing the problem statement. Don't do this mistake. Don't fall for your heart saying it has understood it all. Your heart is wrong. Think about the problem. Confirm that you have understood the requirements correctly. Formalize the requirements in your mind, or better yet, in a Github issue or something. Come up with a naive approach to do it. See if you can optimize the code, think about space-time tradeoffs, think if you can use something like a hashmap etc. You'll be surprised how many better solutions you'll come up with after thinking about it for 10 minutes as opposed to jumping right into the code.
7. Tracking Your Project's Progress & Version Control
Use git, Github (or any other Git hosting). Use issues to write down what you plan to do for the next iteration. Use PR (pull request) feature to fix that issue. Write down if there were any caveats in the comments below the PR requests. Yes, do it even if you're the only person working on the project. It might seem unnecessary and tedious, but once you get the hang of it, your time will be much better utilized and progress much better tracked.
8. Automate Your Deployment
I remember my workflow before starting work. Keep committing to the master branch and testing things out locally. And when things look decent enough, spin up a digital ocean droplet, clone the repository and start the development server there. That was my 'deployment'. If any changes need to be done, commit to master and push from local. Pull them on the server and restart development server.
Now that I know better, I not only make separate branches for each feature, I set up auto deployment on Heroku on particular branches (mostly master and staging/development). It's a one-click affair (assuming you followed the build tools part) and takes away a lot of hassles (and is free as well). Knowing the right tools can make a huge difference, as you just saw.
9. Unit Tests
If you've ever worked on a non-trivial project (say around a thousand lines of code), you will recognize the tragedy when you modify your code while adding a new feature and accidentally break a lot of the old code which you realize later when things start going south at which point a lot of git-fu is required to get back to a safe point and not lose any newer work. Let me tell you something. It is all avoidable with simple unit and integration tests. Think of tests as employing a bunch of robots to look over your old code and point out when you're about to break your own (or someone else's) code.
It is very hard to convince yourself to write tests even after knowing the pluses, let alone without knowing them. But again, you'll have to take a leap of faith here. Or you can wait until someday while casually refactoring some code you mess something up which you realize only after three days with hours of debugging which could've been avoided by writing a simple test.
10. Use ES6
12. Understand What JS Is And What It Isn't
13. You Probably Don't Need That Framework
Similarly, if you are planning to use ReactJS or Vue just because everyone seems to be talking about it, don't. Go read up their introduction and documentation and judge if your project fits the use case that particular framework is build for and the problem it is trying to solve. For learning purposes, you can consider using the frameworks for trivial apps, but for anything else, make decisions on a strictly use case basis.
14. Learn Basics Of CSS
While the popular opinion still says that CSS is a pain in the back to master, I'd suggest learning almost 60-80% of it with maybe 20% of the efforts. No need to remember which browser supports what niche attribute. Just the important very-handy-in-real-life parts like flexbox, grids, box model, margins, paddings, positioning related, display related, floating related and so on. You will cover a lot with just these, and they come in super handy for personal projects. (Again) trust me.
15. Explore Web Workers/Service Workers
What if I tell you, you can hijack API requests from your webapp and service them without making a roundtrip to the server? You'll say, if the request is serviceable on the frontend itself, why bother making an API call in the first place, and I make a poker face to that. Jokes aside, service workers enable you to handle network connectivity drops and provide a much smoother experience. You can save the data that a client wanted to send the server in the browser while offline and then replay those requests again when network connectivity is recovered.
Web workers allow your code to delegate work to another processing thread. This can be any type of work that you would want to unload off the main thread like heavy calculations etc.
16. Explore Browser-Side Databases
There are wrappers such as PouchDB that can sync with the server side CouchDB and provide nice real-time syncing capabilities. Speaking of real-time, you might also want to check out Firebase by Google. I used to use it in the past and it was very easy to set up and work with.
17. Explore Progressive Web Apps
Now you can make your website work offline too. Ever seen that "Add to homescreen" button on certain websites? When you add those websites to your homescreen, you can then open them like regular Android apps and if they're built that way, even use them offline (further reading: developers.google.com/web/progressive-web-apps).
Thank you for reading.