Kotsu
Kotsu copied to clipboard
Extract parts of Kotsu into external modules
Kotsu definitely becoming bigger and updating it within 3rd-party projects becomes harder.
As a potential solution, we could move into standalone NPM modules pieces, which are less likely to be changed by a user.
Besides, it will resolve an issue with few pieces of Kotsu, which are reusable on its own in other projects, like Stylelint config, tcomb
additional types and clean-workdir
script.
Before moving forward, I must admit that there are two factors, which held me back from such changes:
- It will make Kotsu less boilerplate, meaning, that everything no longer at disposal of the end user. Some code pieces will become not editable, and there is no easy way to make them overridable or extensible without tons of undesired and obscure code.
- In some cases, it makes features of Kotsu less obvious. For instance, it is easier to grasp what Ekzo is by looking into it directly in
source/styles
instead of finding it inpackage.json
. After all, not all devs checkingpackage.json
at all. - It will make maintenance of dependencies harder because will would need to update them in several places instead of just in central Kotsu repository.
- It will complicate development, since now to write or test something we would need to constantly link with NPM local modules to our local copy of Kotsu and maintain development-related dependencies in those modules too.
The last issue is mostly solvable by moving to the concept of monorepository, like babel or create-react-app do, and using Lerna. But while it seems to be the handiest solution, I'm still not sure.
So, here what we can potentially do to reduce distributable Kotsu codebase:
-
.stylelintrc.yml
and it dependencies (Stylelint, Stylelint SCSS, Stylelint standard config) move to@kotsu/stylelint-config
, so that other related modules, like Ekzo, could reuse itThough, I'm not sure that
@kotsu/stylelint-config
is a fitting name. It sounds like it tied to Kotsu, but actually, it's our Sass codestyle. -
tasks
and it dependencies move to@kotsu/tasks
.Tasks should be invoked in Gruntfile by importing
@kotsu/tasks
and runningkotsuTasks(grunt)
That way project can opt to use predefined tasks or not too. Besides, tasks should be importable based on layers (for instance, only
@kotsu/tasks/scripts
for scripts), if a project needs an only small portion of default tasks.The project also will be able to override any task by placing files in
tasks
directory and usinggrunt.merge
orgrunt.config
, coupled withObject.assign
orlodash.merge
(which would be preferable, because it handles deep objects). This can be considered as a benefit since with it it will be much easier to understand how exactly project deviates from original Kotsu config.Some downsides:
- Importing
@kotsu/tasks
will install all dependencies, even if the project doesn't need part of default tasks. - Merging operations could potentially make Grunt tasks startup even slower.
- List of already defined tasks now will be obscure because you no longer can simply check
tasks
directory to see all of them
It also unclear what to do with tasklist in Gruntfile (default, build and serve). We could provide them within
@kotsu/tasks
too, but it means that they won't be effectively extensible.As a workaround, we can add some simple API for inserting custom tasks before or after some tasks, like
tasks.default .runBefore('sass', 'some-custom-task') .runAfter('csso', 'some-other-task')
But I have a feeling that it will enormously complicate tasklist.
Finally, note that some tasks, like
default
andserve
are only partially controlled by Grunt and usually launched by NPM scripts at full (likeserve
also launching in parallel JS watch). It makes providing of such functionality at a 3rd-party module even more challenging task. - Importing
-
modules
and it dependencies should be moved to@kotsu/utils
This is a part of Kotsu, which almost never should be altered by the user unless some very specific behavior needed.
As a downside, we giving less freedom to the user and it compromises the main purpose of Kotsu of being a boilerplate with great defaults.
-
modules/refinements
should be moved totcomb-refinements
ortcomb-xtypes
ortcomb-x
or something like that.That module, which provides additional refinements and irreducibles for
tcomb
turned out to be used in many our side and commercial projects, and it would be better to not tie it exclusively to@kotsu
. -
modules/clear-workdir
could be moved toclean-workdir
(or maybe we need a better name).This script is small but useful in any project, which involves building, so there is no sense to make it exclusive to Kotsu
-
Following modules:
-
modules/grunt
(run Grunt via JavaScript) -
modules/nunjucks-test-utils
(a thin wrapper for assembling rendering for tests) -
modules/validate
(a thin wrapper to make easier validation withtcomb
)
Are actually mostly used for tests, and probably be better to move to
@kotsu/test-utils
Though, they can be left in
@kotsu/utils
. I don't see any harm. -
-
Modules-related
tests/kotsu
(but not Nunjucks-components related ones) would be better to move to@kotsu/utils/tests
We can't move components tests out of user's reach because provided components and their tests are just defaults, the user most likely would change them to fit project visuals.
Such change will also prevent the user from running related to
modules
tests, which is mostly pointless waste of time anyway. -
Ekzo should be moved to dependencies.
I'm not a super fan of such change since it will make obscure where Ekzo styles are coming from (Sass isn't that friendly with NPM), and it will complicate development, but hassle with submodules each time you need to init new project for such trivial thing just does not worth it.
So far I do not see a way to make similar simplification with source/styles
or source/templates
. While we potentially could move few components to the standalone modules, I do not see much benefit in it, while other pieces are too subjective and most likely would be modified by the user.