Skip to content

fix: exclude swc by default, and don't exclude sharp if included #1745

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

Merged
merged 1 commit into from
Nov 7, 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
37 changes: 33 additions & 4 deletions packages/runtime/src/helpers/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable max-lines */
import type { NetlifyConfig } from '@netlify/build'
import destr from 'destr'
import { readJSON, writeJSON } from 'fs-extra'
Expand Down Expand Up @@ -80,7 +81,28 @@ const resolveModuleRoot = (moduleName) => {

const DEFAULT_EXCLUDED_MODULES = ['sharp', 'electron']

export const configureHandlerFunctions = async ({ netlifyConfig, publish, ignore = [] }) => {
export const hasManuallyAddedModule = ({
netlifyConfig,
moduleName,
}: {
netlifyConfig: NetlifyConfig
moduleName: string
}) =>
/* eslint-disable camelcase */
Object.values(netlifyConfig.functions).some(({ included_files = [] }) =>
included_files.some((inc) => inc.includes(`node_modules/${moduleName}`)),
)
/* eslint-enable camelcase */

export const configureHandlerFunctions = async ({
netlifyConfig,
publish,
ignore = [],
}: {
netlifyConfig: NetlifyConfig
publish: string
ignore: Array<string>
}) => {
const config = await getRequiredServerFiles(publish)
const files = config.files || []
const cssFilesToInclude = files.filter((f) => f.startsWith(`${publish}/static/css/`))
Expand All @@ -91,6 +113,11 @@ export const configureHandlerFunctions = async ({ netlifyConfig, publish, ignore
netlifyConfig.functions._ipx.node_bundler = 'nft'
}

// If the user has manually added the module to included_files, then don't exclude it
const excludedModules = DEFAULT_EXCLUDED_MODULES.filter(
(moduleName) => !hasManuallyAddedModule({ netlifyConfig, moduleName }),
)

/* eslint-enable no-underscore-dangle */
;[HANDLER_FUNCTION_NAME, ODB_FUNCTION_NAME, '_api_*'].forEach((functionName) => {
netlifyConfig.functions[functionName] ||= { included_files: [], external_node_modules: [] }
Expand All @@ -109,6 +136,7 @@ export const configureHandlerFunctions = async ({ netlifyConfig, publish, ignore
`${publish}/BUILD_ID`,
`${publish}/static/chunks/webpack-middleware*.js`,
`!${publish}/server/**/*.js.nft.json`,
'!**/node_modules/@next/swc*/**/*',
...cssFilesToInclude,
...ignore.map((path) => `!${slash(path)}`),
)
Expand All @@ -123,7 +151,7 @@ export const configureHandlerFunctions = async ({ netlifyConfig, publish, ignore
)
}

DEFAULT_EXCLUDED_MODULES.forEach((moduleName) => {
excludedModules.forEach((moduleName) => {
const moduleRoot = resolveModuleRoot(moduleName)
if (moduleRoot) {
netlifyConfig.functions[functionName].included_files.push(`!${moduleRoot}/**/*`)
Expand Down Expand Up @@ -156,11 +184,11 @@ const buildHeader = (buildHeaderParams: BuildHeaderParams) => {
const sanitizePath = (path: string) => path.replace(/:[^*/]+\*$/, '*')

/**
* Persist NEXT.js custom headers to the Netlify configuration so the headers work with static files
* Persist Next.js custom headers to the Netlify configuration so the headers work with static files
* See {@link https://nextjs.org/docs/api-reference/next.config.js/headers} for more information on custom
* headers in Next.js
*
* @param nextConfig - The NextJS configuration
* @param nextConfig - The Next.js configuration
* @param netlifyHeaders - Existing headers that are already configured in the Netlify configuration
*/
export const generateCustomHeaders = (nextConfig: NextConfig, netlifyHeaders: NetlifyHeaders = []) => {
Expand Down Expand Up @@ -210,3 +238,4 @@ export const generateCustomHeaders = (nextConfig: NextConfig, netlifyHeaders: Ne
}
}
}
/* eslint-enable max-lines */
39 changes: 39 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ beforeEach(async () => {
netlifyConfig.headers = []
netlifyConfig.functions[HANDLER_FUNCTION_NAME] && (netlifyConfig.functions[HANDLER_FUNCTION_NAME].included_files = [])
netlifyConfig.functions[ODB_FUNCTION_NAME] && (netlifyConfig.functions[ODB_FUNCTION_NAME].included_files = [])
netlifyConfig.functions['_api_*'] && (netlifyConfig.functions['_api_*'].included_files = [])
await useFixture('serverless_next_config')
})

Expand Down Expand Up @@ -517,6 +518,7 @@ describe('onBuild()', () => {
'.next/BUILD_ID',
'.next/static/chunks/webpack-middleware*.js',
'!.next/server/**/*.js.nft.json',
'!**/node_modules/@next/swc*/**/*',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[dust] consider a separate PR for not bundling swc.

'!../../node_modules/next/dist/compiled/@ampproject/toolbox-optimizer/**/*',
`!node_modules/next/dist/server/lib/squoosh/**/*.wasm`,
`!node_modules/next/dist/next-server/server/lib/squoosh/**/*.wasm`,
Expand All @@ -533,6 +535,43 @@ describe('onBuild()', () => {
expect(netlifyConfig.functions[ODB_FUNCTION_NAME].node_bundler).toEqual('nft')
})

const excludesSharp = (includedFiles) => includedFiles.some((file) => file.startsWith('!') && file.includes('sharp'))

it("doesn't exclude sharp if manually included", async () => {
await moveNextDist()

const functions = [HANDLER_FUNCTION_NAME, ODB_FUNCTION_NAME, '_api_*']

await nextRuntime.onBuild(defaultArgs)

// Should exclude by default
for (const func of functions) {
expect(excludesSharp(netlifyConfig.functions[func].included_files)).toBeTruthy()
}

// ...but if the user has added it, we shouldn't exclude it
for (const func of functions) {
netlifyConfig.functions[func].included_files = ['node_modules/sharp/**/*']
}

await nextRuntime.onBuild(defaultArgs)

for (const func of functions) {
expect(excludesSharp(netlifyConfig.functions[func].included_files)).toBeFalsy()
}

// ...even if it's in a subdirectory
for (const func of functions) {
netlifyConfig.functions[func].included_files = ['subdirectory/node_modules/sharp/**/*']
}

await nextRuntime.onBuild(defaultArgs)

for (const func of functions) {
expect(excludesSharp(netlifyConfig.functions[func].included_files)).toBeFalsy()
}
})

it('generates a file referencing all page sources', async () => {
await moveNextDist()
await nextRuntime.onBuild(defaultArgs)
Expand Down