Why and how to build your first Laravel package?
First of all, it's truly educational!
Secondly, it's enjoyable — at least it was for me. I think it comes down to the awareness that I have a contribution, a small brick, in the world of open-source tools. Even if only I end up using the package and others only potentially could, it still feels rewarding for that part of my soul that is a programmer.
(spoiler, the package: https://github.com/Zmyslny/laravel-inline-scripts)
But what should it contain? How to choose what belongs in the package?
You can spend 2 hours thinking about how sophisticated the solution should be, but not write a single line of code. A few days later you'll return to the search for that magical problem to solve, but the first line of code still won't appear. And so it goes, embarrassingly long. That's my expirience.
In the end, I decided to wrap the most trivial part of my website.
The only criterion was that… I would use it and I don't care about other developers' opinions on its usefulness. I know, it might sound a bit controversial. But thanks to that, I'm certain that at least one person in the universe will use this package — me.
I'll emphasize once more that it took me a while to reach these conclusions and start doing meaningful work on the package.
So what did I decide to put in my package?
Color scheme switching between light ☀️ / dark 🌛 / system 🖥️.
Trivial.
But to try something new, I also decided to:
100% PHP code test coverage
100% type coverage
Static analysis with PHPStan at level 10
Refactoring with Rector
Automated formatting of everything that can be formatted.
I wrote a Blade component with embedded JavaScript. A second component with color scheme icons, and done.
And here comes the first interesting thought. 💭
What if I kept the JavaScript in a separate .js file and loaded it from there when inserting into the template? That way I could write tests for the JavaScript itself and tests for its behavior on the website.
First iterative change (before I had published anything)
That's how I created a mechanism that takes paths to JavaScript files, loads them, and then registers them as a Blade directive. That one sentence contains quite a significant number of hours of work spread over several evenings. I also made sure the code was truly SOLID.
BladeInlineScripts::takeFiles(
resource_path('js/your-first-script.js'),
resource_path('js/your-second-script.js'),
...
)->registerAs('myInlineScripts');Classes like: BladeInlineScriptsFactory, BladeInlineScriptsFacade, BladeDirectiveRegistrar, ... were created.
And here comes another thought. 💭
What if I added the ability to transform the JavaScript between loading and inserting it into HTML? For example, by inserting placeholders in the JavaScript. Replacing them with chosen values after being read by PHP, I'd create a mechanism for dynamically passing values from PHP to JavaScript.
Second iterative change (before I had published anything)
Now I added the ability to wrap the loaded code in a PHP class. This makes it possible to, for example, replace a placeholder with any value. I added the RenderableScript contract and two ready implementations: FromFile and FromFileWithPlaceholders. An example of using these two classes can be seen below. Both InitScript and SwitchScript extend FromFileWithPlaceholders.
BladeInlineScripts::take(
new InitScript(),
new SwitchScript('d') // toggle with 'd' key
)->registerAs('colorScheme');
Without boring you with the narrative about subsequent, brilliant ideas… I'll get to the conclusions.
The original GOAL: to wrap the color scheme switching mechanism in a template.
and the RESULT is:
a mechanism for loading JavaScript files with the ability to inject variables from PHP
and ready-to-use examples in the form of color scheme switching scripts.
The important takeaway is that if I hadn't started trivially, I wouldn't have achieved anything — because I wouldn't have started at all.
Finally published: https://github.com/Zmyslny/laravel-inline-scripts