The thing that has seemed to have the most effect for me (of course, this may not necessarily be effective for everyone) is refactoring or even completely rewriting my side projects after/near finishing them. It's a little bit maddening, since I would rather move forward and build new features or start a new project, but the exercise is really helpful. It forces me to take a step back, look at everything I've done, and figure out where I could have done something better. Then, hopefully at least, when I'm in a similar spot in the future I'll be able to think ahead better. In fact, "thinking ahead" might be the most valuable skill for a programmer to have, and I don't really see how reading code can help with that. All of their design decisions have been made by the time you read the code, and it's really difficult, especially for a junior developer, to actually consider how and why those decisions were made.
There have been times when I've dug into a module when something wasn't behaving properly, and was shocked at how bad the code was. It's not as if I included it intentionally - it's usually a dependency of a dependency of a dependency. All the same, it was garbage that I'd been shipping as part of my application.
Your point still stands, though. Having the code where it's easy to find and read is helpful. And reading bad code can be as helpful as reading good code. Sometimes, the trauma caused by seeing some atrocious code can improve your habits more quickly than reading beautiful code. :)
One of my favorites is Rob Landley's Aboriginal Linux:
http://landley.net/aboriginal/about.html
I highly recommend his blogs if you're interested.
I'm mainly a front-end developer, and the nice thing about the npm/node ecosystem is all of your dependencies are right there in node_modules, so feel free to read them to see how they work, or why something isn't doing what you expect -- you can even add debugger statements or console.logs.
In some ecosystems this is harder because you might have to hunt for the source, or only have headers. For example in ruby, use bundle show my_dependecy to see where the code is stored.