最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Can't access exported functions in bundled .js file using esbuild - Stack Overflow

programmeradmin3浏览0评论

I want to create a library using TypeScript. It should be available for Node and Browser environments.

I started with the package.json file and installed esbuild as a dependency and typescript as a dev dependency. The result is

{
  "name": "my-lib",
  "version": "1.0.0",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "build": "tsc && esbuild ./dist/lib/index.js --bundle --minify --sourcemap --outfile=./bundle/index.js"
  },
  "dependencies": {
    "esbuild": "0.14.36"
  },
  "devDependencies": {
    "typescript": "4.6.3"
  }
}

The tsconfig.json file contains

{
  "pilerOptions": {
    "baseUrl": ".",
    "declaration": true,
    "esModuleInterop": true,
    "lib": [ "dom", "esnext" ],
    "module": "monjs",
    "outDir": "dist",
    "resolveJsonModule": true,
    "strict": true,
    "target": "es2019",
  },
  "include": [
    "./**/*.ts"
  ],
  "exclude": [
    "./dist"
  ]
}

Inside the root directory I have a lib directory holding an index.ts file which exports all the "public" functions, e.g.

const sum = function (a: number, b: number): number { return a + b; };

export { sum };

Besides that I have a test directory right next to the lib directory, holding some .ts files. I want to test the build script and added the following index.html to the root directory

<!DOCTYPE html>
<html>
    <head>
      <script type='text/javascript' src='./bundle/index.js'></script>
    </head>
    <body>
        <div>
            Loading bundle...
        </div>
    </body>
</html>

<script type="text/javascript">
window.onload = () => {
  console.log('ready');

  const result = sum(1, 2);

  console.log({ result });

  const anotherResult = window.sum(1, 2);

  console.log({ anotherResult });
};
</script>

Unfortunately I get an Uncaught ReferenceError because it is not able to find the function sum. The folder structure before running npm install && npm run build is

Does someone know what's wrong or missing here?

I want to create a library using TypeScript. It should be available for Node and Browser environments.

I started with the package.json file and installed esbuild as a dependency and typescript as a dev dependency. The result is

{
  "name": "my-lib",
  "version": "1.0.0",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "build": "tsc && esbuild ./dist/lib/index.js --bundle --minify --sourcemap --outfile=./bundle/index.js"
  },
  "dependencies": {
    "esbuild": "0.14.36"
  },
  "devDependencies": {
    "typescript": "4.6.3"
  }
}

The tsconfig.json file contains

{
  "pilerOptions": {
    "baseUrl": ".",
    "declaration": true,
    "esModuleInterop": true,
    "lib": [ "dom", "esnext" ],
    "module": "monjs",
    "outDir": "dist",
    "resolveJsonModule": true,
    "strict": true,
    "target": "es2019",
  },
  "include": [
    "./**/*.ts"
  ],
  "exclude": [
    "./dist"
  ]
}

Inside the root directory I have a lib directory holding an index.ts file which exports all the "public" functions, e.g.

const sum = function (a: number, b: number): number { return a + b; };

export { sum };

Besides that I have a test directory right next to the lib directory, holding some .ts files. I want to test the build script and added the following index.html to the root directory

<!DOCTYPE html>
<html>
    <head>
      <script type='text/javascript' src='./bundle/index.js'></script>
    </head>
    <body>
        <div>
            Loading bundle...
        </div>
    </body>
</html>

<script type="text/javascript">
window.onload = () => {
  console.log('ready');

  const result = sum(1, 2);

  console.log({ result });

  const anotherResult = window.sum(1, 2);

  console.log({ anotherResult });
};
</script>

Unfortunately I get an Uncaught ReferenceError because it is not able to find the function sum. The folder structure before running npm install && npm run build is

Does someone know what's wrong or missing here?

