--- tags: one-repo --- # Publishing approach for Fluent UI We have merged repos but we haven't merged publishing practices, and we haven't refined where things go and how we work within a single yarn workspace. There is some short term work going on to unblock things. Let's figure out what the right solution is, starting with requirements for next steps on how we simplify and automate releases. ## Requirements 1. Our team can develop *drastically* different versions of Fluent UI code on master branch of our repo and set up a regular release cadences for them. The release cadence can be different for each version. 2. End-user can consume any version and switch between any version of our library. And this should be easy to do without causing painful changes in user's code or requiring to use a specific tech. 3. All versions of Fluent UI code can be consumed together. For instance, users can use current Button + next Dropdown or current Button and next Button at the same time. (e.g. Teams uses Fabric and Stardust buttons at the same time.) ## Facts *Before we talk about solutions, here are some facts* 1. Our Yarn workspace requires unique package names. This means we cannot have multiple packages in our repo with the same package name such as `@fluentui/react`. 2. Beachball currently supports [scoped publishing](https://github.com/microsoft/beachball/issues/265). We can publish packages with different release cadence today. ## How users consume our packages ### Plan: Different versions use different package names | Command | Behavior | | -|-| | `npm install @fluentui/react` | Installs current long term support release channel. | |`npm install @fluentui/react-next` | Installs the next major release for early testing. | | `npm install @fluentui/react-northstar` | Installs future work release. | Pros: * **Publishing is simple.** No confusion involved related to maintaining a different published package name vs. package name in our monorepo. * **Relatively ergonomic for consumer**. End-user can still consume any version of our package easily by doing `npm add @fluentui/react@npm:@fluentui/react-next` and install the package with unchanged name `@fluentui/react`. Cons: * **Awkward dev exp switching between versions.** Consumers will need to do either of these: 1. Need to change their dependencies and imports. (non-starter) 2. Need to change their version dependency to remap the `@fluentui/react` dependency to `@fluentui/react-{flavor}`. ```json dependencies: { "@fluentui/react": "npm:@fluentui/react-next" } ``` * **Doesn't follow other (commonly used) release channel approaches.** React uses `@next` and `@experimental` tags to send users to the appropriate version. ## References ### Fabric publishing approach and cadence Fabric packages current release on a locked major version. As PRs are submitted, changes require "change files" which define release notes and requested bumps for which packages. A daily job runs to process the change files, update versions/dependency ranges for the various changed packages, and run `npm publish` in the right order. This process keeps developers who consume the packages happy, as bug fixes and minor features can be consumed in relatively short time. ### Stardust publishing approach and cadence The Stardust code has historically worked off a different release process: lock step version all packages on an infrequent monthly cadence. This can be good; less frequent updates means more intentional updates that can correspond with better communication. ### React Release Channels https://reactjs.org/docs/release-channels.html ### Alternative proposal: Different versions align package name at pre-publish Packages in the repo have the names listed in proposal 1, but at publishing time we tweak the names: | Command | Behavior | | -|-| | `npm install @fluentui/react` | Installs current v7 release. | | `npm install @fluentui/react@experimental` | Installs current v0 release. | |`npm install @fluentui/react@next` | Installs the next major release. | Pros: * **Very ergonomic for consumer.** User can switch between channels very easily by using `@tag` Cons: * **Publishing is hard**. In our repo, we must keep the packages with different names. So in order to publish them under the same name and different versions/tags, we need to do some *hacky* pre-publish magic. Published packages will not be in sync with packages inside the repo, things that differ: * Package name * Dependency package names * Import/export path in JS * Makes it impossible (without npm aliasing) to use both packages at the same time. (Possible to do: "@fluentui/react-next": "@fluentui/react@7") * Unknown blockers: * How to export code in `current` from `next`? That is exporting code from an older version of the same package. ### Discussion :::info *This should probably be just a comment but adding as content for better visibility* Please answer the questions below :male-teacher: ::: Q. How will react-focus version? react-focus: current code with patches and minors react-focus-next: staging for major change As dependency: * fui/react depend on react-focus * fui/react-next would depend on react-focus-next * In a major release of current, we'd move react-focus-next code into react-focus * fui/react-experimental would depend on react-focus to finally sync on the shipping release