@esmx/import 3.0.0-rc.18 → 3.0.0-rc.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +134 -0
- package/README.zh-CN.md +134 -0
- package/dist/import-loader.d.ts +0 -3
- package/dist/import-loader.mjs +5 -1
- package/dist/import-vm.d.ts +0 -3
- package/dist/import-vm.mjs +0 -2
- package/package.json +8 -9
- package/src/import-loader.ts +6 -5
- package/src/import-vm.ts +0 -5
package/LICENSE
CHANGED
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://www.esmnext.com/logo.svg?t=2025" width="120" alt="Esmx Logo" />
|
|
3
|
+
<h1>@esmx/import</h1>
|
|
4
|
+
|
|
5
|
+
<div>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@esmx/import">
|
|
7
|
+
<img src="https://img.shields.io/npm/v/@esmx/import.svg" alt="npm version" />
|
|
8
|
+
</a>
|
|
9
|
+
<a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
|
|
10
|
+
<img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
|
|
11
|
+
</a>
|
|
12
|
+
<a href="https://www.esmnext.com/coverage/">
|
|
13
|
+
<img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://nodejs.org/">
|
|
16
|
+
<img src="https://img.shields.io/node/v/@esmx/import.svg" alt="node version" />
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://bundlephobia.com/package/@esmx/import">
|
|
19
|
+
<img src="https://img.shields.io/bundlephobia/minzip/@esmx/import" alt="size" />
|
|
20
|
+
</a>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<p>Node.js server-side implementation of Import Maps for the Esmx framework</p>
|
|
24
|
+
|
|
25
|
+
<p>
|
|
26
|
+
English | <a href="https://github.com/esmnext/esmx/blob/master/packages/import/README.zh-CN.md">中文</a>
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## 🚀 Features
|
|
31
|
+
|
|
32
|
+
- **Dual Implementation** - VM mode for development and Loader mode for production
|
|
33
|
+
- **Hot Reload Support** - VM mode supports multiple creation for development flexibility
|
|
34
|
+
- **High Performance** - Loader mode optimized for production deployment
|
|
35
|
+
- **Node.js Focused** - Specifically designed for Node.js server-side environments
|
|
36
|
+
- **TypeScript Ready** - Full TypeScript support with excellent type safety
|
|
37
|
+
- **ESM Standards** - Fully compliant with Import Maps specification
|
|
38
|
+
|
|
39
|
+
## 📦 Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @esmx/import
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 🚀 Quick Start
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { createVmImport } from '@esmx/import';
|
|
49
|
+
import { pathToFileURL } from 'node:url';
|
|
50
|
+
|
|
51
|
+
const vmImport = createVmImport(baseURL, importMap);
|
|
52
|
+
const module = await vmImport('my-app/src/utils', import.meta.url);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 📖 Mode Comparison
|
|
56
|
+
|
|
57
|
+
`@esmx/import` provides two different Import Maps implementation approaches:
|
|
58
|
+
|
|
59
|
+
| Feature | VM Mode | Loader Mode |
|
|
60
|
+
|---------|---------|-------------|
|
|
61
|
+
| **Function** | `createVmImport()` | `createLoaderImport()` |
|
|
62
|
+
| **Environment** | Development | Production |
|
|
63
|
+
| **Hot Reload** | ✅ Supports multiple creation | ❌ Can only be created once |
|
|
64
|
+
| **Performance** | Relatively slower | High performance |
|
|
65
|
+
| **Isolation** | Fully isolated VM environment | Uses Node.js native Loader |
|
|
66
|
+
| **Debugging** | Easy for development debugging | Suitable for production deployment |
|
|
67
|
+
|
|
68
|
+
## 🔧 Usage Examples
|
|
69
|
+
|
|
70
|
+
### VM Mode (Development)
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { createVmImport } from '@esmx/import';
|
|
74
|
+
import { pathToFileURL } from 'node:url';
|
|
75
|
+
|
|
76
|
+
const baseURL = pathToFileURL('/project');
|
|
77
|
+
const importMap = {
|
|
78
|
+
imports: {
|
|
79
|
+
'my-app/src/utils': '/project/src/utils.mjs'
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const vmImport = createVmImport(baseURL, importMap);
|
|
84
|
+
const module = await vmImport('my-app/src/utils', import.meta.url);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Loader Mode (Production)
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { createLoaderImport } from '@esmx/import';
|
|
91
|
+
import { pathToFileURL } from 'node:url';
|
|
92
|
+
|
|
93
|
+
const baseURL = pathToFileURL('/app/dist/server');
|
|
94
|
+
const importMap = {
|
|
95
|
+
imports: {
|
|
96
|
+
'my-app/src/utils': '/app/dist/server/my-app/src/utils.mjs'
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const loaderImport = createLoaderImport(baseURL, importMap);
|
|
101
|
+
const module = await loaderImport('my-app/src/utils');
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 📚 API Reference
|
|
105
|
+
|
|
106
|
+
### createVmImport(baseURL, importMap?)
|
|
107
|
+
Creates a VM-based import function with hot reload support.
|
|
108
|
+
```typescript
|
|
109
|
+
const vmImport = createVmImport(baseURL, importMap);
|
|
110
|
+
const module = await vmImport(specifier, parent, sandbox?, options?);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### createLoaderImport(baseURL, importMap?)
|
|
114
|
+
Creates a Loader-based import function with high performance, can only be created once.
|
|
115
|
+
```typescript
|
|
116
|
+
const loaderImport = createLoaderImport(baseURL, importMap);
|
|
117
|
+
const module = await loaderImport(specifier);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### ImportMap Format
|
|
121
|
+
```typescript
|
|
122
|
+
interface ImportMap {
|
|
123
|
+
imports?: Record<string, string>;
|
|
124
|
+
scopes?: Record<string, Record<string, string>>;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Important Notes:**
|
|
129
|
+
- Only supports Node.js environment, not browser
|
|
130
|
+
- Paths must be absolute paths or complete URLs
|
|
131
|
+
|
|
132
|
+
## 📄 License
|
|
133
|
+
|
|
134
|
+
MIT © [Esmx Team](https://github.com/esmnext/esmx)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://www.esmnext.com/logo.svg?t=2025" width="120" alt="Esmx Logo" />
|
|
3
|
+
<h1>@esmx/import</h1>
|
|
4
|
+
|
|
5
|
+
<div>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@esmx/import">
|
|
7
|
+
<img src="https://img.shields.io/npm/v/@esmx/import.svg" alt="npm version" />
|
|
8
|
+
</a>
|
|
9
|
+
<a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
|
|
10
|
+
<img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
|
|
11
|
+
</a>
|
|
12
|
+
<a href="https://www.esmnext.com/coverage/">
|
|
13
|
+
<img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://nodejs.org/">
|
|
16
|
+
<img src="https://img.shields.io/node/v/@esmx/import.svg" alt="node version" />
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://bundlephobia.com/package/@esmx/import">
|
|
19
|
+
<img src="https://img.shields.io/bundlephobia/minzip/@esmx/import" alt="size" />
|
|
20
|
+
</a>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<p>为 Esmx 框架提供 Import Maps 的 Node.js 服务端实现</p>
|
|
24
|
+
|
|
25
|
+
<p>
|
|
26
|
+
<a href="https://github.com/esmnext/esmx/blob/master/packages/import/README.md">English</a> | 中文
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## 🚀 特性
|
|
31
|
+
|
|
32
|
+
- **双重实现** - 开发环境使用 VM 模式,生产环境使用 Loader 模式
|
|
33
|
+
- **热重载支持** - VM 模式支持多次创建,提供开发灵活性
|
|
34
|
+
- **高性能** - Loader 模式为生产部署优化
|
|
35
|
+
- **Node.js 专注** - 专为 Node.js 服务端环境设计
|
|
36
|
+
- **TypeScript 就绪** - 完整的 TypeScript 支持,出色的类型安全
|
|
37
|
+
- **ESM 标准** - 完全符合 Import Maps 规范
|
|
38
|
+
|
|
39
|
+
## 📦 安装
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @esmx/import
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 🚀 快速开始
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { createVmImport } from '@esmx/import';
|
|
49
|
+
import { pathToFileURL } from 'node:url';
|
|
50
|
+
|
|
51
|
+
const vmImport = createVmImport(baseURL, importMap);
|
|
52
|
+
const module = await vmImport('my-app/src/utils', import.meta.url);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 📖 模式对比
|
|
56
|
+
|
|
57
|
+
`@esmx/import` 提供两种不同的 Import Maps 实现方式:
|
|
58
|
+
|
|
59
|
+
| 特性 | VM 模式 | Loader 模式 |
|
|
60
|
+
|------|---------|-------------|
|
|
61
|
+
| **函数** | `createVmImport()` | `createLoaderImport()` |
|
|
62
|
+
| **适用环境** | 开发环境 | 生产环境 |
|
|
63
|
+
| **热重载** | ✅ 支持多次创建 | ❌ 只能创建一次 |
|
|
64
|
+
| **性能** | 相对较慢 | 高性能 |
|
|
65
|
+
| **隔离性** | 完全隔离的 VM 环境 | 使用 Node.js 原生 Loader |
|
|
66
|
+
| **调试** | 便于开发调试 | 适合生产部署 |
|
|
67
|
+
|
|
68
|
+
## 🔧 使用示例
|
|
69
|
+
|
|
70
|
+
### VM 模式 (开发环境)
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { createVmImport } from '@esmx/import';
|
|
74
|
+
import { pathToFileURL } from 'node:url';
|
|
75
|
+
|
|
76
|
+
const baseURL = pathToFileURL('/project');
|
|
77
|
+
const importMap = {
|
|
78
|
+
imports: {
|
|
79
|
+
'my-app/src/utils': '/project/src/utils.mjs'
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const vmImport = createVmImport(baseURL, importMap);
|
|
84
|
+
const module = await vmImport('my-app/src/utils', import.meta.url);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Loader 模式 (生产环境)
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { createLoaderImport } from '@esmx/import';
|
|
91
|
+
import { pathToFileURL } from 'node:url';
|
|
92
|
+
|
|
93
|
+
const baseURL = pathToFileURL('/app/dist/server');
|
|
94
|
+
const importMap = {
|
|
95
|
+
imports: {
|
|
96
|
+
'my-app/src/utils': '/app/dist/server/my-app/src/utils.mjs'
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const loaderImport = createLoaderImport(baseURL, importMap);
|
|
101
|
+
const module = await loaderImport('my-app/src/utils');
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 📚 API 参考
|
|
105
|
+
|
|
106
|
+
### createVmImport(baseURL, importMap?)
|
|
107
|
+
创建基于 VM 的导入函数,支持热重载。
|
|
108
|
+
```typescript
|
|
109
|
+
const vmImport = createVmImport(baseURL, importMap);
|
|
110
|
+
const module = await vmImport(specifier, parent, sandbox?, options?);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### createLoaderImport(baseURL, importMap?)
|
|
114
|
+
创建基于 Loader 的导入函数,高性能,只能创建一次。
|
|
115
|
+
```typescript
|
|
116
|
+
const loaderImport = createLoaderImport(baseURL, importMap);
|
|
117
|
+
const module = await loaderImport(specifier);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### ImportMap 格式
|
|
121
|
+
```typescript
|
|
122
|
+
interface ImportMap {
|
|
123
|
+
imports?: Record<string, string>;
|
|
124
|
+
scopes?: Record<string, Record<string, string>>;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**注意事项:**
|
|
129
|
+
- 仅支持 Node.js 环境,不支持浏览器
|
|
130
|
+
- 路径必须为绝对路径或完整 URL
|
|
131
|
+
|
|
132
|
+
## 📄 许可证
|
|
133
|
+
|
|
134
|
+
MIT © [Esmx Team](https://github.com/esmnext/esmx)
|
package/dist/import-loader.d.ts
CHANGED
|
@@ -3,9 +3,6 @@ interface Data {
|
|
|
3
3
|
baseURL: string;
|
|
4
4
|
importMap: ImportMap;
|
|
5
5
|
}
|
|
6
|
-
/**
|
|
7
|
-
* 创建一个使用 loader 实现的 importmap 的 import 函数,只能创建一次,无热更新,适合生产使用。
|
|
8
|
-
*/
|
|
9
6
|
export declare function createLoaderImport(baseURL: URL, importMap?: ImportMap): (specifier: string) => Promise<Record<string, any>>;
|
|
10
7
|
export declare function initialize(data: Data): void;
|
|
11
8
|
export declare function resolve(specifier: string, context: Record<string, any>, nextResolve: Function): any;
|
package/dist/import-loader.mjs
CHANGED
|
@@ -18,7 +18,11 @@ export function createLoaderImport(baseURL, importMap = {}) {
|
|
|
18
18
|
);
|
|
19
19
|
}
|
|
20
20
|
return (specifier) => {
|
|
21
|
-
|
|
21
|
+
try {
|
|
22
|
+
return import(specifier);
|
|
23
|
+
} catch (e) {
|
|
24
|
+
throw new Error(`Failed to import '${specifier}'`);
|
|
25
|
+
}
|
|
22
26
|
};
|
|
23
27
|
}
|
|
24
28
|
let loaderBaseURL = new URL("file:");
|
package/dist/import-vm.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
import vm from 'node:vm';
|
|
2
2
|
import type { ImportMap } from './types';
|
|
3
|
-
/**
|
|
4
|
-
* 创建一个使用 vm 实现的 importmap 的 import 函数,可以创建多次来实现热更新效果,适合开发使用。
|
|
5
|
-
*/
|
|
6
3
|
export declare function createVmImport(baseURL: URL, importMap?: ImportMap): (specifier: string, parent: string, sandbox?: vm.Context, options?: vm.CreateContextOptions) => Promise<Record<string, any>>;
|
package/dist/import-vm.mjs
CHANGED
|
@@ -82,12 +82,10 @@ export function createVmImport(baseURL, importMap = {}) {
|
|
|
82
82
|
},
|
|
83
83
|
identifier: specifier,
|
|
84
84
|
context,
|
|
85
|
-
// @ts-ignore
|
|
86
85
|
importModuleDynamically: (specifier2, referrer) => {
|
|
87
86
|
return moduleLinker(
|
|
88
87
|
specifier2,
|
|
89
88
|
parsed.filename,
|
|
90
|
-
// @ts-ignore
|
|
91
89
|
referrer.context,
|
|
92
90
|
cache,
|
|
93
91
|
[...moduleIds, parsed.pathname]
|
package/package.json
CHANGED
|
@@ -33,16 +33,15 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@biomejs/biome": "1.9.4",
|
|
36
|
-
"@esmx/lint": "3.0.0-rc.
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
39
|
-
"
|
|
40
|
-
"stylelint": "16.15.0",
|
|
36
|
+
"@esmx/lint": "3.0.0-rc.19",
|
|
37
|
+
"@types/node": "22.15.18",
|
|
38
|
+
"@vitest/coverage-v8": "3.1.3",
|
|
39
|
+
"stylelint": "16.19.1",
|
|
41
40
|
"typescript": "5.8.2",
|
|
42
|
-
"unbuild": "
|
|
43
|
-
"vitest": "3.
|
|
41
|
+
"unbuild": "3.5.0",
|
|
42
|
+
"vitest": "3.1.3"
|
|
44
43
|
},
|
|
45
|
-
"version": "3.0.0-rc.
|
|
44
|
+
"version": "3.0.0-rc.19",
|
|
46
45
|
"type": "module",
|
|
47
46
|
"private": false,
|
|
48
47
|
"exports": {
|
|
@@ -61,5 +60,5 @@
|
|
|
61
60
|
"template",
|
|
62
61
|
"public"
|
|
63
62
|
],
|
|
64
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "83a9cfac4a91b2b54ac576e120bb4541f4cce9d6"
|
|
65
64
|
}
|
package/src/import-loader.ts
CHANGED
|
@@ -9,9 +9,7 @@ interface Data {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
let registered = '';
|
|
12
|
-
|
|
13
|
-
* 创建一个使用 loader 实现的 importmap 的 import 函数,只能创建一次,无热更新,适合生产使用。
|
|
14
|
-
*/
|
|
12
|
+
|
|
15
13
|
export function createLoaderImport(baseURL: URL, importMap: ImportMap = {}) {
|
|
16
14
|
if (!registered) {
|
|
17
15
|
module.register<Data>(fileURLToPath(import.meta.url), {
|
|
@@ -28,11 +26,14 @@ export function createLoaderImport(baseURL: URL, importMap: ImportMap = {}) {
|
|
|
28
26
|
);
|
|
29
27
|
}
|
|
30
28
|
return (specifier: string): Promise<Record<string, any>> => {
|
|
31
|
-
|
|
29
|
+
try {
|
|
30
|
+
return import(specifier);
|
|
31
|
+
} catch (e) {
|
|
32
|
+
throw new Error(`Failed to import '${specifier}'`);
|
|
33
|
+
}
|
|
32
34
|
};
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
// loader 线程时的处理逻辑
|
|
36
37
|
let loaderBaseURL: URL = new URL('file:');
|
|
37
38
|
let loaderParsedImportMap: IM.ParsedImportMap = {};
|
|
38
39
|
|
package/src/import-vm.ts
CHANGED
|
@@ -27,9 +27,6 @@ async function importBuiltinModule(specifier: string, context: vm.Context) {
|
|
|
27
27
|
return module;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
* 创建一个使用 vm 实现的 importmap 的 import 函数,可以创建多次来实现热更新效果,适合开发使用。
|
|
32
|
-
*/
|
|
33
30
|
export function createVmImport(baseURL: URL, importMap: ImportMap = {}) {
|
|
34
31
|
const parsedImportMap = IM.parse(importMap, baseURL);
|
|
35
32
|
const parse = (specifier: string, parent: string) => {
|
|
@@ -101,12 +98,10 @@ export function createVmImport(baseURL: URL, importMap: ImportMap = {}) {
|
|
|
101
98
|
},
|
|
102
99
|
identifier: specifier,
|
|
103
100
|
context: context,
|
|
104
|
-
// @ts-ignore
|
|
105
101
|
importModuleDynamically: (specifier, referrer) => {
|
|
106
102
|
return moduleLinker(
|
|
107
103
|
specifier,
|
|
108
104
|
parsed.filename,
|
|
109
|
-
// @ts-ignore
|
|
110
105
|
referrer.context,
|
|
111
106
|
cache,
|
|
112
107
|
[...moduleIds, parsed.pathname]
|