Skip to content
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
132 changes: 0 additions & 132 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1013,134 +1013,6 @@ jobs:
stepName: 'test-cache-components-prod-${{ matrix.group }}'
secrets: inherit

test-node-streams-cache-components-dev:
name: test node streams cache components dev
needs:
[
'optimize-ci',
'changes',
'build-native',
'build-next',
'fetch-test-timings',
]
if: ${{ needs.optimize-ci.outputs.skip == 'false' && needs.changes.outputs.docs-only == 'false' }}

strategy:
fail-fast: false
matrix:
group: [1/6, 2/6, 3/6, 4/6, 5/6, 6/6]
uses: ./.github/workflows/build_reusable.yml
with:
afterBuild: |
export __NEXT_USE_NODE_STREAMS=true
export __NEXT_CACHE_COMPONENTS=true
export __NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS=true
export __NEXT_EXPERIMENTAL_APP_NEW_SCROLL_HANDLER=true
export NEXT_EXTERNAL_TESTS_FILTERS="test/cache-components-tests-manifest.json"
export NEXT_TEST_MODE=dev
export IS_TURBOPACK_TEST=1
export TURBOPACK_DEV=1

node run-tests.js \
--timings \
--require-timings \
-g ${{ matrix.group }} \
--type development
testTimingsArtifact: 'test-timings'
stepName: 'test-node-streams-cache-components-dev-${{ matrix.group }}'
secrets: inherit

test-node-streams-cache-components-prod:
name: test node streams cache components prod
needs:
[
'optimize-ci',
'changes',
'build-native',
'build-next',
'fetch-test-timings',
]
if: ${{ needs.optimize-ci.outputs.skip == 'false' && needs.changes.outputs.docs-only == 'false' }}

strategy:
fail-fast: false
matrix:
group: [1/7, 2/7, 3/7, 4/7, 5/7, 6/7, 7/7]
uses: ./.github/workflows/build_reusable.yml
with:
afterBuild: |
export __NEXT_USE_NODE_STREAMS=true
export __NEXT_CACHE_COMPONENTS=true
export __NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS=true
export __NEXT_EXPERIMENTAL_APP_NEW_SCROLL_HANDLER=true
export NEXT_EXTERNAL_TESTS_FILTERS="test/cache-components-tests-manifest.json"
export NEXT_TEST_MODE=start
export IS_TURBOPACK_TEST=1
export TURBOPACK_BUILD=1

node run-tests.js \
--timings \
--require-timings \
-g ${{ matrix.group }} \
--type production
testTimingsArtifact: 'test-timings'
stepName: 'test-node-streams-cache-components-prod-${{ matrix.group }}'
secrets: inherit

test-node-streams-dev:
name: test node streams dev
needs: ['optimize-ci', 'changes', 'build-native', 'build-next']
if: ${{ needs.optimize-ci.outputs.skip == 'false' && needs.changes.outputs.docs-only == 'false' }}

strategy:
fail-fast: false
matrix:
group: [1/6, 2/6, 3/6, 4/6, 5/6, 6/6]
uses: ./.github/workflows/build_reusable.yml
with:
afterBuild: |
export __NEXT_USE_NODE_STREAMS=true
export NEXT_EXTERNAL_TESTS_FILTERS="test/use-node-streams-tests-manifest.json"
export NEXT_TEST_MODE=dev
export IS_TURBOPACK_TEST=1
export TURBOPACK_DEV=1
export __NEXT_EXPERIMENTAL_STRICT_ROUTE_TYPES=true
export RUST_BACKTRACE=1

node run-tests.js \
--timings \
-g ${{ matrix.group }} \
--type development
stepName: 'test-node-streams-dev-${{ matrix.group }}'
secrets: inherit

test-node-streams-prod:
name: test node streams prod
needs: ['optimize-ci', 'changes', 'build-native', 'build-next']
if: ${{ needs.optimize-ci.outputs.skip == 'false' && needs.changes.outputs.docs-only == 'false' }}

strategy:
fail-fast: false
matrix:
group: [1/7, 2/7, 3/7, 4/7, 5/7, 6/7, 7/7]
uses: ./.github/workflows/build_reusable.yml
with:
afterBuild: |
export __NEXT_USE_NODE_STREAMS=true
export NEXT_EXTERNAL_TESTS_FILTERS="test/use-node-streams-tests-manifest.json"
export NEXT_TEST_MODE=start
export IS_TURBOPACK_TEST=1
export TURBOPACK_BUILD=1
export __NEXT_EXPERIMENTAL_STRICT_ROUTE_TYPES=true
export RUST_BACKTRACE=1

node run-tests.js \
--timings \
-g ${{ matrix.group }} \
--type production
stepName: 'test-node-streams-prod-${{ matrix.group }}'
secrets: inherit

