Esbuild: How to set all node internal modules and project's dependency modules to external

Created on 24 Aug 2020  Â·  7Comments  Â·  Source: evanw/esbuild

I am a electron developer.
I want to use esbuild to build my code.
and electron's main process code just like a local node project's code.
It should use a lot of node internal modules and third-party modules.
Will it is possible to exclude all of them and just compile the user code?
Thanks

Most helpful comment

AFAICT, setting the {platform: "node"} option will also correctly set all of node's built-ins to be treated as externals.

All 7 comments

Adding some context for clarity.

The web UI code in electron applications can access unbundled Node modules and a few other items directly from the filesystem. Bundlers like webpack support excluding these modules this with a target flag. I am unsure if there is any additional changes beyond excluding modules from bundling / compiling (see example at end).

In a prior question someone asked about excluding modules:

By default esbuild attempts to bundle all module dependencies. If you want to exclude a module dependency, you can use the --external flag like this:

node_modules/esbuild/bin/esbuild --external:fs --bundle ui/index.js --outfile=ui/bundle.js --sourcemap

That will cause the call to require('fs') to be passed through to the output file unmodified.

At any rate, I think this webpack code is the definition where the electron externals are specified (the "main" process), though you only _need_ to bundle the UI code. For that, Webpack uses this from target-electron-renderer:

var webpack = require('webpack');
var JsonpTemplatePlugin = webpack.JsonpTemplatePlugin;
var FunctionModulePlugin = require('webpack/lib/FunctionModulePlugin');
var NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
var ExternalsPlugin = webpack.ExternalsPlugin;
var LoaderTargetPlugin = webpack.LoaderTargetPlugin;

module.exports = function (options) {
  return function webpackTargetElectronRenderer(compiler) {
    compiler.apply(
      new JsonpTemplatePlugin(options.output),
      new FunctionModulePlugin(options.output),
      new NodeTargetPlugin(),
      new ExternalsPlugin('commonjs', [
        'desktop-capturer',
        'electron',
        'ipc',
        'ipc-renderer',
        'native-image',
        'remote',
        'web-frame',
        'clipboard',
        'crash-reporter',
        'screen',
        'shell'
      ]),
      new LoaderTargetPlugin(options.target)
    );
  };
};

So I should set all electron's modules and my dependency modules to external if I use esbuild?
@cloverich
Is that what you mean?

As long as those dependencies are listed in your package.json you can craft a little script like this:

// make.mjs (node LTS - node Current)
import ES from 'esbuild';
import { readFileSync } from 'fs';

const localPkgJson = JSON.parse(readFileSync('./package.json', 'utf-8'));

/** @type ES.BuildOptions */
const SHARED_ESBUILD_OPTIONS = {
  bundle: true,
  entryPoints: ['./src/your-entry-point.ts'],
  external: Object.keys({
    ...(localPkgJson.dependencies || {}),
    ...(localPkgJson.devDependencies || {}),
    ...(localPkgJson.peerDependencies || {})
  })
};

make();

async function make() {
  await ES.build({
    ...SHARED_ESBUILD_OPTIONS,
    format: 'esm',
    outfile: './lib/your-bundled-module.mod.js'
  });
}

@chrstntdd ,Thanks,
Is there some way to find out all node.js internal modules?

On 05/09/2020 04:25, liulun wrote:

@chrstntdd https://github.com/chrstntdd ,Thanks,
Is there some way to find out all node.js internal modules?

Use node's module, like so:

require('module').builtinModules
[
  '_http_agent',       '_http_client',        '_http_common',
  '_http_incoming',    '_http_outgoing',      '_http_server',
  '_stream_duplex',    '_stream_passthrough', '_stream_readable',
  '_stream_transform', '_stream_wrap',        '_stream_writable',
  '_tls_common',       '_tls_wrap',           'assert',
  'async_hooks',       'buffer',              'child_process',
  'cluster',           'console',             'constants',
  'crypto',            'dgram',               'dns',
  'domain',            'events',              'fs',
  'fs/promises',       'http',                'http2',
  'https',             'inspector',           'module',
  'net',               'os',                  'path',
  'perf_hooks',        'process',             'punycode',
  'querystring',       'readline',            'repl',
  'stream',            'string_decoder',      'sys',
  'timers',            'tls',                 'trace_events',
  'tty',               'url',                 'util',
  'v8',                'vm',                  'wasi',
  'worker_threads',    'zlib'
]

AFAICT, setting the {platform: "node"} option will also correctly set all of node's built-ins to be treated as externals.

@chrstntdd Thanks very much!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fannheyward picture fannheyward  Â·  4Comments

OneOfOne picture OneOfOne  Â·  3Comments

tonyhb picture tonyhb  Â·  3Comments

lolychee picture lolychee  Â·  4Comments

iamakulov picture iamakulov  Â·  4Comments