@package-verse/esmpack 1.0.11 → 1.0.12

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/README.md CHANGED
@@ -2,22 +2,19 @@
2
2
  ESM Pack Packer and Web Server with PostCSS and ESM Loader
3
3
 
4
4
  # Why?
5
- Because, there is no simple packer that just rewrites module paths. After ES6 and HTTP2, there is no need to bundle all JavaScripts into a single file. Parsing and loading entire bundle is a single threaded operation, which blocks UI rendering and also consumes very high memory.
5
+ Because, there is no simple packer that just generates module paths. After ES6 and HTTP2, there is no need to bundle all JavaScripts into a single file. Parsing and loading entire bundle is a single threaded operation, which blocks UI rendering and also consumes very high memory.
6
6
 
7
7
  # So what does this do?
8
8
  1. Creates a single pack JS file which only has import definition of all the imports.
9
- 2. Packed file strips css and delivers separate css as combined CSS.
10
- 3. Retains ESM source code as it is except import path, import path is rewritten to fully qualified CDN url. So caching is preserved over different main module versions but same dependencies.
9
+ 2. Import map contains inline JavaScript module via data url to inject CSS link into document.
11
10
 
12
11
 
13
12
  ## Dev Packer
14
13
 
15
- 1. Development time packer will generate HTML file along with the pack that will generate import maps along with the loading of control and hosting it.
14
+ 1. Development time packer will generate HTML file along with the import map and inline script to host the module.
16
15
  2. Dev Packer will generate `let cs = document.currentScript;import("imported-path").then((r) => ESMPack.render(r, cs))` script inside html for every JS's corresponding html.
17
16
  3. Library author must implement `ESMPack.render` method which will accept exports from imported method and `currentScript`.
18
- 4. Every `js` file's imports will be changed to fully qualified references for external imports.
19
17
 
20
18
  ## Release Packer
21
19
 
22
- 1. A single script with `.pack.js` will be generated that will import every nested imports along with fully qualified path for every nested imported external references.
23
- 2. Every `js` file's imports will be changed to fully qualified references for external imports.
20
+ 1. `pack.js` will generate a single JS file that will inject import map into document and it will call `ESMPack.render` method with import.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@package-verse/esmpack",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "ESM Pack Packer and Web Server with PostCSS and ESM Loader",
5
5
  "homepage": "https://github.com/package-verse/esmpack#readme",
6
6
  "bugs": {
@@ -1,5 +1,6 @@
1
1
  import path from "path";
2
2
  import { Babel } from "../parser/babel.js";
3
+ import packageMap, { IPackageMap } from "./packageMap.js";
3
4
 
4
5
  /**
5
6
  * File Packer must do following tasks...
@@ -20,15 +21,13 @@ import { Babel } from "../parser/babel.js";
20
21
  * Imports all nested dependencies of App.js that should not contain fully qualified path
21
22
  * Import dynamically loaded modules as well
22
23
  * Imports App.js dynamically so CSS can be ready before hosting the User interface
23
- * 2. App.pack.global.css
24
- * 3. App.pack.local.css
25
- * 4. App.pack.{hash-of-absolute-module-path}.js <-- this will be a dependency for non js module such as image or json etc.
26
- * This will load an absolute path via resolve
27
24
  */
28
25
  export default class FilePacker {
29
26
 
30
27
  readonly absoluteSrc: string;
31
28
 
29
+ modules: IPackageMap;
30
+
32
31
  readonly cssImports = [];
33
32
 
34
33
  readonly jsonImports = [];
@@ -50,6 +49,9 @@ export default class FilePacker {
50
49
 
51
50
  async pack() {
52
51
 
52
+ // resolve package.json
53
+ this.modules = await packageMap(this.root);
54
+
53
55
  const resolve = (url, sourceFile) => this.resolve(url, sourceFile);
54
56
 
55
57
  // we don't need the code
@@ -82,6 +84,9 @@ export default class FilePacker {
82
84
  }
83
85
 
84
86
  moduleUrl(url: string, sourceFile: string) {
87
+
88
+
89
+
85
90
  return url;
86
91
  }
87
92
  }
@@ -0,0 +1,27 @@
1
+ import { IPackageInfo, IPackageMap } from "./packageMap.js";
2
+
3
+ /**
4
+ * This class holds a path of single module along
5
+ * with it's own package info
6
+ */
7
+ export default class JSModule {
8
+
9
+ public imports: IPackageMap;
10
+
11
+ public owner: IPackageInfo;
12
+ public main: IPackageInfo;
13
+
14
+ public mainFolder: string;
15
+ public ownerFolder: string;
16
+
17
+ public src: string;
18
+
19
+ constructor(
20
+ p: Partial<JSModule>
21
+ ) {
22
+ // do nothing
23
+ Object.setPrototypeOf(p, JSModule.prototype);
24
+ return p as any;
25
+ }
26
+
27
+ }
@@ -0,0 +1,64 @@
1
+ import { readFile } from "fs/promises";
2
+ import { join } from "path";
3
+
4
+ const resolvedImports = new Map<string, Promise<IPackageMap>>();
5
+
6
+ export interface IPackageInfo {
7
+ name: string;
8
+ version: string;
9
+ main: string;
10
+ }
11
+
12
+ export interface IPackageMap {
13
+ [key: string]: IPackageInfo
14
+ }
15
+
16
+ async function populatePackageInfo(root, imports: IPackageMap, packageJsonPath) {
17
+ const {
18
+ name,
19
+ version,
20
+ dependencies,
21
+ type,
22
+ module: moduleMain,
23
+ main
24
+ } = JSON.parse(await readFile(packageJsonPath, "utf-8"));
25
+
26
+ if (imports[name]) {
27
+ return;
28
+ }
29
+
30
+ /**
31
+ * Dependency must specify module or main, we will not assume it.
32
+ * We want to keep import map small.
33
+ *
34
+ * Otherwise, caller must explicitly specify the fully qualified module path to load
35
+ */
36
+ imports[name] = {
37
+ name,
38
+ version,
39
+ main: moduleMain
40
+ || (type === "module" ? main : void 0)
41
+ || void 0
42
+ }
43
+
44
+ for(const key of Object.keys(dependencies)) {
45
+ if (imports[key]) {
46
+ continue;
47
+ }
48
+ await populatePackageInfo(root, imports, join(root, "node_modules", key, "package.json"));
49
+ }
50
+ }
51
+
52
+ export default function packageMap(root: string) {
53
+ let value = resolvedImports.get(root);
54
+ if(value) {
55
+ return value;
56
+ }
57
+ value = (async ()=> {
58
+ const moduleImports = {} as IPackageMap;
59
+ await populatePackageInfo(root, moduleImports, join(root, "package.json"));
60
+ return moduleImports;
61
+ })();
62
+ resolvedImports.set(root, value);
63
+ return value;
64
+ }