tests-pass:
needs:
[
Expand All @@ -1157,10 +1029,6 @@ jobs:
'test-firefox-safari',
'test-cache-components-dev',
'test-cache-components-prod',
'test-node-streams-cache-components-dev',
'test-node-streams-cache-components-prod',
'test-node-streams-dev',
'test-node-streams-prod',
'test-cargo-unit',
'rust-check',
'rustdoc-check',
Expand Down
12 changes: 11 additions & 1 deletion packages/next-env/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,17 @@ let cachedLoadedEnvFiles: LoadedEnvFiles = []
let previousLoadedEnvFiles: LoadedEnvFiles = []

export function updateInitialEnv(newEnv: Env) {
Object.assign(initialEnv || {}, newEnv)
if (!initialEnv) {
return
}

for (const [key, value] of Object.entries(newEnv)) {
if (value === undefined) {
delete initialEnv[key]
} else {
initialEnv[key] = value
}
}
}

type Log = {
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/server/config-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2040,6 +2040,7 @@ export const defaultConfig = Object.freeze({
gestureTransition: false,
inlineCss: false,
useCache: undefined,
useNodeStreams: true,
slowModuleDetection: undefined,
globalNotFound: false,
browserDebugInfoInTerminal: 'warn',
Expand Down
32 changes: 22 additions & 10 deletions packages/next/src/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1620,9 +1620,28 @@ function finalizeConfig(config: NextConfigComplete): NextConfigComplete {
validationLevel:
config.experimental.instantInsights?.validationLevel ?? 'manual-warning',
}
syncUseNodeStreamsEnv(config)
return config
}

function syncUseNodeStreamsEnv(config: NextConfig): void {
// This must use resolved config: user configs are inspected before defaults
// are merged, while runtime bundles must select the default implementation.
const useNodeStreams = config.experimental?.useNodeStreams
? 'true'
: undefined

if (useNodeStreams) {
process.env.__NEXT_USE_NODE_STREAMS = useNodeStreams
} else {
delete process.env.__NEXT_USE_NODE_STREAMS
}

// Dev env reloads restore process.env from this snapshot. Preserve the
// resolved runtime selection so a reload cannot mix stream implementations.
updateInitialEnv({ __NEXT_USE_NODE_STREAMS: useNodeStreams })
Comment thread
timneutkens marked this conversation as resolved.
}

async function applyModifyConfig(
config: NextConfigComplete,
phase: PHASE_TYPE,
Expand Down Expand Up @@ -1750,6 +1769,7 @@ export default async function loadConfig(
return cachedResult.rawConfig
}

syncUseNodeStreamsEnv(cachedResult.config)
return cachedResult.config
} else {
// Reset next.config errors before loading config
Expand Down Expand Up @@ -1777,6 +1797,8 @@ export default async function loadConfig(
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG
)

syncUseNodeStreamsEnv(standaloneConfig)

// Cache the standalone config
configCache.set(cacheKey, {
config: standaloneConfig,
Expand Down Expand Up @@ -2229,16 +2251,6 @@ function enforceExperimentalFeatures(
config.experimental.useNodeStreams = true
}

// Keep runtime bundle selection env in sync with the resolved config.
// Explicit user config (e.g. useNodeStreams: false) should win over an
// inherited shell env var to avoid selecting nodestream runtime bundles
// while define-env compiled user bundles with node streams disabled.
if (config.experimental.useNodeStreams) {
process.env.__NEXT_USE_NODE_STREAMS = 'true'
} else {
delete process.env.__NEXT_USE_NODE_STREAMS
}

// TODO: Remove this once strictRouteTypes is the default.
if (
process.env.__NEXT_EXPERIMENTAL_STRICT_ROUTE_TYPES === 'true' &&
Expand Down
22 changes: 21 additions & 1 deletion test/unit/preserve-process-env.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
import { loadEnvConfig } from '../../packages/next-env/'
import {
loadEnvConfig,
resetEnv,
updateInitialEnv,
} from '../../packages/next-env/'

describe('preserve process env', () => {
it('should not reassign `process.env`', () => {
const originalProcessEnv = process.env
loadEnvConfig('.')
expect(Object.is(originalProcessEnv, process.env)).toBeTrue()
})

it('should remove values unset in the initial env snapshot', () => {
const key = '__NEXT_TEST_UNSET_INITIAL_ENV'

try {
loadEnvConfig('.')
process.env[key] = 'changed'
updateInitialEnv({ [key]: undefined })

resetEnv()

expect(process.env[key]).toBeUndefined()
} finally {
delete process.env[key]
}
})
})
13 changes: 0 additions & 13 deletions test/use-node-streams-tests-manifest.json

This file was deleted.

Loading