Skip to content

Commit

Permalink
feat!: remove support for JavaScript bundles (#224)
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardoboucas committed Nov 24, 2022
1 parent 08ce8a5 commit d8f45b1
Show file tree
Hide file tree
Showing 8 changed files with 9 additions and 188 deletions.
61 changes: 4 additions & 57 deletions node/bundler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { BundleError } from './bundle_error.js'
import { bundle, BundleOptions } from './bundler.js'
import { isNodeError } from './utils/error.js'

test('Produces a JavaScript bundle and a manifest file', async () => {
test('Produces an ESZIP bundle', async () => {
const sourceDirectory = resolve(fixturesDir, 'with_import_maps', 'functions')
const tmpDir = await tmp.dir()
const declarations = [
Expand All @@ -34,39 +34,6 @@ test('Produces a JavaScript bundle and a manifest file', async () => {
const manifest = JSON.parse(manifestFile)
const { bundles } = manifest

expect(bundles.length).toBe(1)
expect(bundles[0].format).toBe('js')
expect(generatedFiles.includes(bundles[0].asset)).toBe(true)
expect(result.manifest).toEqual(manifest)

await fs.rmdir(tmpDir.path, { recursive: true })
})

test('Produces only a ESZIP bundle when the `edge_functions_produce_eszip` feature flag is set', async () => {
const sourceDirectory = resolve(fixturesDir, 'with_import_maps', 'functions')
const tmpDir = await tmp.dir()
const declarations = [
{
function: 'func1',
path: '/func1',
},
]
const result = await bundle([sourceDirectory], tmpDir.path, declarations, {
basePath: fixturesDir,
configPath: join(sourceDirectory, 'config.json'),
featureFlags: {
edge_functions_produce_eszip: true,
},
})
const generatedFiles = await fs.readdir(tmpDir.path)

expect(result.functions.length).toBe(1)
expect(generatedFiles.length).toBe(2)

const manifestFile = await fs.readFile(resolve(tmpDir.path, 'manifest.json'), 'utf8')
const manifest = JSON.parse(manifestFile)
const { bundles } = manifest

expect(bundles.length).toBe(1)
expect(bundles[0].format).toBe('eszip2')
expect(generatedFiles.includes(bundles[0].asset)).toBe(true)
Expand All @@ -86,9 +53,6 @@ test('Uses the vendored eszip module instead of fetching it from deno.land', asy
const result = await bundle([sourceDirectory], tmpDir.path, declarations, {
basePath: fixturesDir,
configPath: join(sourceDirectory, 'config.json'),
featureFlags: {
edge_functions_produce_eszip: true,
},
})
const generatedFiles = await fs.readdir(tmpDir.path)

Expand Down Expand Up @@ -124,7 +88,7 @@ test('Adds a custom error property to user errors during bundling', async () =>
expect(error).toBeInstanceOf(BundleError)
expect((error as BundleError).customErrorInfo).toEqual({
location: {
format: 'javascript',
format: 'eszip',
runtime: 'deno',
},
type: 'functionsBundling',
Expand All @@ -145,11 +109,7 @@ test('Prints a nice error message when user tries importing NPM module', async (
]

try {
await bundle([sourceDirectory], tmpDir.path, declarations, {
featureFlags: {
edge_functions_produce_eszip: true,
},
})
await bundle([sourceDirectory], tmpDir.path, declarations)
} catch (error) {
expect(error).toBeInstanceOf(BundleError)
expect((error as BundleError).message).toEqual(
Expand All @@ -170,7 +130,7 @@ test('Does not add a custom error property to system errors during bundling', as
})

test('Uses the cache directory as the `DENO_DIR` value if the `edge_functions_cache_deno_dir` feature flag is set', async () => {
expect.assertions(7)
expect.assertions(6)

const sourceDirectory = resolve(fixturesDir, 'with_import_maps', 'functions')
const outDir = await tmp.dir()
Expand Down Expand Up @@ -214,7 +174,6 @@ test('Uses the cache directory as the `DENO_DIR` value if the `edge_functions_ca

const denoDir2 = await fs.readdir(join(cacheDir.path, 'deno_dir'))

expect(denoDir2.includes('deps')).toBe(true)
expect(denoDir2.includes('gen')).toBe(true)

await fs.rmdir(outDir.path, { recursive: true })
Expand All @@ -232,9 +191,6 @@ test('Supports import maps with relative paths', async () => {
const result = await bundle([sourceDirectory], tmpDir.path, declarations, {
basePath: fixturesDir,
configPath: join(sourceDirectory, 'config.json'),
featureFlags: {
edge_functions_produce_eszip: true,
},
})
const generatedFiles = await fs.readdir(tmpDir.path)

Expand Down Expand Up @@ -300,9 +256,6 @@ test('Ignores any user-defined `deno.json` files', async () => {
bundle([join(fixtureDir, 'functions')], tmpDir.path, declarations, {
basePath: fixturesDir,
configPath: join(fixtureDir, 'functions', 'config.json'),
featureFlags: {
edge_functions_produce_eszip: true,
},
}),
).not.toThrow()

Expand All @@ -322,9 +275,6 @@ test('Processes a function that imports a custom layer', async () => {
const result = await bundle([sourceDirectory], tmpDir.path, declarations, {
basePath: fixturesDir,
configPath: join(sourceDirectory, 'config.json'),
featureFlags: {
edge_functions_produce_eszip: true,
},
})
const generatedFiles = await fs.readdir(tmpDir.path)

Expand Down Expand Up @@ -357,9 +307,6 @@ test('Loads declarations and import maps from the deploy configuration', async (
const result = await bundle(directories, tmpDir.path, declarations, {
basePath: fixtureDir,
configPath: join(fixtureDir, '.netlify', 'edge-functions', 'config.json'),
featureFlags: {
edge_functions_produce_eszip: true,
},
})
const generatedFiles = await fs.readdir(tmpDir.path)

Expand Down
48 changes: 1 addition & 47 deletions node/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import type { Bundle } from './bundle.js'
import { FunctionConfig, getFunctionConfig } from './config.js'
import { Declaration, getDeclarationsFromConfig } from './declaration.js'
import { load as loadDeployConfig } from './deploy_config.js'
import { EdgeFunction } from './edge_function.js'
import { FeatureFlags, getFlags } from './feature_flags.js'
import { findFunctions } from './finder.js'
import { bundle as bundleESZIP } from './formats/eszip.js'
import { bundle as bundleJS } from './formats/javascript.js'
import { ImportMap } from './import_map.js'
import { getLogger, LogFunction } from './logger.js'
import { writeManifest } from './manifest.js'
Expand All @@ -31,50 +29,6 @@ interface BundleOptions {
systemLogger?: LogFunction
}

interface BundleFormatOptions {
buildID: string
debug?: boolean
deno: DenoBridge
distDirectory: string
functions: EdgeFunction[]
featureFlags: FeatureFlags
importMap: ImportMap
basePath: string
}

const createBundle = ({
basePath,
buildID,
debug,
deno,
distDirectory,
functions,
importMap,
featureFlags,
}: BundleFormatOptions) => {
if (featureFlags.edge_functions_produce_eszip) {
return bundleESZIP({
basePath,
buildID,
debug,
deno,
distDirectory,
featureFlags,
functions,
importMap,
})
}

return bundleJS({
buildID,
debug,
deno,
distDirectory,
functions,
importMap,
})
}

const bundle = async (
sourceDirectories: string[],
distDirectory: string,
Expand Down Expand Up @@ -126,7 +80,7 @@ const bundle = async (
}

const functions = await findFunctions(sourceDirectories)
const functionBundle = await createBundle({
const functionBundle = await bundleESZIP({
basePath,
buildID,
debug,
Expand Down
4 changes: 0 additions & 4 deletions node/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,6 @@ test('Ignores function paths from the in-source `config` function if the feature
const result = await bundle([internalDirectory, userDirectory], tmpDir.path, declarations, {
basePath: fixturesDir,
configPath: join(internalDirectory, 'config.json'),
featureFlags: {
edge_functions_produce_eszip: true,
},
})
const generatedFiles = await fs.readdir(tmpDir.path)

Expand Down Expand Up @@ -194,7 +191,6 @@ test('Loads function paths from the in-source `config` function', async () => {
configPath: join(internalDirectory, 'config.json'),
featureFlags: {
edge_functions_config_export: true,
edge_functions_produce_eszip: true,
},
})
const generatedFiles = await fs.readdir(tmpDir.path)
Expand Down
1 change: 0 additions & 1 deletion node/feature_flags.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const defaultFlags: Record<string, boolean> = {
edge_functions_cache_deno_dir: false,
edge_functions_config_export: false,
edge_functions_produce_eszip: false,
}

type FeatureFlag = keyof typeof defaultFlags
Expand Down
74 changes: 2 additions & 72 deletions node/formats/javascript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,11 @@ import { pathToFileURL } from 'url'

import { deleteAsync } from 'del'

import { DenoBridge } from '../bridge.js'
import { Bundle, BundleFormat } from '../bundle.js'
import { wrapBundleError } from '../bundle_error.js'
import { EdgeFunction } from '../edge_function.js'
import { ImportMap } from '../import_map.js'
import { wrapNpmImportError } from '../npm_import_error.js'
import type { FormatFunction } from '../server/server.js'
import { getFileHash } from '../utils/sha256.js'

const BOOTSTRAP_LATEST = 'https://637cf7ce9214b300099b3aa8--edge.netlify.com/bootstrap/index-combined.ts'

interface BundleJSOptions {
buildID: string
debug?: boolean
deno: DenoBridge
distDirectory: string
functions: EdgeFunction[]
importMap: ImportMap
}

const bundleJS = async ({
buildID,
debug,
deno,
distDirectory,
functions,
importMap,
}: BundleJSOptions): Promise<Bundle> => {
const stage2Path = await generateStage2({ distDirectory, functions, fileName: `${buildID}-pre.js` })
const extension = '.js'
const jsBundlePath = join(distDirectory, `${buildID}${extension}`)
const flags = [`--import-map=${importMap.toDataURL()}`, '--no-config']

if (!debug) {
flags.push('--quiet')
}

try {
await deno.run(['bundle', ...flags, stage2Path, jsBundlePath], { pipeOutput: true })
} catch (error: unknown) {
throw wrapBundleError(wrapNpmImportError(error), { format: 'javascript' })
}

await fs.unlink(stage2Path)

const hash = await getFileHash(jsBundlePath)

return { extension, format: BundleFormat.JS, hash }
}

const defaultFormatExportTypeError: FormatFunction = (name) =>
`The Edge Function "${name}" has failed to load. Does it have a function as the default export?`

Expand All @@ -66,7 +21,6 @@ interface GenerateStage2Options {
formatExportTypeError?: FormatFunction
formatImportError?: FormatFunction
functions: EdgeFunction[]
type?: 'local' | 'production'
}

const generateStage2 = async ({
Expand All @@ -75,15 +29,11 @@ const generateStage2 = async ({
formatExportTypeError,
formatImportError,
functions,
type = 'production',
}: GenerateStage2Options) => {
await deleteAsync(distDirectory, { force: true })
await fs.mkdir(distDirectory, { recursive: true })

const entryPoint =
type === 'local'
? getLocalEntryPoint(functions, { formatExportTypeError, formatImportError })
: getProductionEntryPoint(functions)
const entryPoint = getLocalEntryPoint(functions, { formatExportTypeError, formatImportError })
const stage2Path = join(distDirectory, fileName)

await fs.writeFile(stage2Path, entryPoint)
Expand Down Expand Up @@ -137,24 +87,4 @@ const getLocalEntryPoint = (
return [bootImport, declaration, ...imports, bootCall].join('\n\n')
}

const getProductionEntryPoint = (functions: EdgeFunction[]) => {
const bootImport = `import { boot } from "${getBootstrapURL()}";`
const lines = functions.map((func, index) => {
const importName = `func${index}`
const exportLine = `"${func.name}": ${importName}`
const url = pathToFileURL(func.path)

return {
exportLine,
importLine: `import ${importName} from "${url}";`,
}
})
const importLines = lines.map(({ importLine }) => importLine).join('\n')
const exportLines = lines.map(({ exportLine }) => exportLine).join(', ')
const exportDeclaration = `const functions = {${exportLines}};`
const defaultExport = 'boot(functions);'

return [bootImport, importLines, exportDeclaration, defaultExport].join('\n\n')
}

export { bundleJS as bundle, generateStage2, getBootstrapURL, getLocalEntryPoint }
export { generateStage2, getBootstrapURL, getLocalEntryPoint }
1 change: 0 additions & 1 deletion node/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ const prepareServer = ({
functions,
formatExportTypeError,
formatImportError,
type: 'local',
})

try {
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/invalid_functions/functions/func1.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export default async () => new NotAResponse('Hello')
export default async () =>
6 changes: 1 addition & 5 deletions test/integration/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@ const bundleFunction = async (bundlerDir) => {

console.log(`Bundling functions at '${functionsDir}'...`)

return await bundle([functionsDir], destPath, [{ function: 'func1', path: '/func1' }], {
featureFlags: {
edge_functions_produce_eszip: true,
},
})
return await bundle([functionsDir], destPath, [{ function: 'func1', path: '/func1' }])
}

const runAssertions = (bundleOutput) => {
Expand Down

0 comments on commit d8f45b1

Please sign in to comment.