Skip to content

Commit

Permalink
feature(cli): add reactStrictMode option (#3721)
Browse files Browse the repository at this point in the history
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
  • Loading branch information
stipsan and stipsan committed Oct 5, 2022
1 parent 7aff925 commit 5ecbbd9
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 14 deletions.
4 changes: 4 additions & 0 deletions dev/test-studio/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# To disable strict mode on your local checkout:
# `cp .env.example .env.development`
# Then restart your `sanity start` or `yarn dev` command
SANITY_STUDIO_REACT_STRICT_MODE=false
3 changes: 3 additions & 0 deletions dev/test-studio/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

# Ignore generated source files
/workshop/scopes.js

.env.*
!.env.example
4 changes: 4 additions & 0 deletions dev/test-studio/sanity.cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export default createCliConfig({
dataset: 'test',
},

// Can be overriden by:
// A) `SANITY_STUDIO_REACT_STRICT_MODE=false yarn dev`
// B) creating a `.env` file locally that sets the same env variable as above
reactStrictMode: true,
vite(viteConfig: UserConfig): UserConfig {
return {
...viteConfig,
Expand Down
8 changes: 8 additions & 0 deletions packages/@sanity/cli/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,14 @@ export interface CliConfig {
basePath?: string
}

/**
* Wraps the Studio in `<React.StrictMode>` root to aid flagging potential problems related to concurrent features (`startTransition`, `useTransition`, `useDeferredValue`, `Suspense`)
* Can also be enabled by setting `SANITY_STUDIO_REACT_STRICT_MODE="true"|"false"`.
* It only applies to `sanity start` in dev mode, it's ignored in `sanity build` and in production.
* Defaults to `false`
*/
reactStrictMode?: boolean

server?: {
hostname?: string
port?: number
Expand Down
2 changes: 1 addition & 1 deletion packages/@sanity/server/src/buildStaticFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export async function buildStaticFiles(
vite: extendViteConfig,
} = options

await writeSanityRuntime({cwd, watch: false})
await writeSanityRuntime({cwd, reactStrictMode: false, watch: false})

let viteConfig = await getViteConfig({
cwd,
Expand Down
5 changes: 3 additions & 2 deletions packages/@sanity/server/src/devServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface DevServerOptions {
httpHost?: string
projectName?: string

reactStrictMode: boolean
vite?: (config: InlineConfig) => InlineConfig
}

Expand All @@ -21,10 +22,10 @@ export interface DevServer {
}

export async function startDevServer(options: DevServerOptions): Promise<DevServer> {
const {cwd, httpPort, httpHost, basePath: base, vite: extendViteConfig} = options
const {cwd, httpPort, httpHost, basePath: base, reactStrictMode, vite: extendViteConfig} = options

const startTime = Date.now()
await writeSanityRuntime({cwd, watch: true})
await writeSanityRuntime({cwd, reactStrictMode, watch: true})

debug('Resolving vite config')
let viteConfig = await getViteConfig({
Expand Down
15 changes: 9 additions & 6 deletions packages/@sanity/server/src/getEntryModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import studioConfig from %STUDIO_CONFIG_LOCATION%
renderStudio(
document.getElementById("sanity"),
studioConfig
studioConfig,
%STUDIO_REACT_STRICT_MODE%
)
`

export function getEntryModule(options: {relativeConfigLocation: string}): string {
return entryModule.replace(
/%STUDIO_CONFIG_LOCATION%/,
JSON.stringify(options.relativeConfigLocation)
)
export function getEntryModule(options: {
reactStrictMode: boolean
relativeConfigLocation: string
}): string {
return entryModule
.replace(/%STUDIO_REACT_STRICT_MODE%/, JSON.stringify(Boolean(options.reactStrictMode)))
.replace(/%STUDIO_CONFIG_LOCATION%/, JSON.stringify(options.relativeConfigLocation))
}
12 changes: 10 additions & 2 deletions packages/@sanity/server/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {

export interface RuntimeOptions {
cwd: string
reactStrictMode: boolean
watch: boolean
}

Expand All @@ -23,7 +24,11 @@ export interface RuntimeOptions {
* @param options - Current working directory (Sanity root dir), and whether or not to watch
* @internal
*/
export async function writeSanityRuntime({cwd, watch}: RuntimeOptions): Promise<void> {
export async function writeSanityRuntime({
cwd,
reactStrictMode,
watch,
}: RuntimeOptions): Promise<void> {
const monorepo = await loadSanityMonorepo(cwd)
const runtimeDir = path.join(cwd, '.sanity', 'runtime')

Expand Down Expand Up @@ -55,5 +60,8 @@ export async function writeSanityRuntime({cwd, watch}: RuntimeOptions): Promise<
debug('Writing app.js to runtime directory')
const studioConfigPath = await getSanityStudioConfigPath(cwd)
const relativeConfigLocation = path.relative(runtimeDir, studioConfigPath)
await fs.writeFile(path.join(runtimeDir, 'app.js'), getEntryModule({relativeConfigLocation}))
await fs.writeFile(
path.join(runtimeDir, 'app.js'),
getEntryModule({reactStrictMode, relativeConfigLocation})
)
}
1 change: 1 addition & 0 deletions packages/@sanity/server/test/devServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('devServer', () => {
httpPort: 9700,
httpHost: 'localhost',

reactStrictMode: false,
vite(viteConfig: InlineConfig) {
return {
...viteConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,17 @@ function getDevServerConfig({

const basePath = env.SANITY_STUDIO_BASEPATH || cliConfig?.project?.basePath || '/'

const reactStrictMode = env.SANITY_STUDIO_REACT_STRICT_MODE
? env.SANITY_STUDIO_REACT_STRICT_MODE === 'true'
: Boolean(cliConfig?.reactStrictMode)

return {
cwd: workDir,
httpPort,
httpHost,
basePath,
staticPath: path.join(workDir, 'static'),
reactStrictMode,
vite: cliConfig?.vite,
}
}
Expand Down
14 changes: 11 additions & 3 deletions packages/sanity/src/core/studio/renderStudio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@ import type {Config} from '../config'
import {Studio} from './Studio'

/** @internal */
export function renderStudio(rootElement: HTMLElement | null, config: Config) {
export function renderStudio(
rootElement: HTMLElement | null,
config: Config,
reactStrictMode = false
) {
if (!rootElement) {
throw new Error('Missing root element to mount application into')
}

const root = createRoot(rootElement)
root.render(
<StrictMode>
reactStrictMode ? (
<StrictMode>
<Studio config={config} />
</StrictMode>
) : (
<Studio config={config} />
</StrictMode>
)
)
return () => root.unmount()
}

0 comments on commit 5ecbbd9

Please sign in to comment.