@aziontech/opennextjs-azion
Version:
Azion builder for next apps
57 lines (56 loc) • 2.55 kB
JavaScript
/**
* This code was originally copied and modified from the @opennextjs/cloudflare repository.
* Significant changes have been made to adapt it for use with Azion.
*/
/**
* ESBuild plugin to handle optional dependencies.
*
* Optional dependencies might be installed by the application to support optional features.
*
* When an optional dependency is installed, it must be inlined in the bundle.
* When it is not installed, the plugin swaps it for a throwing implementation.
*
* The plugin uses ESBuild built-in resolution to check if the dependency is installed.
*/
export function handleOptionalDependencies(dependencies) {
// Regex matching either a full module ("module") or a prefix ("module/...")
const filter = new RegExp(`^(${dependencies.flatMap((name) => [`${name}$`, String.raw `${name}/`]).join("|")})`);
const name = "optional-deps";
const marker = {};
const nsMissingDependency = `${name}-missing-dependency`;
return {
name,
setup: async (build) => {
build.onResolve({ filter }, async ({ path, pluginData, ...options }) => {
// Use ESBuild to resolve the dependency.
// Because the plugin asks ESBuild to resolve the path we just received,
// ESBuild will ask this plugin again.
// We use a marker in the pluginData to break the loop.
if (pluginData === marker) {
return {};
}
const result = await build.resolve(path, {
...options,
pluginData: marker,
});
// ESBuild reports error when the dependency is not installed.
// In such a case the OnLoad hook will inline a throwing implementation.
if (result.errors.length > 0) {
return {
path: `/${path}`,
namespace: nsMissingDependency,
pluginData: { name: path },
};
}
// Returns ESBuild resolution information when the dependency is installed.
return result;
});
// Replaces missing dependency with a throwing implementation.
build.onLoad({ filter: /.*/, namespace: nsMissingDependency }, ({ pluginData }) => {
return {
contents: `throw new Error('Missing optional dependency "${pluginData.name}"')`,
};
});
},
};
}