rome / tools

Unified developer tools for JavaScript, TypeScript, and the web
https://docs.rome.tools/
MIT License
23.77k stars 663 forks source link

☂️ One config format, in one place #1596

Closed jamiebuilds closed 2 years ago

jamiebuilds commented 3 years ago

I want to address this before we ship the 0.1 release.

One of my bigger regrets on Babel is not sticking to a single universal config format that was always in one place in the file system. It largely grew out of the many different integrations with Gulp, Grunt, Webpack, etc. where people configured Babel with its library API. But today you have:

.babelrc
.babelrc.json
.babelrc.js
.babelrc.cjs
.babelrc.mjs
babel.config.json
babel.config.js
babel.config.cjs
babel.config.mjs

Not to mention the many other places Babel
config can appear in other tools' config files
and random JS files (i.e. webpack.config.js)

I think this is really bad for the community:

I would suggest that we have a single config file rome.??? and it always appear at the "root" of the project (whether that is the git root or some other folder), or some "workspace"-like folders that belongs to a shared root.

I think the best two choices for this config file are either:

I think it would be a big mistake to use a dynamic language like javascript for this format as it complicates caching, removes the point about being copy-pasteable, and makes it impossible to have CLI tools that automate it.

Some quick pros and cons with either syntax:

JSONC:

TOML:

Overall my personal preference is TOML, but I would be happy with either.

jamiebuilds commented 3 years ago

I also should probably explicitly call out that I think it would be better if the rome.toml/json file was always required. It's a very useful flag for tools (like the Rome vscode extension) to detect if a directory is a Rome project.

See "prettier.requireConfig" in the Prettier VSCode extension for example, it makes it so only projects with a .prettierrc file have prettier run on them on file-save.

yassere commented 3 years ago

I think that JSONC is a good choice, and I don't think there are compelling reasons to deviate from a syntax that the community is already familiar with.

I like TOML for simple config, but personally, I think it's easier to quickly understand nested config in a json-like format (especially when you can easily fold/expand sections in your editor).

And ultimately, I hope our cli is powerful enough that most tutorials will be able to say "run these rome config commands" rather than "copy this snippet".

jamiebuilds commented 3 years ago

I think it's easier to quickly understand nested config in a json-like format (especially when you can easily fold/expand sections in your editor).

I actually feel the opposite way. TOML avoids the problems of nesting because using tables you're always not far from context:

[lint]
# ...many lines of code...
# ...many lines of code...
# ...many lines of code...
# ...many lines of code...
# ...many lines of code...
[lint.rules]
# ...many lines of code...
# ...many lines of code...
# ...many lines of code...
# ...many lines of code...
# ...many lines of code...
[lint.rules.a11y]
noAccessKey = true
noAriaUnsupportedElements = false

I don't have to scroll and match indentation/braces to see where I am. Even with braces-folding you still end up with a lots of content to scroll through. You can also text search in your editor "lint.rules.a1" and jump directly to the right section.

And ultimately, I hope our cli is powerful enough that most tutorials will be able to say "run these rome config commands" rather than "copy this snippet".

I think regardless of what our documentation/cli/etc does, users are going to communicate with one another via config. Even though git has a similar CLI for editing config as Rome, there are still thousands of stack overflow answers that paste config into them, and the average Rome config file will probably larger than the average git config file.

milesj commented 3 years ago

How does Rome handle environment specific configs? Like dev/prod/local/etc?

iduuck commented 3 years ago

I think @milesj has a valid point, the CLI at least should include an option to override the path (or at least the filename) of your config. This would make it much easier (also for CI) to match for dev/prod/local/etc. Otherwise, CI needs to create a file out of each context.

jamiebuilds commented 3 years ago

I don't want to go into too much detail in this issue, but at a high level, I don't think that Rome needs/should have environment-specific configuration for a few reasons:

Rome can and should be very flexible, but not at the expense of pushing every decision onto every user. And we'd like to preserve the ability for us to push out situationally-aware improvements to everyone without asking them to opt-in all the time.

