diff --git a/node/npm_dependencies.ts b/node/npm_dependencies.ts index c2ddb73d..de963337 100644 --- a/node/npm_dependencies.ts +++ b/node/npm_dependencies.ts @@ -69,7 +69,7 @@ export const getDependencyTrackerPlugin = ( return { external: true } } - const isLocalImport = specifier.startsWith(path.sep) || specifier.startsWith('.') + const isLocalImport = specifier.startsWith(path.sep) || specifier.startsWith('.') || path.isAbsolute(specifier) // If this is a local import, return so that esbuild visits that path. if (isLocalImport) { @@ -161,10 +161,6 @@ export const vendorNPMSpecifiers = async ({ return } - logger.user( - 'You are using npm modules in Edge Functions, which is an experimental feature. Learn more at https://ntl.fyi/edge-functions-npm.', - ) - // To bundle an entire module and all its dependencies, create a barrel file // where we re-export everything from that specifier. We do this for every // specifier, and each of these files will become entry points to esbuild. diff --git a/node/server/server.test.ts b/node/server/server.test.ts index d7dbe74f..ee92c6b7 100644 --- a/node/server/server.test.ts +++ b/node/server/server.test.ts @@ -44,13 +44,14 @@ test('Starts a server and serves requests for edge functions', async () => { getFunctionsConfig: true, } - const { functionsConfig, graph, success } = await server( + const { features, functionsConfig, graph, success } = await server( functions, { very_secret_secret: 'i love netlify', }, options, ) + expect(features).toEqual({}) expect(success).toBe(true) expect(functionsConfig).toEqual([{ path: '/my-function' }, {}, { path: '/global-netlify' }]) diff --git a/node/server/server.ts b/node/server/server.ts index b69bb8f2..953b0585 100644 --- a/node/server/server.ts +++ b/node/server/server.ts @@ -1,6 +1,7 @@ import { DenoBridge, OnAfterDownloadHook, OnBeforeDownloadHook, ProcessRef } from '../bridge.js' import { getFunctionConfig, FunctionConfig } from '../config.js' import type { EdgeFunction } from '../edge_function.js' +import type { FeatureFlags } from '../feature_flags.js' import { generateStage2 } from '../formats/javascript.js' import { ImportMap } from '../import_map.js' import { getLogger, LogFunction, Logger } from '../logger.js' @@ -18,6 +19,7 @@ interface PrepareServerOptions { distDirectory: string distImportMapPath?: string entryPoint?: string + featureFlags?: FeatureFlags flags: string[] formatExportTypeError?: FormatFunction formatImportError?: FormatFunction @@ -36,6 +38,7 @@ const prepareServer = ({ deno, distDirectory, distImportMapPath, + featureFlags, flags: denoFlags, formatExportTypeError, formatImportError, @@ -64,17 +67,22 @@ const prepareServer = ({ formatImportError, }) + const features: Record = {} const importMap = baseImportMap.clone() - const vendor = await vendorNPMSpecifiers({ - basePath, - directory: distDirectory, - functions: functions.map(({ path }) => path), - importMap, - logger, - }) - if (vendor) { - importMap.add(vendor.importMap) + if (featureFlags?.edge_functions_npm_modules) { + const vendor = await vendorNPMSpecifiers({ + basePath, + directory: distDirectory, + functions: functions.map(({ path }) => path), + importMap, + logger, + }) + + if (vendor) { + features.npmModules = true + importMap.add(vendor.importMap) + } } try { @@ -116,6 +124,7 @@ const prepareServer = ({ const success = await waitForServer(port, processRef.ps) return { + features, functionsConfig, graph, success, @@ -141,6 +150,7 @@ interface ServeOptions { certificatePath?: string debug?: boolean distImportMapPath?: string + featureFlags?: FeatureFlags inspectSettings?: InspectSettings importMapPaths?: string[] onAfterDownload?: OnAfterDownloadHook @@ -159,6 +169,7 @@ export const serve = async ({ debug, distImportMapPath, inspectSettings, + featureFlags, formatExportTypeError, formatImportError, importMapPaths = [], @@ -212,6 +223,7 @@ export const serve = async ({ deno, distDirectory: servePath, distImportMapPath, + featureFlags, flags, formatExportTypeError, formatImportError,