简体   繁体   English

无法使用 esbuild 访问 bundled.js 文件中的导出函数

[英]Can't access exported functions in bundled .js file using esbuild

I want to create a library using TypeScript. It should be available for Node and Browser environments.我想使用 TypeScript 创建一个库。它应该可用于节点和浏览器环境。

I started with the package.json file and installed esbuild as a dependency and typescript as a dev dependency.我从 package.json 文件开始,将esbuild安装为依赖项,将typescript安装为开发依赖项。 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 tsconfig.json 文件包含

{
  "compilerOptions": {
    "baseUrl": ".",
    "declaration": true,
    "esModuleInterop": true,
    "lib": [ "dom", "esnext" ],
    "module": "commonjs",
    "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, eg在根目录中,我有一个 lib 目录,其中包含一个导出所有“公共”函数的 index.ts 文件,例如

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.除此之外,我在 lib 目录旁边有一个测试目录,其中包含一些 .ts 文件。 I want to test the build script and added the following index.html to the root directory我想测试build脚本并将以下 index.html 添加到根目录

<!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 .不幸的是,我得到了一个Uncaught ReferenceError因为它无法找到 function sum The folder structure before running npm install && npm run build is运行npm install && npm run build之前的文件夹结构是

在此处输入图像描述

Does someone know what's wrong or missing here?有人知道这里出了什么问题或遗漏了什么吗?

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:如果您想通过脚本标记将捆绑的 javascript 包含到 html 文件中(如您的示例所示),您应该将sum变量添加到页面全局变量 scope 中,如下所示:

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.在全局页面 scope 中定义变量可确保捆绑器中的缩小或重命名过程不会破坏您的应用程序。

It would be better for you to check the concept of Commonjs and ECMAScript Module(ESM) before working.你最好在工作之前检查一下 Commonjs 和 ECMAScript Module(ESM) 的概念。 The compilerOptions.module in tsconfig.json is Commonjs, which is the bundling method used by Node.js. This does not work with browser. tsconfig.json中的compilerOptions.moduletsconfig.json的,是Node.js使用的bundling方式,这个对浏览器不起作用。 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.这是因为浏览器没有require方法可以识别exports object和Node.js全局可用的module object。

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.因此,在创建支持浏览器的模块时,通常使用Webpack打包成UMD格式,如果不支持旧版浏览器,可以考虑用ESM方式打包,甚至不用Webpack。

First, modify tsconfig.json as follows:首先修改tsconfig.json如下:

{
  "compilerOptions": {
    "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:接下来修改下面的HTML如下:

<!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 .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 .如果您的库可以从另一个捆绑器(如 webpack)导入,您希望它在浏览器中工作,并且您希望仅使用 tsc 来实现它,请参阅以下链接

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.导出从未使用过的 function,这就是错误的原因。 Then I show you how to solve this.然后我告诉你如何解决这个问题。

You must first bear in mind that nothing is exported in the index.ts.您必须首先记住,index.ts 中没有导出任何内容。 Rather the index.ts receives functions from other JS modules.相反,index.ts 从其他 JS 模块接收函数。 Then create a Sum.TS file that will be a module where you will write the following code:然后创建一个 Sum.TS 文件,该文件将成为一个模块,您将在其中编写以下代码:

sum.ts求和.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 中导入模块 sum.ts 的总和 function 文件必须保持如下所示:

index.ts索引.ts

import { sum } from "./sum";

sum

In this way you already have the sum function available to use in the index.html.通过这种方式,您已经拥有可用于 index.html 的总和 function。

When you export functions these are not available in the compiled code.当您导出函数时,这些在编译代码中不可用。 Only imports are available in the compiled code.编译后的代码中只有导入可用。

If you want to use the index.ts to store public functions the code should be like this:如果你想使用 index.ts 来存储公共函数,代码应该是这样的:

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

update更新

Just change your index.ts to this:只需将您的 index.ts 更改为:

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

and your index.html to this:和你的 index.html 到这个:

<!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.不要在 index.ts 中导出函数,因为您将无法在浏览器中执行它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法导入捆绑文件 - Can't import bundled file 如何使用其他JavaScript文件中的新类访问我的createjs导出的js文件? - How can i access my createjs exported js file using a new class in a other javascript file? X [错误] [plugin esbuild-style-plugin] E:\...\postcss.config.js 的 PostCSS 配置文件无法加载 - X [ERROR] [plugin esbuild-style-plugin] PostCSS config file at E:\...\postcss.config.js can't load esbuild 不包括 HTML 调用的 JS 函数 - esbuild Not Including JS Functions Called by HTML 无法访问捆绑在同一Browserify捆绑包中的模块之间的功能? - Can not access functions between modules bundled into the same Browserify bundle? 如何将这个 esbuild CLI 语句翻译成 JS 文件 - How to translate this esbuild CLI sentence to JS file 如何使用 GraalVM 从 Java 访问 JS 导出的模块 object? - How can I access a JS-exported module object from Java using GraalVM? 如何使用 jest 访问导出函数的对象以进行单元测试 - How to access objects of exported functions for unit testing using jest 无法在 webpack 3 中设置捆绑文件的自定义文件命名 - can't set custom file naming of bundled files in webpack 3 为什么我不能使用webpack捆绑文件中的类? - Why can't I use a class from webpack bundled file?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM