From d67ae846103c42ff0464c578813749940326e8ba Mon Sep 17 00:00:00 2001 From: Arsh <69170106+lilnasy@users.noreply.github.com> Date: Thu, 15 Jun 2023 19:50:35 +0530 Subject: [PATCH] Node built-in modules support for Deno adapter (#7288) * feature(deno adapter): allow built-in node modules * Add changeset * format --- .changeset/modern-lobsters-sparkle.md | 5 ++ .github/workflows/ci.yml | 2 +- packages/integrations/deno/src/index.ts | 70 ++++++++++++++++++- .../integrations/deno/test/basics.test.ts | 6 ++ .../basics/src/pages/nodecompat.astro | 15 ++++ 5 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 .changeset/modern-lobsters-sparkle.md create mode 100644 packages/integrations/deno/test/fixtures/basics/src/pages/nodecompat.astro diff --git a/.changeset/modern-lobsters-sparkle.md b/.changeset/modern-lobsters-sparkle.md new file mode 100644 index 000000000..057afdc04 --- /dev/null +++ b/.changeset/modern-lobsters-sparkle.md @@ -0,0 +1,5 @@ +--- +'@astrojs/deno': minor +--- + +The deno adapter now supports npm package that require built-in node modules. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 970dc1d7c..17848dfd9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -148,7 +148,7 @@ jobs: - name: Use Deno uses: denoland/setup-deno@v1 with: - deno-version: v1.26.1 + deno-version: v1.34.1 - name: Install dependencies run: pnpm install diff --git a/packages/integrations/deno/src/index.ts b/packages/integrations/deno/src/index.ts index 7e4a520ca..8b1f38959 100644 --- a/packages/integrations/deno/src/index.ts +++ b/packages/integrations/deno/src/index.ts @@ -21,6 +21,59 @@ const SHIM = `globalThis.process = { };`; const DENO_VERSION = `0.177.0`; +// REF: https://github.com/denoland/deno/tree/main/ext/node/polyfills +const COMPATIBLE_NODE_MODULES = [ + 'assert', + 'assert/strict', + 'async_hooks', + 'buffer', + 'child_process', + 'cluster', + 'console', + 'constants', + 'crypto', + 'dgram', + 'diagnostics_channel', + 'dns', + 'events', + 'fs', + 'fs/promises', + 'http', + // 'http2', + 'https', + 'inspector', + 'module', + 'net', + 'os', + 'path', + 'path/posix', + 'path/win32', + 'perf_hooks', + 'process', + 'punycode', + 'querystring', + 'readline', + 'repl', + 'stream', + 'stream/promises', + 'stream/web', + 'string_decoder', + 'sys', + 'timers', + 'timers/promises', + // 'tls', + 'trace_events', + 'tty', + 'url', + 'util', + 'util/types', + // 'v8', + // 'vm', + // 'wasi', + // 'webcrypto', + 'worker_threads', + 'zlib', +]; // We shim deno-specific imports so we can run the code in Node // to prerender pages. In the final Deno build, this import is @@ -51,6 +104,14 @@ const denoImportsShimPlugin = { }, }; +const denoRenameNodeModulesPlugin = { + name: '@astrojs/esbuild-rename-node-modules', + setup(build: esbuild.PluginBuild) { + const filter = new RegExp(COMPATIBLE_NODE_MODULES.map((mod) => `(^${mod}$)`).join('|')); + build.onResolve({ filter }, (args) => ({ path: 'node:' + args.path, external: true })); + }, +}; + export default function createIntegration(args?: Options): AstroIntegration { let _buildConfig: BuildConfig; let _vite: any; @@ -89,7 +150,7 @@ export default function createIntegration(args?: Options): AstroIntegration { } } vite.ssr = { - noExternal: true, + noExternal: COMPATIBLE_NODE_MODULES, }; if (Array.isArray(vite.build.rollupOptions.external)) { @@ -114,8 +175,11 @@ export default function createIntegration(args?: Options): AstroIntegration { allowOverwrite: true, format: 'esm', bundle: true, - external: ['@astrojs/markdown-remark'], - plugins: [denoImportsShimPlugin], + external: [ + ...COMPATIBLE_NODE_MODULES.map((mod) => `node:${mod}`), + '@astrojs/markdown-remark', + ], + plugins: [denoImportsShimPlugin, denoRenameNodeModulesPlugin], banner: { js: SHIM, }, diff --git a/packages/integrations/deno/test/basics.test.ts b/packages/integrations/deno/test/basics.test.ts index 381343d06..9e4174506 100644 --- a/packages/integrations/deno/test/basics.test.ts +++ b/packages/integrations/deno/test/basics.test.ts @@ -104,6 +104,12 @@ Deno.test({ assertEquals(h1!.innerText, 'test'); }); + await t.step('node compatibility', async () => { + const resp = await fetch(new URL('/nodecompat', app.url)); + assertEquals(resp.status, 200); + await resp.text(); + }); + app.stop(); }, }); diff --git a/packages/integrations/deno/test/fixtures/basics/src/pages/nodecompat.astro b/packages/integrations/deno/test/fixtures/basics/src/pages/nodecompat.astro new file mode 100644 index 000000000..35c47793f --- /dev/null +++ b/packages/integrations/deno/test/fixtures/basics/src/pages/nodecompat.astro @@ -0,0 +1,15 @@ +--- +// unprefixed node built-in module +import path from 'path' + +// prefixed node built-in module +import os from 'node:os' +--- +
+Go to my file +{os.arch()}
+Everything went fine.
+ \ No newline at end of file