diff --git a/apps/docs/markdown-pages/docs/manual/build-configuration-schema.mdx b/apps/docs/markdown-pages/docs/manual/build-configuration-schema.mdx index 6fce0b810..22ac259dc 100644 --- a/apps/docs/markdown-pages/docs/manual/build-configuration-schema.mdx +++ b/apps/docs/markdown-pages/docs/manual/build-configuration-schema.mdx @@ -8,3 +8,5 @@ order: 3 --- + +For feature-gated source directories, dependency feature selection, and current build-system defaults, see [Configuration](./build-configuration.mdx). The schema above does not yet describe all native build-system options. diff --git a/apps/docs/markdown-pages/docs/manual/build-configuration.mdx b/apps/docs/markdown-pages/docs/manual/build-configuration.mdx index cabc933d9..92f151c78 100644 --- a/apps/docs/markdown-pages/docs/manual/build-configuration.mdx +++ b/apps/docs/markdown-pages/docs/manual/build-configuration.mdx @@ -9,9 +9,9 @@ order: 2 # Configuration -`rescript.json` is the single, mandatory build meta file needed for `rescript`. +Put each package's build configuration in `rescript.json`. -**The complete configuration schema is [here](./build-configuration-schema.mdx)**. We'll _non-exhaustively_ highlight the important parts in prose below. +Browse the [configuration schema](./build-configuration-schema.mdx) for a reference. The sections below explain common settings and native build-system options. ## name, namespace @@ -58,7 +58,7 @@ Your source files need to be specified explicitly (we don't want to accidentally } ``` -You can mark your directories as dev-only (for e.g. tests). These won't be built and exposed to third-parties, or even to other "dev" directories in the same project: +You can mark directories containing tests or development helpers as dev-only. Their modules can use `dev-dependencies`; they aren't compiled when the package is a third-party dependency or when you use [`--prod`](./build-overview.mdx#production-builds): ```json { @@ -87,7 +87,55 @@ List of ReScript dependencies. Just like `package.json`'s dependencies, they'll Note that only sources marked with `"type":"dev"` will be able to resolve modules from `dev-dependencies`. -> The legacy keys `bs-dependencies` and `bs-dev-dependencies` are still accepted but deprecated. +Use package names as strings to build all of a dependency's features. To select only some of its features, use the object form described below. + +## features + +Features let a package include optional source directories, such as browser-specific modules. Tag a source directory with `feature`, and use the top-level `features` map when one feature should enable others: + +```json +{ + "name": "optional-ui", + "sources": [ + { "dir": "src" }, + { "dir": "src-dom", "feature": "dom" }, + { "dir": "src-browser", "feature": "browser" } + ], + "features": { + "core": [], + "browser": ["dom"] + } +} +``` + +Without a feature selection, all source directories are built. Use `--features` with `build` or `watch` to select features for the package you're building: + +```sh +rescript build --features core +rescript build --features browser +``` + +The first command builds only the untagged `src` directory. The second also builds `src-browser` and `src-dom`, because `browser` enables `dom`. Feature implications are transitive, and cycles are rejected. Untagged directories are included with every selection; tagged directories require their feature to be active. Nested source directories inherit their parent's feature unless they declare their own. + +`--features` takes a comma-separated list, such as `--features core,browser`. An empty selection is rejected. The flag only selects the current package's features; it does not select features for its dependencies. + +### Selecting a Dependency's Features + +In the consuming package's `rescript.json`, list the features you need from a dependency: + +```json +{ + "dependencies": [{ "name": "optional-ui", "features": ["browser"] }] +} +``` + +The dependency's own feature map expands this selection, so `optional-ui` also builds its `dom` feature. The same object form works in `dev-dependencies`. + +- A string entry, or an object without `features`, enables all of that dependency's features. +- An explicit `"features": []` builds only its untagged source directories. +- If several packages consume the same dependency, their feature requests are combined. If any consumer requests all features, all are enabled. + +Feature selection and `--prod` both apply: a dev-only directory is excluded from a production build even if its feature is enabled. ## js-post-build @@ -122,7 +170,7 @@ Controls how the compiler emits JSX and which runtime (if any) it delegates to. } ``` -- `version`: JSX transform version. `4` enables the React 17+ transform and is the current and only supported option in v12. +- `version`: JSX transform version. `4` enables the React 17+ transform and is the current supported version. - `module`: Override the target module that receives JSX calls. Useful for [generic JSX transforms](./jsx.mdx#generic-jsx-transform-jsx-beyond-react-experimental); omit it when using the built-in React runtime. - `preserve`: When `true`, the compiler re-emits JSX syntax in the generated JavaScript so bundlers or other tooling can take over the transform later. The regenerated JSX might differ slightly from the original source but stays semantically equivalent. See [Preserve mode](./jsx.mdx#preserve-mode) for details. @@ -130,20 +178,33 @@ All fields are optional; unspecified fields fall back to the defaults mentioned ## package-specs -Output to either CommonJS (the default) or JavaScript module. Example: +Choose JavaScript modules (`esmodule`, the default) or CommonJS (`commonjs`). By default, JavaScript is generated alongside the source files. For example: ```json { "package-specs": { - "module": "commonjs", + "module": "esmodule", "in-source": true } } ``` -- `"module": "commonjs"` generates output as CommonJS format. -- `"module": "esmodule"` generates output as JavaScript module format. Will be default value in next major. -- `"in-source": true` generates output alongside source files. If you omit it, it'll generate the artifacts into `lib/js`. The output directory is not configurable otherwise. +- `"module": "esmodule"` generates JavaScript modules and is the default when `package-specs` is omitted. +- `"module": "commonjs"` generates CommonJS output. +- `"in-source": true` is the default and generates output alongside source files. Set it to `false` to use `lib/es6` for JavaScript modules or `lib/js` for CommonJS. + +To emit both formats, use distinct suffixes so the outputs don't overwrite each other: + +```json +{ + "package-specs": [ + { "module": "esmodule", "suffix": ".mjs" }, + { "module": "commonjs", "suffix": ".cjs" } + ] +} +``` + +A suffix set on an individual package spec overrides the top-level `suffix` setting. This configuration only applies to you, when you develop the project. When the project is used as a third-party library, the consumer's own `rescript.json` `package-specs` overrides the configuration here, logically. @@ -153,7 +214,7 @@ This configuration only applies to you, when you develop the project. When the p one of the following: -- `".js` +- `".js"` - `".mjs"` - `".cjs"` - `".res.js"` @@ -191,8 +252,6 @@ Extra flags to pass to the compiler. For advanced usages. - `-open ABC` opens the module `ABC` for each file in the project. `ABC` can either be a dependency, namespaced project or local module of the current project. -> The legacy key `bsc-flags` is still accepted but deprecated. - ## gentypeconfig To enable genType, set `"gentypeconfig"` at top level in the project's `rescript.json`. @@ -223,6 +282,22 @@ To enable genType, set `"gentypeconfig"` at top level in the project's `rescript `debug`: Enable debug logs. +## Migrating Older Configurations + +Use `rescript.json` for new projects. For compatibility, the build system also reads `bsconfig.json` when `rescript.json` is absent, with a deprecation warning. + +Prefer these current configuration keys: + +| Legacy key | Current key | +| --------------------- | ------------------ | +| `bs-dependencies` | `dependencies` | +| `bs-dev-dependencies` | `dev-dependencies` | +| `bsc-flags` | `compiler-flags` | + +The legacy keys are still accepted with deprecation warnings. Remove `external-stdlib`; it is no longer supported. + +Use `esmodule` instead of `es6` or `es6-global`, and `commonjs` instead of `cjs`. The `es6` and `cjs` aliases are still accepted with deprecation warnings; `es6-global` is unsupported. + ## Environment Variables We heavily disrecommend the usage of environment variables, but for certain cases, they're justified. diff --git a/apps/docs/markdown-pages/docs/manual/build-monorepo-setup.mdx b/apps/docs/markdown-pages/docs/manual/build-monorepo-setup.mdx index 39f0336f3..56c22bd84 100644 --- a/apps/docs/markdown-pages/docs/manual/build-monorepo-setup.mdx +++ b/apps/docs/markdown-pages/docs/manual/build-monorepo-setup.mdx @@ -15,8 +15,6 @@ order: 5 ReScript 12.0 introduces improved support for native monorepos through the new ["Rewatch"](../../blog/reforging-build-system.mdx) build system. This guide walks you through the setup process. -**Note:** This feature requires the new build system and is **not compatible** with `rescript-legacy`. - ## Project Structure A ReScript monorepo requires a `rescript.json` file at the repository root, plus a `rescript.json` file in each sub-project directory. @@ -68,17 +66,19 @@ Therefore, it is recommended to place these settings in the root `rescript.json` **Settings from different config files:** When Rewatch builds a package within a monorepo setup, it uses these settings from the root rescript.json: -- `"jsx"` (jsx_args, jsx_module_args, jsx_mode_args, jsx_preserve_args) -- `"experimental"` (experimental_features_args) -- `"package-specs"` (used for implementation_args) -- `"suffix"` (used for package output) +- `"jsx"` +- `"experimental-features"` +- `"package-specs"` +- `"suffix"` These settings come from the package's own rescript.json: - `"sources"` (determines which files to compile) - `"dependencies"` (package dependencies) -- `"warnings"` (warning_args) -- `"compiler-flags"` (bsc_flags) +- `"dev-dependencies"` +- `"features"` +- `"warnings"` +- `"compiler-flags"` When the root package is built, Rewatch will look for the dependencies inside the `my-monorepo/node_modules` folder. It is expected that `package-1` and `package-2` are available there via a symlink system provided by your node_modules package manager. @@ -137,6 +137,10 @@ rescript clean rescript format ``` +Use `rescript build --prod` to exclude dev dependencies and dev-only source directories across the monorepo. The same flag is available on `watch` and `clean`. + +To select features of a workspace package when building the root, use a dependency entry such as `{"name": "package-1", "features": ["browser"]}` in the root configuration. `--features` selects the package being built, rather than every package in the monorepo. See [Features](./build-configuration.mdx#features) for the selection rules. + ### Building individual packages You can also run ReScript commands on individual packages instead of the entire monorepo. This is useful when you only want to work on one package. diff --git a/apps/docs/markdown-pages/docs/manual/build-overview.mdx b/apps/docs/markdown-pages/docs/manual/build-overview.mdx index 1641dd7bd..be05cea3a 100644 --- a/apps/docs/markdown-pages/docs/manual/build-overview.mdx +++ b/apps/docs/markdown-pages/docs/manual/build-overview.mdx @@ -11,7 +11,7 @@ order: 1 ReScript comes with a fast, native build system through the [`rescript`](https://www.npmjs.com/package/rescript) package. -Every ReScript project needs a build description file, `rescript.json`. +Configure each ReScript package in a `rescript.json` file. See [Build Configuration](./build-configuration.mdx) for the available settings and compatibility with older configuration files. The current build system was introduced in ReScript 12. It tracks dependencies across packages and schedules only the work affected by a change. See [Reforging the Build System](../../blog/reforging-build-system.mdx) for a deeper look at its architecture. @@ -54,10 +54,31 @@ rescript watch Any new file change will be picked up and the build will re-run. +Watch output distinguishes rebuilds, successful compilations, warnings, and failures. To clear the terminal before each rebuild, use: + +```sh +rescript watch --clear-screen +``` + +Screen clearing only applies to interactive terminal output. You can also run a separate `rescript build` while a watcher is active. + Third-party libraries in `node_modules` aren't watched. For monorepo setup in ReScript 12+, see [Setting up a monorepo](./build-monorepo-setup.mdx). +### Production Builds + +Use `--prod` to exclude `dev-dependencies` and source directories marked with `"type": "dev"`: + +```sh +rescript build --prod +rescript watch --prod +``` + +This filtering applies across the packages being built, including local monorepo packages. Without `--prod`, local packages also compile their dev sources and dev dependencies. + +To select optional parts of a package's source tree, see [Features](./build-configuration.mdx#features). + ### Incremental Builds The build system recompiles only files affected by a change. Interface files (`.resi`) can reduce this work further: if an implementation change doesn't alter the corresponding interface, dependent modules don't need to be recompiled. See [Module signatures](./module.mdx#signatures) and [Build Performance](./build-performance.mdx). @@ -70,6 +91,8 @@ If you ever get into a stale build for edge-case reasons, use: rescript clean ``` +`rescript clean --prod` applies the same dev-source and dev-dependency exclusions as production builds. Cleaning covers all feature-gated source directories; `clean` does not accept `--features`. + ## Format Source Files Format the project's ReScript files with: