Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(cli): add reactStrictMode option #3721

Merged
merged 1 commit into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
}