[英]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.module
是tsconfig.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 文件,该文件将成为一个模块,您将在其中编写以下代码:
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 文件必须保持如下所示:
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
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.