Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bun build --target node injects incorrect require function #6168

Closed
edison-manrique opened this issue Sep 29, 2023 · 14 comments · Fixed by #8057
Closed

bun build --target node injects incorrect require function #6168

edison-manrique opened this issue Sep 29, 2023 · 14 comments · Fixed by #8057
Labels
bug Something isn't working bundler Something to do with the bundler

Comments

@edison-manrique
Copy link

edison-manrique commented Sep 29, 2023

What version of Bun is running?

1.0.3+25e69c71e70ac8a0a88f9cf15b4057bd7b2a633a

What platform is your computer?

Darwin 21.6.0 x86_64 i386

What steps can reproduce the bug?

edison@EMC3 localtunnel % bun build app.ts --outdir . --target node 

  ./app.js  92.64 KB

[57ms] bundle 43 modules
edison@EMC3 localtunnel % node -v
v20.8.0
edison@EMC3 localtunnel % node app.js                               
file:///Users/edison/Documents/webserver/git/localtunnel/app.js:19
  return import.meta.require(id);
                     ^

TypeError: (intermediate value).require is not a function
    at __require (file:///Users/edison/Documents/webserver/git/localtunnel/app.js:19:22)
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.js:2622:19
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.js:17:45
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.js:2744:16
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.js:17:45
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.js:2758:34
    at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
    at async loadESM (node:internal/process/esm_loader:34:7)
    at async handleMainPromise (node:internal/modules/run_main:66:12)

Node.js v20.8.0

What is the expected behavior?

edison@EMC3 localtunnel % bun app.js
Ingresa el puerto de tu servidor localhost: 

What do you see instead?

file:///Users/edison/Documents/webserver/git/localtunnel/app.js:19
  return import.meta.require(id);
                     ^

TypeError: (intermediate value).require is not a function

Additional information

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getProtoOf = Object.getPrototypeOf;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __toESM = (mod, isNodeMode, target) => {
  target = mod != null ? __create(__getProtoOf(mod)) : {};
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
  for (let key of __getOwnPropNames(mod))
    if (!__hasOwnProp.call(to, key))
      __defProp(to, key, {
        get: () => mod[key],
        enumerable: true
      });
  return to;
};
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __require = (id) => {
  return import.meta.require(id);
};
@edison-manrique edison-manrique added the bug Something isn't working label Sep 29, 2023
@aquapi
Copy link
Contributor

aquapi commented Sep 29, 2023

@edi-manrique Try changing the extension to .mjs and run it

@edison-manrique
Copy link
Author

edison@EMC3 localtunnel % node app.mjs
file:///Users/edison/Documents/webserver/git/localtunnel/app.mjs:19
  return import.meta.require(id);
                     ^

TypeError: (intermediate value).require is not a function
    at __require (file:///Users/edison/Documents/webserver/git/localtunnel/app.mjs:19:22)
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.mjs:2622:19
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.mjs:17:45
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.mjs:2744:16
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.mjs:17:45
    at file:///Users/edison/Documents/webserver/git/localtunnel/app.mjs:2758:34
    at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
    at async loadESM (node:internal/process/esm_loader:34:7)
    at async handleMainPromise (node:internal/modules/run_main:66:12)

Node.js v20.8.0
edison@EMC3 localtunnel % 

@fradinni
Copy link

fradinni commented Sep 29, 2023

@edi-manrique I had the same issue, here is a workaround to make it work with NodeJS (found in this comment on the following ticket #5707)

You have to add this line on top of your generated/built JS file:

import { createRequire as createImportMetaRequire } from "module"; import.meta.require ||= (id) => createImportMetaRequire(import.meta.url)(id);

I wrote a custom build.js file to automate this:

import path from 'path';
import fs from 'fs';

// NodeJS Build
const NODE_FIX = 'import { createRequire as createImportMetaRequire } from "module"; import.meta.require ||= (id) => createImportMetaRequire(import.meta.url)(id);\n';
const BUILD_DIR = 'build';
const nodeBuild = await Bun.build({
    entrypoints: ['./index.ts'],
    target: 'node',
    minify: true,
    naming: "[dir]/[name].[ext]"
});

// Write output files
for (const result of nodeBuild.outputs) {
    const fileContent = NODE_FIX + await result.text();
    const destDir = path.join(import.meta.dir, BUILD_DIR);
    const dest = path.join(destDir, result.path);
    fs.existsSync(destDir) || fs.mkdirSync(destDir);
    Bun.write(dest, fileContent);
}

Then you just have to run:

bun run build.js

Adapt it to your needs, hope it will help.

@Electroid Electroid added the bundler Something to do with the bundler label Sep 29, 2023
@mathiasrw
Copy link
Contributor

mathiasrw commented Oct 4, 2023

To automate adding

import { createRequire as createImportMetaRequire } from "module"; import.meta.require ||= (id) => createImportMetaRequire(import.meta.url)(id);

to the generated file while considering hashbangs, you can add this to your scripts in package.json

"postbuild": "npx rexreplace '^(#!.+\\n)?' '$1import { createRequire as createImportMetaRequire } from \'module\'; import.meta.require ||= (id) => createImportMetaRequire(import.meta.url)(id);\\n' -GM path/to/YOUR_FILE.js",

@soeasyjx
Copy link

soeasyjx commented Oct 9, 2023

I have the same problem, is there a better solution

@fradinni
Copy link

fradinni commented Oct 9, 2023

@soeasyjx I don't think so.

@Jarred-Sumner Jarred-Sumner changed the title bun build --target node error bun build --target node injects incorrect require function Oct 9, 2023
@augustoapg
Copy link

To automate adding

import { createRequire as createImportMetaRequire } from "module"; import.meta.require ||= (id) => createImportMetaRequire(import.meta.url)(id);

to the generated file while considering hashbangs, you can add this to your scripts in package.json

"postbuild": "npx rexreplace '^(#!.+\\n)?' '$1import { createRequire as createImportMetaRequire } from 'module'; import.meta.require ||= (id) => createImportMetaRequire(import.meta.url)(id);\\n' -GM path/to/YOUR_FILE.js",

@mathiasrw really liked the workaround, but I am getting this issue for some reason...

import { createRequire as createImportMetaRequire } from module; import.meta.require ||= (id) => createImportMetaRequire(import.meta.url)(id);
                                                         ^^^^^^

SyntaxError: Unexpected identifier
    at ESMLoader.moduleStrategy (node:internal/modules/esm/translators:117:18)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:337:14)
    at async link (node:internal/modules/esm/module_job:70:21)

Am I missing something? I'm very new to Bun, and a bit new to bundlers in general.

@fradinni
Copy link

@augustoapg, escape quotes arround 'module' ?

'$1import { createRequire as createImportMetaRequire } from \'module\'; ....'

@mathiasrw
Copy link
Contributor

mathiasrw commented Oct 13, 2023

@fradinni ohhh - good point. I have updated the example.

@augustoapg
Copy link

@fradinni peerfect, that did it! Thank you so much! And thanks @mathiasrw again for the clever solution!

@soeasyjx
Copy link

soeasyjx commented Oct 16, 2023

I reported this error after executing bun build packaging and running cli

package.json

{
 "start": "bun run src/index.ts",
 "build":"bun build src/index.ts --outdir dist --target node"
}
const file = Bun.file(dir);
             ^

ReferenceError: Bun is not defined

@mathiasrw
Copy link
Contributor

@soeasyjx Please make new issues when you encounter a new issue.

also: You cant use Bun. when running node. is only available in Bun. Use fs for node instead

mathix420 added a commit to mathix420/sb-datasource-to-i18n-json that referenced this issue Nov 15, 2023
@iamacup
Copy link

iamacup commented Dec 11, 2023

I am experiencing this as output from bun build with --target browser as the target when i have a dependency on this library: "@slate-serializers/html": "^2.1.2",

var __defProp = Object.defineProperty;
var __getProtoOf = Object.getPrototypeOf;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __toESM = (mod, isNodeMode, target) => {
  target = mod != null ? __create(__getProtoOf(mod)) : {};
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
  for (let key of __getOwnPropNames(mod))
    if (!__hasOwnProp.call(to, key))
      __defProp(to, key, {
        get: () => mod[key],
        enumerable: true
      });
  return to;
};
var __toCommonJS = (from) => {
  const moduleCache = __toCommonJS.moduleCache ??= new WeakMap;
  var cached = moduleCache.get(from);
  if (cached)
    return cached;
  var to = __defProp({}, "__esModule", { value: true });
  var desc = { enumerable: false };
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key))
        __defProp(to, key, {
          get: () => from[key],
          enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
        });
  }
  moduleCache.set(from, to);
  return to;
};
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __require = (id) => {
  return import.meta.require(id);
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {
      get: all[name],
      enumerable: true,
      configurable: true,
      set: (newValue) => all[name] = () => newValue
    });
};

the actual __require function seems to never be used in the rest of the generated output. To fix this we wrote a custom watch step that comments the return import.meta.require(id); line out of the dist after it changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working bundler Something to do with the bundler
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants