unjs / unenv

🕊️ Convert javaScript code to be runtime agnostic
MIT License
390 stars 21 forks source link

Can this tool be used with esbuild? #32

Closed ezmiller closed 3 months ago

ezmiller commented 2 years ago

I tried to use this tool with esbuild to build a Cloudflare worker. I need to use a library that has dependencies on node libs like fs.

I tried:

import buildAlias form 'esbuild-plugin-alias`
import { env, nodeless } from 'unenv'

const { alias } = env(nodeless)

async function main() {
  ...
  const result = await build({
    ...
    plugins[buildAlias(alias)],
    ...
  })
}

main()

I ended up getting a bunch of warnings from esbuild b/c the esbuild requires absolute paths and the paths supplied in the nodeless presets are relative.

Any thoughts about how to get this to work?

SegaraRai commented 2 years ago

It can be used by resolving it to an absolute path using require.resolve. We currently use a plugin like this one. (ESM style. may need some rewrite for CJS)

import { createRequire } from 'module';
import { join } from 'path';
import { build } from 'esbuild';
import { nodeless } from 'unenv';

/** @type {(plugin: import('esbuild').Plugin) => import('esbuild').Plugin} */
const definePlugin = (plugin) => plugin;

const nodelessPlugin = definePlugin({
  name: 'unenv-nodeless',
  setup(build) {
    const alias = nodeless.alias;
    const re = new RegExp(`^(${Object.keys(alias).join('|')})$`); // this should be escaped

    const require = createRequire(import.meta.url);
    const aliasAbsolute = Object.fromEntries(
      Object.entries(alias).map(([key, value]) => [
        key,
        require.resolve(value).replace(/\.cjs$/, '.mjs'),
      ])
    );

    build.onResolve(
      {
        filter: re,
      },
      (args) => {
        const result = aliasAbsolute[args.path];
        return result ? { path: result } : undefined;
      }
    );
  },
});

build({
  entryPoints: ['./src/index.ts'],
  outfile: 'dist/index_dev.js',
  platform: 'browser',
  bundle: true,
  format: 'esm',
  logLevel: 'info',
  plugins: [nodelessPlugin],
});
pi0 commented 3 months ago

We plan to add an unplugin to unenv for easier integration. Lets track via #263