jer3m01 commented 3 years ago

I'd go for TOML.

Haven't used it much before but just from these few examples I already understand it. So I don't think that learning it would be a problem. TOML being somewhat capable of being read and reformatted when incorrect is also a plus, ref: https://twitter.com/buildsghost/status/1408492371357028353. Since TOML is flat we could easily allow splitting the config in as many files as wanted and just combine them with minimal boilerplate per file.

Having worked with JSON and JS config files, finding the correct context is a huge hassle. Same for formatting i.e. missing bracket/colon/comma/... I'd prefer some repetition (TOML keys) over indentation hell. For comments you'd have to manually set the file language as most editors will complain.

I think having a single format would be better for everyone, removing the need to know all of them when providing/needing support.

How does Rome handle environment specific configs? Like dev/prod/local/etc?

[...] the CLI at least should include an option to override the path (or at least the filename) of your config.

We could definitely include an option like --config <path> and/or use an env variable.


@jamiebuilds would we only use rome.toml/json and remove the .config folder?

jamiebuilds commented 3 years ago

@jamiebuilds would we only use rome.toml/json and remove the .config folder?

Yeah, I mean... if Rome is successful, then we'll be eliminating the need for a lot of config files.

Example I have a project right now that looks like this: ``` .editorconfig .eslintignore .eslintrc.yml .gitignore .prettierignore .prettierrc.yml .stylelintignore .stylelintrc.yml babel.config.js eslint-local-rules.js karma.conf.ts package-lock.json package.json tsconfig.json webpack.config.js ``` If you were to only use Rome tools, that could look like this: ``` .editorconfig .gitignore package-lock.json package.json rome.toml tsconfig.json ``` Maybe in the future even: ``` .editorconfig .gitignore rome.toml ```

But in the meantime a couple things:

iduuck commented 3 years ago

Ok, understood. But actually I would still give the user the ability to define a custom file. There are multiple use cases where there are other build tools (whose use cases Rome cannot handle), and with it configuration files. When it comes to project structure, I would always prefer having build tool configuration in one folder. So she Config file decision should be available for me. But not mandatory to be set.

ematipico commented 3 years ago

I am happy with either. I personally like TOML syntax and first time I started looking into it, I got the hang of it quite quickly. It has rules, it supports comments out of the box, it's really expressive and "flat" (no nested things).

Comments inside a JSON seems, to me, unnatural.

Regarding the position of the file, having it inside the root folder is a good idea.

@iDuuck The Rome config file accepts a extends where you can point a new file where you can extend other properties. So, you would have something like:

rome.toml
rome-config/
 ---- config.toml

The config files would look like this

# inside rome.toml
root = true
name = "project"
extends = [ "./rome-config/config.toml" ]
# inside config.toml

[lint]
enabled = false

[format]
enabled = true
ematipico commented 3 years ago

I'd say we could move the config file in the root folder, away from .config/ folder with one release.

After that we could use some telemetry to understand which projects prefer to use json and which ones prefer toml. And with another release, we could deprecate one format and offer a "conversion" command that moves the config with the deprecated extension to the new one.

jamiebuilds commented 3 years ago

Spoke more about this as a team:

TmLev commented 2 years ago

Have you considered using plain .js format? This can be much more flexible than other formats.

ematipico commented 2 years ago

Have you considered using plain .js format? This can be much more flexible than other formats.

We did and we want to stay away from that approach for various reasons.

scarsam commented 1 year ago

@ematipico

The Rome config file accepts a extends where you can point a new file where you can extend other properties. So, you would have something like:

Not sure if this is out-of-date but you're saying that Rome allows extends, but I cannot get that working and don't see it anywhere in the documentation. I want to prevent us from having 20+ different configuration files instead of 1 in our org if we should be able to try out Rome.

ematipico commented 1 year ago

@scarsam Since the rewrite to Rust, we haven't been able to port ALL the old features we had. This is one of them, we plan to add it again soon. Unfortunately, I can't give you a timeline. Once there, the documentation will be updated!