From c07156f59bd00293c26023b6d50bf905558e7b39 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sat, 9 Jul 2022 17:30:44 -0500 Subject: [PATCH 1/9] Add hot-reloading for env file changes --- packages/next-env/index.ts | 28 ++++--- packages/next/server/base-server.ts | 5 +- packages/next/server/dev/hot-reloader.ts | 4 + packages/next/server/dev/next-dev-server.ts | 28 +++++++ packages/next/server/next-server.ts | 10 ++- .../env-config/app/pages/another-global.js | 1 + .../env-config/app/pages/api/all.js | 20 +++-- .../integration/env-config/app/pages/index.js | 4 + .../env-config/app/pages/some-ssg.js | 4 + .../env-config/app/pages/some-ssp.js | 4 + .../integration/env-config/test/index.test.js | 76 ++++++++++++++++++- 11 files changed, 162 insertions(+), 22 deletions(-) create mode 100644 test/integration/env-config/app/pages/another-global.js diff --git a/packages/next-env/index.ts b/packages/next-env/index.ts index 97df9677629..7843f797f91 100644 --- a/packages/next-env/index.ts +++ b/packages/next-env/index.ts @@ -10,6 +10,7 @@ export type LoadedEnvFiles = Array<{ contents: string }> +const initialEnv = Object.assign({}, process.env) let combinedEnv: Env | undefined = undefined let cachedLoadedEnvFiles: LoadedEnvFiles = [] @@ -21,18 +22,21 @@ type Log = { export function processEnv( loadedEnvFiles: LoadedEnvFiles, dir?: string, - log: Log = console + log: Log = console, + forceReload = false ) { - // don't reload env if we already have since this breaks escaped - // environment values e.g. \$ENV_FILE_KEY - if (process.env.__NEXT_PROCESSED_ENV || loadedEnvFiles.length === 0) { + // only reload env when forceReload is specified + if ( + !forceReload && + (process.env.__NEXT_PROCESSED_ENV || loadedEnvFiles.length === 0) + ) { return process.env as Env } // flag that we processed the environment values in case a serverless // function is re-used or we are running in `next start` mode process.env.__NEXT_PROCESSED_ENV = 'true' - const origEnv = Object.assign({}, process.env) + const origEnv = Object.assign({}, initialEnv) const parsed: dotenv.DotenvParseOutput = {} for (const envFile of loadedEnvFiles) { @@ -68,14 +72,18 @@ export function processEnv( export function loadEnvConfig( dir: string, dev?: boolean, - log: Log = console + log: Log = console, + forceReload = false ): { combinedEnv: Env loadedEnvFiles: LoadedEnvFiles } { - // don't reload env if we already have since this breaks escaped - // environment values e.g. \$ENV_FILE_KEY - if (combinedEnv) return { combinedEnv, loadedEnvFiles: cachedLoadedEnvFiles } + // only reload env when forceReload is specified + if (combinedEnv && !forceReload) { + return { combinedEnv, loadedEnvFiles: cachedLoadedEnvFiles } + } + process.env = Object.assign({}, initialEnv) + cachedLoadedEnvFiles = [] const isTest = process.env.NODE_ENV === 'test' const mode = isTest ? 'test' : dev ? 'development' : 'production' @@ -112,6 +120,6 @@ export function loadEnvConfig( } } } - combinedEnv = processEnv(cachedLoadedEnvFiles, dir, log) + combinedEnv = processEnv(cachedLoadedEnvFiles, dir, log, forceReload) return { combinedEnv, loadedEnvFiles: cachedLoadedEnvFiles } } diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index e552fffdb60..17a030ecb88 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -264,7 +264,10 @@ export default abstract class Server { res: BaseNextResponse ): void - protected abstract loadEnvConfig(params: { dev: boolean }): void + protected abstract loadEnvConfig(params: { + dev: boolean + forceReload?: boolean + }): void public constructor(options: ServerOptions) { const { diff --git a/packages/next/server/dev/hot-reloader.ts b/packages/next/server/dev/hot-reloader.ts index a8a588bf25f..54122368b6d 100644 --- a/packages/next/server/dev/hot-reloader.ts +++ b/packages/next/server/dev/hot-reloader.ts @@ -899,6 +899,10 @@ export default class HotReloader { ) }) + for (const key of Object.keys(entries)) { + delete entries[key] + } + this.onDemandEntries = onDemandEntryHandler({ multiCompiler, pagesDir: this.pagesDir, diff --git a/packages/next/server/dev/next-dev-server.ts b/packages/next/server/dev/next-dev-server.ts index 9aa929b1285..3ee5afd0df9 100644 --- a/packages/next/server/dev/next-dev-server.ts +++ b/packages/next/server/dev/next-dev-server.ts @@ -286,7 +286,17 @@ export default class DevServer extends Server { ) let nestedMiddleware: string[] = [] + const envFiles = [ + '.env.development.local', + '.env.local', + '.env.development', + '.env', + ].map((file) => pathJoin(this.dir, file)) + + files.push(...envFiles) + wp.watch(files, directories, 0) + const envFileTimes = new Map() wp.on('aggregated', async () => { const routedMiddleware: string[] = [] @@ -295,8 +305,20 @@ export default class DevServer extends Server { const knownFiles = wp.getTimeInfoEntries() const appPaths: Record = {} const ssrMiddleware = new Set() + let envChange = false for (const [fileName, meta] of knownFiles) { + if (envFiles.includes(fileName)) { + if ( + envFileTimes.get(fileName) && + envFileTimes.get(fileName) !== meta.timestamp + ) { + envChange = true + } + envFileTimes.set(fileName, meta.timestamp) + continue + } + if ( meta?.accuracy === undefined || !regexPageExtension.test(fileName) @@ -373,6 +395,12 @@ export default class DevServer extends Server { routedPages.push(pageName) } + if (envChange) { + this.loadEnvConfig({ dev: true, forceReload: true }) + await this.hotReloader?.stop() + await this.hotReloader?.start() + } + if (nestedMiddleware.length > 0) { Log.error( new NestedMiddlewareError(nestedMiddleware, this.dir, this.pagesDir) diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 4fcef3be4d1..7816fc3a8da 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -160,8 +160,14 @@ export default class NextNodeServer extends BaseServer { ? (compression() as ExpressMiddleware) : undefined - protected loadEnvConfig({ dev }: { dev: boolean }) { - loadEnvConfig(this.dir, dev, Log) + protected loadEnvConfig({ + dev, + forceReload, + }: { + dev: boolean + forceReload?: boolean + }) { + loadEnvConfig(this.dir, dev, Log, forceReload) } protected getPublicDir(): string { diff --git a/test/integration/env-config/app/pages/another-global.js b/test/integration/env-config/app/pages/another-global.js new file mode 100644 index 00000000000..7db38a7029f --- /dev/null +++ b/test/integration/env-config/app/pages/another-global.js @@ -0,0 +1 @@ +export default () =>

{process.env.NEXT_PUBLIC_HELLO_WORLD}

diff --git a/test/integration/env-config/app/pages/api/all.js b/test/integration/env-config/app/pages/api/all.js index 882343cf27b..52f181fe5fb 100644 --- a/test/integration/env-config/app/pages/api/all.js +++ b/test/integration/env-config/app/pages/api/all.js @@ -21,18 +21,22 @@ const variables = [ 'ENV_FILE_EXPANDED_CONCAT', 'ENV_FILE_EXPANDED_ESCAPED', 'ENV_FILE_KEY_EXCLAMATION', + 'NEW_ENV_KEY', + 'NEW_ENV_LOCAL_KEY', + 'NEW_ENV_DEV_KEY', + 'NEXT_PUBLIC_HELLO_WORLD', ] -const items = { - nextConfigEnv: process.env.nextConfigEnv, - nextConfigPublicEnv: process.env.nextConfigPublicEnv, -} +export default async (req, res) => { + const items = { + nextConfigEnv: process.env.nextConfigEnv, + nextConfigPublicEnv: process.env.nextConfigPublicEnv, + } -variables.forEach((variable) => { - items[variable] = process.env[variable] -}) + variables.forEach((variable) => { + items[variable] = process.env[variable] + }) -export default async (req, res) => { // Only for testing, don't do this... res.json(items) } diff --git a/test/integration/env-config/app/pages/index.js b/test/integration/env-config/app/pages/index.js index 8e0d187a75f..c8bc8ce3a77 100644 --- a/test/integration/env-config/app/pages/index.js +++ b/test/integration/env-config/app/pages/index.js @@ -21,6 +21,10 @@ const variables = [ 'ENV_FILE_EXPANDED_CONCAT', 'ENV_FILE_EXPANDED_ESCAPED', 'ENV_FILE_KEY_EXCLAMATION', + 'NEW_ENV_KEY', + 'NEW_ENV_LOCAL_KEY', + 'NEW_ENV_DEV_KEY', + 'NEXT_PUBLIC_HELLO_WORLD', ] export async function getStaticProps() { diff --git a/test/integration/env-config/app/pages/some-ssg.js b/test/integration/env-config/app/pages/some-ssg.js index 5486f5de7b4..d46d371b590 100644 --- a/test/integration/env-config/app/pages/some-ssg.js +++ b/test/integration/env-config/app/pages/some-ssg.js @@ -21,6 +21,10 @@ const variables = [ 'ENV_FILE_EXPANDED_CONCAT', 'ENV_FILE_EXPANDED_ESCAPED', 'ENV_FILE_KEY_EXCLAMATION', + 'NEW_ENV_KEY', + 'NEW_ENV_LOCAL_KEY', + 'NEW_ENV_DEV_KEY', + 'NEXT_PUBLIC_HELLO_WORLD', ] export async function getStaticProps() { diff --git a/test/integration/env-config/app/pages/some-ssp.js b/test/integration/env-config/app/pages/some-ssp.js index 0be53f7d037..ee985c926e2 100644 --- a/test/integration/env-config/app/pages/some-ssp.js +++ b/test/integration/env-config/app/pages/some-ssp.js @@ -21,6 +21,10 @@ const variables = [ 'ENV_FILE_EXPANDED_CONCAT', 'ENV_FILE_EXPANDED_ESCAPED', 'ENV_FILE_KEY_EXCLAMATION', + 'NEW_ENV_KEY', + 'NEW_ENV_LOCAL_KEY', + 'NEW_ENV_DEV_KEY', + 'NEXT_PUBLIC_HELLO_WORLD', ] export async function getServerSideProps() { diff --git a/test/integration/env-config/test/index.test.js b/test/integration/env-config/test/index.test.js index c87ce54f6f3..23baf525c59 100644 --- a/test/integration/env-config/test/index.test.js +++ b/test/integration/env-config/test/index.test.js @@ -12,10 +12,12 @@ import { launchApp, killApp, fetchViaHTTP, + check, } from 'next-test-utils' let app let appPort +let output = '' const appDir = join(__dirname, '../app') const getEnvFromHtml = async (path) => { @@ -27,7 +29,7 @@ const getEnvFromHtml = async (path) => { return env } -const runTests = (mode = 'dev') => { +const runTests = (mode = 'dev', didReload = false) => { const isDevOnly = mode === 'dev' const isTestEnv = mode === 'test' const isDev = isDevOnly || isTestEnv @@ -56,6 +58,11 @@ const runTests = (mode = 'dev') => { expect(data.ENV_FILE_EMPTY_FIRST).toBe(isTestEnv ? '' : '$escaped') expect(data.ENV_FILE_PROCESS_ENV).toBe('env-cli') + if (didReload) { + expect(data.NEW_ENV_KEY).toBe('true') + expect(data.NEW_ENV_LOCAL_KEY).toBe('hello') + expect(data.NEW_ENV_DEV_KEY).toBe('from-dev') + } expect(data.nextConfigEnv).toBe('hello from next.config.js') expect(data.nextConfigPublicEnv).toBe('hello again from next.config.js') } @@ -138,17 +145,84 @@ const runTests = (mode = 'dev') => { describe('Env Config', () => { describe('dev mode', () => { beforeAll(async () => { + output = '' appPort = await findPort() app = await launchApp(appDir, appPort, { env: { PROCESS_ENV_KEY: 'processenvironment', ENV_FILE_PROCESS_ENV: 'env-cli', }, + onStdout(msg) { + output += msg || '' + }, + onStderr(msg) { + output += msg || '' + }, }) + + await renderViaHTTP(appPort, '/another-global') }) afterAll(() => killApp(app)) runTests('dev') + + describe('with hot reload', () => { + const originalContents = [] + beforeAll(async () => { + const outputIndex = output.length + const envToUpdate = [ + { + toAdd: 'NEW_ENV_KEY=true', + file: '.env', + }, + { + toAdd: 'NEW_ENV_LOCAL_KEY=hello', + file: '.env.local', + }, + { + toAdd: 'NEW_ENV_DEV_KEY=from-dev\nNEXT_PUBLIC_HELLO_WORLD=again', + file: '.env.development', + }, + ] + + for (const { file, toAdd } of envToUpdate) { + const content = await fs.readFile(join(appDir, file), 'utf8') + originalContents.push({ file, content }) + await fs.writeFile(join(appDir, file), content + '\n' + toAdd) + } + + await check(() => { + return output.substring(outputIndex) + }, /Loaded env from/) + }) + afterAll(async () => { + for (const { file, content } of originalContents) { + await fs.writeFile(join(appDir, file), content) + } + }) + + runTests('dev', true) + + it('should update inlined values correctly', async () => { + await renderViaHTTP(appPort, '/another-global') + + const buildManifest = await fs.readJson( + join(__dirname, '../app/.next/build-manifest.json') + ) + + const pageFile = buildManifest.pages['/another-global'].find( + (filename) => filename.includes('pages/another-global') + ) + + // read client bundle contents since a server side render can + // have the value available during render but it not be injected + const bundleContent = await fs.readFile( + join(appDir, '.next', pageFile), + 'utf8' + ) + expect(bundleContent).toContain('again') + }) + }) }) describe('test environment', () => { From 9f3a863924e912e636064fb24717db5fa14f90d9 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sat, 9 Jul 2022 18:46:04 -0500 Subject: [PATCH 2/9] update watching --- packages/next/server/dev/next-dev-server.ts | 16 ++++++++++++---- packages/next/types/misc.d.ts | 6 ++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/next/server/dev/next-dev-server.ts b/packages/next/server/dev/next-dev-server.ts index 3ee5afd0df9..085788f26ad 100644 --- a/packages/next/server/dev/next-dev-server.ts +++ b/packages/next/server/dev/next-dev-server.ts @@ -263,7 +263,7 @@ export default class DevServer extends Server { ) let resolved = false - return new Promise((resolve, reject) => { + return new Promise(async (resolve, reject) => { // Watchpack doesn't emit an event for an empty directory fs.readdir(this.pagesDir, (_, files) => { if (files?.length) { @@ -276,7 +276,9 @@ export default class DevServer extends Server { } }) - const wp = (this.webpackWatcher = new Watchpack()) + const wp = (this.webpackWatcher = new Watchpack({ + ignored: /(node_modules|\.next)/, + })) const pages = [this.pagesDir] const app = this.appDir ? [this.appDir] : [] const directories = [...pages, ...app] @@ -294,8 +296,7 @@ export default class DevServer extends Server { ].map((file) => pathJoin(this.dir, file)) files.push(...envFiles) - - wp.watch(files, directories, 0) + wp.watch({ directories: [this.dir], startTime: 0 }) const envFileTimes = new Map() wp.on('aggregated', async () => { @@ -308,6 +309,13 @@ export default class DevServer extends Server { let envChange = false for (const [fileName, meta] of knownFiles) { + if ( + !files.includes(fileName) && + !directories.some((dir) => fileName.startsWith(dir)) + ) { + continue + } + if (envFiles.includes(fileName)) { if ( envFileTimes.get(fileName) && diff --git a/packages/next/types/misc.d.ts b/packages/next/types/misc.d.ts index 641cc7069d5..8e59e218618 100644 --- a/packages/next/types/misc.d.ts +++ b/packages/next/types/misc.d.ts @@ -356,6 +356,12 @@ declare module 'next/dist/compiled/watchpack' { class Watchpack extends EventEmitter { constructor(options?: any) + watch(params: { + files?: string[] + directories?: string[] + startTime?: number + missing?: string[] + }): void watch(files: string[], directories: string[], startTime?: number): void close(): void From 8b81d178df149623cbd13ce8951f75645f6cd4ff Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sat, 9 Jul 2022 18:54:23 -0500 Subject: [PATCH 3/9] update test --- test/unit/isolated/config.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unit/isolated/config.test.ts b/test/unit/isolated/config.test.ts index 01bc0c2671f..5d2d9ecab60 100644 --- a/test/unit/isolated/config.test.ts +++ b/test/unit/isolated/config.test.ts @@ -1,6 +1,5 @@ /* eslint-env jest */ import { join } from 'path' -import loadConfig from 'next/dist/server/config' import { PHASE_DEVELOPMENT_SERVER } from 'next/constants' const pathToConfig = join(__dirname, '_resolvedata', 'without-function') @@ -10,6 +9,8 @@ const pathToConfigFn = join(__dirname, '_resolvedata', 'with-function') // x-ref: https://github.com/nodejs/node/issues/35889 process.env.__NEXT_TEST_MODE = 'jest' +const loadConfig = require('next/dist/server/config').default + describe('config', () => { it('Should get the configuration', async () => { const config = await loadConfig(PHASE_DEVELOPMENT_SERVER, pathToConfig) From 21254c9cafe0a0eabc5911078a98ebe51144c200 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sat, 9 Jul 2022 19:07:58 -0500 Subject: [PATCH 4/9] update initial env handling --- packages/next-env/index.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/next-env/index.ts b/packages/next-env/index.ts index 7843f797f91..f8de0069cbc 100644 --- a/packages/next-env/index.ts +++ b/packages/next-env/index.ts @@ -4,13 +4,13 @@ import * as path from 'path' import * as dotenv from 'dotenv' import { expand as dotenvExpand } from 'dotenv-expand' -export type Env = { [key: string]: string } +export type Env = { [key: string]: string | undefined } export type LoadedEnvFiles = Array<{ path: string contents: string }> -const initialEnv = Object.assign({}, process.env) +let initialEnv: Env | undefined = undefined let combinedEnv: Env | undefined = undefined let cachedLoadedEnvFiles: LoadedEnvFiles = [] @@ -25,6 +25,9 @@ export function processEnv( log: Log = console, forceReload = false ) { + if (!initialEnv) { + initialEnv = Object.assign({}, process.env) + } // only reload env when forceReload is specified if ( !forceReload && @@ -65,7 +68,6 @@ export function processEnv( ) } } - return Object.assign(process.env, parsed) } @@ -78,6 +80,9 @@ export function loadEnvConfig( combinedEnv: Env loadedEnvFiles: LoadedEnvFiles } { + if (!initialEnv) { + initialEnv = Object.assign({}, process.env) + } // only reload env when forceReload is specified if (combinedEnv && !forceReload) { return { combinedEnv, loadedEnvFiles: cachedLoadedEnvFiles } From 2dd57ee2cb38a7552abbe96e4f787e826a1081c5 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sat, 9 Jul 2022 19:08:40 -0500 Subject: [PATCH 5/9] undo test change --- test/unit/isolated/config.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit/isolated/config.test.ts b/test/unit/isolated/config.test.ts index 5d2d9ecab60..01bc0c2671f 100644 --- a/test/unit/isolated/config.test.ts +++ b/test/unit/isolated/config.test.ts @@ -1,5 +1,6 @@ /* eslint-env jest */ import { join } from 'path' +import loadConfig from 'next/dist/server/config' import { PHASE_DEVELOPMENT_SERVER } from 'next/constants' const pathToConfig = join(__dirname, '_resolvedata', 'without-function') @@ -9,8 +10,6 @@ const pathToConfigFn = join(__dirname, '_resolvedata', 'with-function') // x-ref: https://github.com/nodejs/node/issues/35889 process.env.__NEXT_TEST_MODE = 'jest' -const loadConfig = require('next/dist/server/config').default - describe('config', () => { it('Should get the configuration', async () => { const config = await loadConfig(PHASE_DEVELOPMENT_SERVER, pathToConfig) From 1b4a55312a0525e634deb740ee7307b7c1e6b85a Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 18 Jul 2022 09:21:14 -0500 Subject: [PATCH 6/9] add comment for entries clearing --- packages/next/server/dev/hot-reloader.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/next/server/dev/hot-reloader.ts b/packages/next/server/dev/hot-reloader.ts index 8a6610d4975..3f3184830e9 100644 --- a/packages/next/server/dev/hot-reloader.ts +++ b/packages/next/server/dev/hot-reloader.ts @@ -922,6 +922,8 @@ export default class HotReloader { ) }) + // clear previous entries from on-demand-entry-handler + // so we have a fresh start from any previous instances for (const key of Object.keys(entries)) { delete entries[key] } From 22f406beb5362fe2ad97e9e7ea3ad07a6ded5806 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 18 Jul 2022 09:48:15 -0500 Subject: [PATCH 7/9] update on-demand-entry-handler restart handling --- packages/next/server/dev/hot-reloader.ts | 11 +++++------ packages/next/server/dev/on-demand-entry-handler.ts | 7 ++++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/next/server/dev/hot-reloader.ts b/packages/next/server/dev/hot-reloader.ts index 3f3184830e9..f251c991ece 100644 --- a/packages/next/server/dev/hot-reloader.ts +++ b/packages/next/server/dev/hot-reloader.ts @@ -29,6 +29,7 @@ import { findPageFile } from '../lib/find-page-file' import { BUILDING, entries, + getInvalidator, onDemandEntryHandler, } from './on-demand-entry-handler' import { denormalizePagePath } from '../../shared/lib/page-path/denormalize-page-path' @@ -922,12 +923,6 @@ export default class HotReloader { ) }) - // clear previous entries from on-demand-entry-handler - // so we have a fresh start from any previous instances - for (const key of Object.keys(entries)) { - delete entries[key] - } - this.onDemandEntries = onDemandEntryHandler({ multiCompiler, pagesDir: this.pagesDir, @@ -948,6 +943,10 @@ export default class HotReloader { edgeServerStats: () => this.edgeServerStats, }), ] + + // trigger invalidation to ensure any previous callbacks + // are handled in the on-demand-entry-handler + getInvalidator().invalidate() } public async stop(): Promise { diff --git a/packages/next/server/dev/on-demand-entry-handler.ts b/packages/next/server/dev/on-demand-entry-handler.ts index 9d34f9a3df7..9fafa9bd62e 100644 --- a/packages/next/server/dev/on-demand-entry-handler.ts +++ b/packages/next/server/dev/on-demand-entry-handler.ts @@ -127,6 +127,10 @@ export const entries: { let invalidator: Invalidator export const getInvalidator = () => invalidator +const doneCallbacks: EventEmitter | null = new EventEmitter() +const lastClientAccessPages = [''] +const lastServerAccessPagesForAppDir = [''] + export function onDemandEntryHandler({ maxInactiveAge, multiCompiler, @@ -145,9 +149,6 @@ export function onDemandEntryHandler({ appDir?: string }) { invalidator = new Invalidator(multiCompiler) - const doneCallbacks: EventEmitter | null = new EventEmitter() - const lastClientAccessPages = [''] - const lastServerAccessPagesForAppDir = [''] const startBuilding = (_compilation: webpack.Compilation) => { invalidator.startBuilding() From 301eacfa607f5cd695e56ad6fd7f57beea22fae3 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 18 Jul 2022 09:54:37 -0500 Subject: [PATCH 8/9] lint-fix --- packages/next/server/dev/on-demand-entry-handler.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/next/server/dev/on-demand-entry-handler.ts b/packages/next/server/dev/on-demand-entry-handler.ts index 9fafa9bd62e..ddf1ad780cf 100644 --- a/packages/next/server/dev/on-demand-entry-handler.ts +++ b/packages/next/server/dev/on-demand-entry-handler.ts @@ -224,11 +224,7 @@ export function onDemandEntryHandler({ const pingIntervalTime = Math.max(1000, Math.min(5000, maxInactiveAge)) setInterval(function () { - disposeInactiveEntries( - lastClientAccessPages, - lastServerAccessPagesForAppDir, - maxInactiveAge - ) + disposeInactiveEntries(maxInactiveAge) }, pingIntervalTime + 1000).unref() function handleAppDirPing( @@ -398,11 +394,7 @@ export function onDemandEntryHandler({ } } -function disposeInactiveEntries( - lastClientAccessPages: string[], - lastServerAccessPagesForAppDir: string[], - maxInactiveAge: number -) { +function disposeInactiveEntries(maxInactiveAge: number) { Object.keys(entries).forEach((page) => { const { lastActiveTime, status, dispose, bundlePath } = entries[page] From a1f61eb5bab32b8ac5098861a4d8574a3596bbde Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 18 Jul 2022 10:25:08 -0500 Subject: [PATCH 9/9] handle bad plugin --- packages/next/server/dev/hot-reloader.ts | 2 +- packages/next/server/dev/on-demand-entry-handler.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/next/server/dev/hot-reloader.ts b/packages/next/server/dev/hot-reloader.ts index f251c991ece..3ec5251ce32 100644 --- a/packages/next/server/dev/hot-reloader.ts +++ b/packages/next/server/dev/hot-reloader.ts @@ -946,7 +946,7 @@ export default class HotReloader { // trigger invalidation to ensure any previous callbacks // are handled in the on-demand-entry-handler - getInvalidator().invalidate() + getInvalidator()?.invalidate() } public async stop(): Promise { diff --git a/packages/next/server/dev/on-demand-entry-handler.ts b/packages/next/server/dev/on-demand-entry-handler.ts index ddf1ad780cf..0fd01e7c2fb 100644 --- a/packages/next/server/dev/on-demand-entry-handler.ts +++ b/packages/next/server/dev/on-demand-entry-handler.ts @@ -460,19 +460,19 @@ class Invalidator { this.building = true if (!keys || keys.length === 0) { - this.multiCompiler.compilers[0].watching.invalidate() - this.multiCompiler.compilers[1].watching.invalidate() - this.multiCompiler.compilers[2].watching.invalidate() + this.multiCompiler.compilers[0].watching?.invalidate() + this.multiCompiler.compilers[1].watching?.invalidate() + this.multiCompiler.compilers[2].watching?.invalidate() return } for (const key of keys) { if (key === 'client') { - this.multiCompiler.compilers[0].watching.invalidate() + this.multiCompiler.compilers[0].watching?.invalidate() } else if (key === 'server') { - this.multiCompiler.compilers[1].watching.invalidate() + this.multiCompiler.compilers[1].watching?.invalidate() } else if (key === 'edgeServer') { - this.multiCompiler.compilers[2].watching.invalidate() + this.multiCompiler.compilers[2].watching?.invalidate() } } }