diff --git a/README.md b/README.md index 8ccb4e78c8..2efe8b6c0e 100644 --- a/README.md +++ b/README.md @@ -48,15 +48,9 @@ If your Next.js project was already deployed to Netlify pre-3.0.0, use the Netli package = "@netlify/plugin-nextjs" ``` -Note: the plugin does not run for statically exported Next.js sites (aka sites that use `next export`). To use the plugin, you should use the `[build]` config in the .toml snippet above. Be sure to exclude `next export` from your build script. - - You can also add context-specific properties and environment variables to your `netlify.toml`. Read more about [deploy contexts](https://docs.netlify.com/configure-builds/file-based-configuration/#deploy-contexts) in our docs. For example: - -```toml -[context.production.environment] -NEXT_SERVERLESS = "true" -NODE_ENV = "production" -``` +Note: the plugin does not run for statically exported Next.js sites (aka sites that use `next export`). To use the plugin, you should use the `[build]` config in the .toml snippet above. Be sure to exclude `next export` from your build script. +The plugin will attempt to detect if the site uses static export or Storybook, and will not run for either. If you want to disable the auto-detection, you can set the `NEXT_PLUGIN_FORCE_RUN` environment variable to `true` or `false`. +Setting it to `true` or `1` will mean the plugin always runs, and setting it to `false` or `0` will mean it never runs. If unset, auto-detection will be used. This variable should be set in the Netlify UI or in the `netlify.toml` file. 2\. From your project's base directory, use `npm`, `yarn`, or any other Node.js package manager to add this plugin to `dependencies` in `package.json`. diff --git a/helpers/doesNotNeedPlugin.js b/helpers/doesNotNeedPlugin.js index c4f52a7a5b..4e0d14150e 100644 --- a/helpers/doesNotNeedPlugin.js +++ b/helpers/doesNotNeedPlugin.js @@ -6,6 +6,26 @@ const isStaticExportProject = require('./isStaticExportProject') const usesBuildCommand = require('./usesBuildCommand') const doesNotNeedPlugin = ({ netlifyConfig, packageJson }) => { + // The env var skips the auto-detection + const envVar = process.env.NEXT_PLUGIN_FORCE_RUN + if (envVar === 'false' || envVar === '0' || envVar === false) { + console.log( + yellowBright`The env var NEXT_PLUGIN_FORCE_RUN was set to ${JSON.stringify( + envVar, + )}, so auto-detection is disabled and the plugin will not run`, + ) + return true + } + if (envVar === 'true' || envVar === '1' || envVar === true) { + console.log( + yellowBright`The env var NEXT_PLUGIN_FORCE_RUN was set to ${JSON.stringify( + envVar, + )}, so auto-detection is disabled and the plugin will run regardless`, + ) + return false + } + // Otherwise use auto-detection + const { build } = netlifyConfig const { scripts = {} } = packageJson @@ -18,7 +38,7 @@ const doesNotNeedPlugin = ({ netlifyConfig, packageJson }) => { if (usesBuildCommand({ build, scripts, command: 'build-storybook' })) { console.log( - yellowBright`Site seems to be building a Storybook rather than the Next.js site, so the Essential Next.js plugin will not run.`, + yellowBright`Site seems to be building a Storybook rather than the Next.js site, so the Essential Next.js plugin will not run. If this is incorrect, set NEXT_PLUGIN_FORCE_RUN to true`, ) return true } diff --git a/helpers/usesBuildCommand.js b/helpers/usesBuildCommand.js index 3b86f04b8c..2cd1bf56b8 100644 --- a/helpers/usesBuildCommand.js +++ b/helpers/usesBuildCommand.js @@ -24,11 +24,12 @@ const usesBuildCommand = ({ build, scripts, command }) => { return raw.some((script) => script.includes(command)) } catch (error) { console.error( - 'There was an error parsing your build command:', - error.message, - `\n\nThe build command is "${build.command}" and the available npm scripts are: ${Object.keys(scripts) + `Static export detection disabled because we could not parse your build command: ${error.message} +The build command is "${build.command}" and the available npm scripts are: ${Object.keys(scripts) .map((script) => `"${script}"`) - .join(', ')}`, + .join(', ')} + +If the site does use static export then you can set the env var NEXT_PLUGIN_FORCE_RUN to "false" or uninstall the plugin. See https://ntl.fyi/remove-plugin for instructions.`, ) } } diff --git a/test/index.js b/test/index.js index 97bd7a7147..fc584fb440 100644 --- a/test/index.js +++ b/test/index.js @@ -143,6 +143,42 @@ describe('preBuild()', () => { expect(process.env.NEXT_PRIVATE_TARGET).toBe('serverless') }) + test('run plugin if `NEXT_PLUGIN_FORCE_RUN` is set to true, even if next export is in script', async () => { + process.env.NEXT_PLUGIN_FORCE_RUN = 'true' + await plugin.onPreBuild({ + netlifyConfig, + packageJson: { ...DUMMY_PACKAGE_JSON, scripts: { build: 'next export' } }, + utils, + constants: {}, + }) + expect(process.env.NEXT_PRIVATE_TARGET).toBe('serverless') + process.env.NEXT_PLUGIN_FORCE_RUN = undefined + }) + + test('run plugin if `NEXT_PLUGIN_FORCE_RUN` is set to true, even if build-storybook is in script', async () => { + process.env.NEXT_PLUGIN_FORCE_RUN = 'true' + await plugin.onPreBuild({ + netlifyConfig, + packageJson: { ...DUMMY_PACKAGE_JSON, scripts: { build: 'build-storybook' } }, + utils, + constants: {}, + }) + expect(process.env.NEXT_PRIVATE_TARGET).toBe('serverless') + process.env.NEXT_PLUGIN_FORCE_RUN = undefined + }) + + test('not run plugin if `NEXT_PLUGIN_FORCE_RUN` is set to false', async () => { + process.env.NEXT_PLUGIN_FORCE_RUN = 'false' + await plugin.onPreBuild({ + netlifyConfig, + packageJson: DUMMY_PACKAGE_JSON, + utils, + constants: {}, + }) + expect(process.env.NEXT_PRIVATE_TARGET).toBeUndefined() + process.env.NEXT_PLUGIN_FORCE_RUN = undefined + }) + test('do nothing if app has static html export in toml/ntl config', async () => { await plugin.onPreBuild({ netlifyConfig: { build: { command: 'next build && next export' } },