Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

☂️ One config format, in one place #1596

Closed
jamiebuilds opened this issue Jun 25, 2021 · 16 comments
Closed

☂️ One config format, in one place #1596

jamiebuilds opened this issue Jun 25, 2021 · 16 comments
Labels
umbrella Issue to track a collection of other issues

Comments

@jamiebuilds
Copy link
Contributor

jamiebuilds commented Jun 25, 2021

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:

  • Documentation/Blog posts/Stack overflow/GitHub issues all reference one format or another, forcing user to translate between them.
  • New users to a codebase have to search for Babel configuration that could be anywhere
  • Tools built around Babel need to know how to find all of these different files, and even when they do they aren't reliable.
  • It creates a decision that you need to make when first setting up a project and people don't know the tradeoffs

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.

  • Users can copy and paste config from docs/blogs/stack overflow/github issues without having to translate it between syntaxes.
  • Users always know where to find their Rome config.
  • Tools built around Rome can easily find the config and safely depend on it being there.
  • It removes the need to make a decision on how to configure your project.
  • We can invest a lot of time making the CLI tools for that one config format really good.

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

  • rome.toml
  • rome.json (parsed as JSONC -- the same format tsconfig.json uses)

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:

  • Pro: Most users are already familiar with the syntax.
  • Pro: Its very "What You See Is What You Get".
  • Pro: It avoids the repetition that TOML has.
  • Con: It can get hard to read really quickly.
  • Con: Copy-paste requires context that people don't always include.
  • Con: The comment syntax is often surprising to people.

TOML:

  • Pro: The syntax is very easy to learn, and very intuitive even if you don't know it.
  • Pro: The (automatically merging) [table.with.context] syntax makes copy-and-paste very easy.
  • Pro: It stays very readable even with lots of data in it.
  • Con: There aren't any major JS tools using it right now, so it'd be another thing for people to learn
  • Con: It can be somewhat difficult to predict what the final data looks like when parsed
  • Con: It requires some repetition [lint] [lint.rules] [lint.rules.js]

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

@jamiebuilds jamiebuilds added the umbrella Issue to track a collection of other issues label Jun 25, 2021
@jamiebuilds
Copy link
Contributor Author

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
Copy link
Contributor

yassere commented Jun 25, 2021

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
Copy link
Contributor Author

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
Copy link

milesj commented Jun 25, 2021

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

@iduuck
Copy link

iduuck commented Jun 25, 2021

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
Copy link
Contributor Author

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 should always be fully aware of what environment you're in rome dev rome ci rome build rome test rome check etc. Which means that it can turn things on or off automatically for the task at hand.
  • For building, and this has yet to be designed, Rome can categorize different work/settings that it then turns on and off automatically. This is something I pushed for when designing the Parcel config format: Parcel divides up "transforms" and "optimizers" and only runs the optimizers if you are building for production.

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
Copy link
Contributor

jer3m01 commented Jun 25, 2021

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
Copy link
Contributor Author

@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:

  • Hidden files/folders (dotfiles) are bad for beginners, so .romerc and .config/rome.toml would both be bad choices
  • I don't see .config really taking off in a major way in any communities, so I think it's actually counter-intuitive to where people expect to find config.

@iduuck
Copy link

iduuck commented Jun 27, 2021

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
Copy link
Contributor

ematipico commented Jun 28, 2021

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
Copy link
Contributor

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
Copy link
Contributor Author

Spoke more about this as a team:

  • We want to move away from the .config folder for the reasons outlined in this comment
  • We want to continue to have the rome config command regardless of if we standardize around a single config file, we think its still useful.
  • We have not yet decided on TOML vs JSON w/ Comments
    • We agree that we should parse JSON as JSONC
  • We have not yet decided if we should remove package.json#rome
  • We want to add a top-level rome.toml/json (lowercase) file
  • We'll be documenting things as rome.json by default

@TmLev
Copy link

TmLev commented Sep 27, 2021

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

@ematipico
Copy link
Contributor

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
Copy link

scarsam commented Nov 23, 2022

@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
Copy link
Contributor

@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!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
umbrella Issue to track a collection of other issues
Projects
None yet
Development

No branches or pull requests

8 participants