Share Improve this question asked Apr 14, 2022 at 9:12 user17298649user17298649 5
  • Why "module": "monjs" if you want to use the library in a browser? – Bergi Commented Apr 18, 2022 at 23:40
  • @Bergi this package should run inside Node and Browser environments. Should I use "module": "umd" instead? – user17298649 Commented Apr 19, 2022 at 11:36
  • Yes, if you want to build a file that can be distributed to either, UMD will be necessary. Or you distribute two separate files in the package, one for node and one for browsers. – Bergi Commented Apr 19, 2022 at 12:52
  • Also it's not really clear what you're trying to achieve here. Why is esbuild not a dev dependency? Why do you want to bundle your library at all, shouldn't that be done by the application that uses the library? – Bergi Commented Apr 19, 2022 at 12:53
  • how are you bundling function using esbuild? – Yilmaz Commented Apr 21, 2022 at 22:30
Add a ment  | 

3 Answers 3

Reset to default 3

If you want include your bundled javascript into html file via script tag (as in your example), you should add sum variable to page global variables scope like that:

const sum = function (a: number, b: number): number { return a + b; };
window.sum = sum;
// or `globalThis.sum = sum;`

Defining variable in global page scope makes it sure that no minification or renaming processes in bundler will break your app.

It would be better for you to check the concept of Commonjs and ECMAScript Module(ESM) before working. The pilerOptions.module in tsconfig.json is Commonjs, which is the bundling method used by Node.js. This does not work with browser. This is because the browser does not have the require method which can recognize the exports object and the module object, which is available globally in Node.js.

Therefore, when creating modules that support browsers, usually bundle them in UMD format using Webpack. If you don't support older browsers, you can think of bundling in the ESM way, even without a Webpack.

First, modify tsconfig.json as follows:

{
  "pilerOptions": {
    "baseUrl": ".",
    "declaration": true,
    "esModuleInterop": true,
    "lib": [ "dom", "esnext" ],
    "module": "esnext", // update
    "outDir": "dist",
    // "resolveJsonModule": true,
    "strict": true,
    "target": "es2019",
  },
  "include": [
    "./**/*.ts"
  ],
  "exclude": [
    "./dist"
  ]
}

Next, modify the following HTML as follows:

<!DOCTYPE html>
<html>
  <head>
    <script type="module">
      import {sum} from './dist/index.js';
    
      window.onload = () => {
        console.log('ready');
        const result = sum(1, 2);
        console.log({ result });
        const anotherResult = sum(1, 2);
        console.log({ anotherResult });
      };
    </script>
  </head>
  <body>
      <div>
        Loading bundle...
      </div>
  </body>
</html>

You can create library that work in your browser after npm install && npm run build.

If your library can be imported from another bundler (like a webpack), you want it to work in a browser, and you want to implement it using tsc only, see the following link.

Your code is fine, the problem is that you are using bad export. Exports a function that is never used and that is why the error. Then I show you how to solve this.

You must first bear in mind that nothing is exported in the index.ts. Rather the index.ts receives functions from other JS modules. Then create a Sum.TS file that will be a module where you will write the following code:

sum.ts

const sum = function (a: number, b: number): number { return a + b; };

export { sum };

In Index.ts imports the sum function of the module sum.ts the file must remain like this:

index.ts

import { sum } from "./sum";

sum

In this way you already have the sum function available to use in the index.html.

When you export functions these are not available in the piled code. Only imports are available in the piled code.

If you want to use the index.ts to store public functions the code should be like this:

const sum = function (a: number, b: number): number { return a + b; };
sum

update

Just change your index.ts to this:

 const sum = function (a: number, b: number): number { return a + b; };
    sum

and your index.html to this:

<!DOCTYPE html>
<html>
    <head>
      <script type='text/javascript' src='./bundle/index.js'></script>
    </head>
    <body>
        <div>
            Loading bundle...
        </div>
    </body>
</html>

<script type="text/javascript">
window.onload = () => {
  console.log('ready');

  const result = sum(1, 2);

  console.log({ result });

  const anotherResult = sum(1, 2);

  console.log({ anotherResult });
};
</script>

Don't export functions in index.ts as you won't be able to do them in the browser.

发布评论

评论列表(0)

  1. 暂无评论