Open cometkim opened 1 year ago
This is good stuff @cometkim ! How do we move forward on this?
I'm not actively promoting this to avoid adding any more noise before the v11 release. And still having time to think about better refactoring and migration strategies :grinning:
But please feel free to mention me if you have any thoughts on the config schema you rely on when working with other proposals, such as the #6408
Do we want to keep dev-dependencies? Is there a clear use-case for it?
Do we want to keep dev-dependencies? Is there a clear use-case for it?
no use cases right now unless we plan to support a standalone package manager for rescript.json
. However, I have explored this and it may still be useful information to third parties.
dev-dependencies
is useful for test frameworks and such.
I briefly discussed with @cknitt about using a third-party library for parsing manifest in the last ReScript Retreat.
TL;DR: Why not?
We have a lot of "ext" code to achieve zero dependencies. It has become another gray area for us over time.
There are some planned changes to JSON parsing (removing comments, trailing comma support) but making the change has a very low ROI.
I suggest adding Yojson as a dependency to build a new manifest. Yojson is very actively maintained and used in the OCaml community. Avoid "too declarative" options like ppx_deriving_yojson, atdgen for structured validation and error integration. At least for now.
Yes, in earlier days it was important to minimize dependencies at all costs as their source had to be vendored and shipped as part of the npm package to be able to build the compiler binaries on demand on npm install rescript
.
These days, fortunately, we just ship precompiled binaries for all major platforms instead and can easily add dependencies via our opam/dune-based build workflow.
While I still think we should be conservative about adding dependencies, adding yojson for JSON parsing seems absolutely fine to me.
Status: WIP. More research is required to complete this RFC.
This aims to simplify the current configuration schema and its parsing. Trying to explain its specifics and how to achieve it.
Motivation
ReScript v11 will support
rescript.json
for projects and their dependencies (See #6382), and so is deprecatingbsconfig.json
.Although it was a good opportunity to become aware of its inherent problems, and many deprecated or undocumented features. ReScript v11, we want to clean up these to make config easier to use and simplify the parsing phase.
Goals
For end-users, it is confusing because it's too complex, and contains many deprecated or undocumented features. So, the goal is to re-organize this to reduce confusion and provide a simpler schema that fits most use cases today.
For maintainers, the goal is to reduce code complexity. This is achieved by major code refactoring for the long term rather than simply deleting features.
For 3rd-party developers, the goal is to make reusing it outside the compiler (and the compiler itself) easier.
Detailed design
Cleanup & Simplifying Schema
TBD, this should be asked to the forum to collect actual use cases of current living features.
Not all of the suggestions here will happen, but we'll list out possible options for exploration ahead of the discussion.
Remove
bs
prefixes:bs-dependencies
->dependencies
bs-dev-dependencies
->dev-dependencies
bsc-flags
->compiler-flags
bs-external-includes
->external-includes
Remove legacy specs:
reason
: replaced byjsx
refmt
: not used (revisit later If the compiler gets configurable linter/formatter)entries
: options for OCamlConsiderable redesign:
js-post-build
package-specs
&suffix
jsx
:gentypeconfig
:external-stdlib
Js
andBelt
become external librarieswarnings
warnings.number
andwarnings.error
{ "missing-fields-in-record-pattern": "error", "unused-function-args": "off" }
sources
sources[].generators
(undocumented)sources[].resources
(undocumented)sources[].internal-depends
(undocumented)sources[].subdirs
so ensuresourceItem
definition is no longer recursive"src"
or["src", "test"]
or[{"dir": "src", "subdirs": [...]}]
?sources
?Remove undocumented, rarely used features:
generators
cut-generators
Fix naming convention:
gentypeconfig
->gentype
So ideal configuration might look like this:
Two-phase parsing
The current implementation (
bsb_config
) is interprets JSON input as it reads, with many IO operations. Since it's not pure and pretty heavy, it cannot be reused elsewhere it is needed such as syntax, gentype, reanalyze, etc.This proposal makes a new concept "manifest" or "user manifest" or "project manifest" which is a pure representation of
rescript.json
input. It is generated by JSON parsing and not by any system calls. So the manifest's types and parsing logic can be reused with no restrictions where necessary.Then the existing
bsb_config
represents the execution context of the bsb program and is initialized by therescript_manifest
module.The program flow would be like this:
Also
rescript_manifest
can be published to opam, to be consumed by third-party developersManaging Codebase
To keep the new config logic sustainable, we need to isolate it from the old codebase. This is achieved by the separated module
rescript_manifest
described in the "Two-phase parsing" section.To do this, we should extract the JSON-related part from the existing
bsb_config
code, and use it inbsb_config
again.JSON parsing logic is managed for each field within the
rescript_manifest
module. Therescript_manifest
parser is a combination of field parsers.Schema Detection
The
rescript_manifest
module maintains a snapshot of supported field combinations and exposes this as a version of the schema.The manifest version exists independently of the compiler version and is mapped to the config version of the running compiler, although the compiler can still handle multiple versions of the manifest.
The manifest version is encoded in URL and managed in compatibility date format to facilitate incremental enhancement such as adding fields.
e.g.
https://rescript-lang.org/manifest/2024-01-01/rescript.json
The manifest input must provide a
$schema
field for the compiler to identify the manifest version.Users must select one manifest version. This means that users cannot use
bs-dependencies
anddependencies
at the same time.Implementation steps
Building a base parser combinator library in OCaml,
Extract the bsconfig schema from the
bsb_config
module, and isolate it to separate modulerescript_manifest
.Define a registry and workflow to experiment with new manifest schema, incrementally
Migration Strategy
Switching Schema Detection Behavior
For v11.x, If the
$schema
field is not given, thehttps://rescript-lang.org/manifest/bsconfig.json
(legacy) schema is automatically selected.For v12, it will select the latest version supported by the current compiler version. The compiler may drop bsconfig schema support entirely.
An explicit version is recommended, the compiler may warn users about this.
Tooling Support
TBD
on
rescript init
, on VSCode extension, migration command, etc