vite-plugin-blocklet 0.8.17 → 0.9.1

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/dist/index.cjs CHANGED
@@ -10,6 +10,10 @@ var util = require('@ocap/util');
10
10
  var did = require('@arcblock/did');
11
11
  var ufo = require('ufo');
12
12
  var isMobile = require('ismobilejs');
13
+ var path = require('node:path');
14
+ var mlly = require('mlly');
15
+ var externalGlobals = require('rollup-plugin-external-globals');
16
+ var pMap = require('p-map');
13
17
  var getPort = require('get-port');
14
18
  var mri = require('mri');
15
19
  var httpProxyMiddleware = require('http-proxy-middleware');
@@ -477,6 +481,147 @@ function createExpressPlugin({ entryPath, ignorePath = [] }) {
477
481
  };
478
482
  }
479
483
 
484
+ const DEFINE_KEY = '__UNDER_BLOCKLET_EMBED_BUNDLE__';
485
+ const PROXY_SUFFIX = 'blocklet-embed-proxy';
486
+ const ENTRY_FILE = 'index.mjs';
487
+ const defaultExternals = [
488
+ // default externals
489
+ 'react',
490
+ '@arcblock/ux/lib/Locale/context',
491
+ '@arcblock/did-connect/lib/Session',
492
+ ];
493
+
494
+ /**
495
+ * @param {object} options - The options for the plugin.
496
+ * @param {object} [options.embeds={}] - The embeds to be built.
497
+ * @param {array} [options.embedExternals=['react', '@arcblock/ux/lib/Locale/context', '@arcblock/did-connect/lib/Session']] - The external modules to be used in the embeds.
498
+ * @param {array} [options.embedPlugins=[]] - The plugins to be used in the embeds.
499
+ * @param {number} [options.embedBuildConcurrency=0] - The plugins to be used in the embeds.
500
+ * @return {array} The Vite config plugin.
501
+ */
502
+ function createEmbedPlugin(options) {
503
+ const cache = {
504
+ config: {},
505
+ };
506
+
507
+ const inputEmbeds = options?.embeds || [];
508
+ const embedBuildConcurrency = options?.embedBuildConcurrency || 0;
509
+ let embedList = inputEmbeds;
510
+ if (!Array.isArray(inputEmbeds)) {
511
+ embedList = Object.keys(inputEmbeds).map((key) => {
512
+ return {
513
+ output: key,
514
+ entry: inputEmbeds[key],
515
+ };
516
+ });
517
+ }
518
+
519
+ if (inputEmbeds.length === 0) {
520
+ return [];
521
+ }
522
+
523
+ return [
524
+ {
525
+ name: 'blocklet:embed:serve',
526
+ apply: 'serve',
527
+ enforce: 'pre',
528
+ async resolveId(id, importer, options) {
529
+ const queryObject = ufo.getQuery(id);
530
+ if (queryObject[PROXY_SUFFIX] !== undefined) {
531
+ return id;
532
+ }
533
+ const entryId = ufo.parseURL(id).pathname;
534
+ const embedInput = embedList.find((x) => ufo.joinURL(ufo.withLeadingSlash(x.output), ENTRY_FILE) === entryId);
535
+ if (embedInput?.entry) {
536
+ const resolution = await this.resolve(embedInput.entry, importer, options);
537
+ return ufo.withQuery(resolution.id, { [PROXY_SUFFIX]: '' });
538
+ }
539
+ return null;
540
+ },
541
+ async load(id) {
542
+ const queryObject = ufo.getQuery(id);
543
+ if (queryObject[PROXY_SUFFIX] !== undefined) {
544
+ const entryId = ufo.parseURL(id).pathname;
545
+ const fileContent = await node_fs.promises.readFile(entryId, { encoding: 'utf-8' });
546
+ const names = mlly.findExportNames(fileContent);
547
+ let code = `import ${JSON.stringify(entryId)};`;
548
+ code += `export * from ${JSON.stringify(entryId)};`;
549
+ if (names.includes('default')) {
550
+ code += `export { default } from ${JSON.stringify(entryId)};`;
551
+ }
552
+ return code;
553
+ }
554
+ return null;
555
+ },
556
+ },
557
+ {
558
+ name: 'blocklet:embed:build',
559
+ apply: 'build',
560
+ enforce: 'post',
561
+ config(config) {
562
+ cache.config = config;
563
+ },
564
+ async closeBundle() {
565
+ if (cache.config?.define?.[DEFINE_KEY]) {
566
+ return;
567
+ }
568
+
569
+ const external = options?.embedExternals ? options.embedExternals : defaultExternals;
570
+ const externalMaps = external.reduce((acc, cur) => {
571
+ acc[cur] = `window[Symbol.for('embedModules')]['${cur}']`;
572
+ return acc;
573
+ }, {});
574
+
575
+ const promiseList = pMap(
576
+ embedList,
577
+ async (embedItem) => {
578
+ const entryItem = embedItem.entry;
579
+ const outputItem = ufo.withoutLeadingSlash(embedItem.output);
580
+ // eslint-disable-next-line no-await-in-loop
581
+ await vite.build({
582
+ ...cache.config,
583
+ configFile: false,
584
+ publicDir: false,
585
+ define: {
586
+ ...cache.config?.define,
587
+ 'process.env': {
588
+ NODE_ENV: 'production',
589
+ ...(cache.config?.define?.['process.env'] || {}),
590
+ },
591
+ [DEFINE_KEY]: true,
592
+ },
593
+ plugins: [
594
+ ...(cache.config?.plugins || []),
595
+ ...(options?.embedPlugins || []),
596
+ externalGlobals(externalMaps),
597
+ ],
598
+ build: {
599
+ lib: {
600
+ entry: entryItem,
601
+ formats: ['es'],
602
+ fileName: path.parse(ENTRY_FILE).name,
603
+ },
604
+ rollupOptions: {
605
+ external,
606
+ output: {
607
+ dir: ufo.joinURL(cache.config?.build?.outDir || 'dist', outputItem),
608
+ },
609
+ },
610
+ },
611
+ });
612
+ },
613
+ {
614
+ concurrency: embedBuildConcurrency || 1,
615
+ },
616
+ );
617
+ if (embedBuildConcurrency === 0) {
618
+ await promiseList;
619
+ }
620
+ },
621
+ },
622
+ ];
623
+ }
624
+
480
625
  const argv = process.argv.slice(2);
481
626
  const isProduction = process.env.NODE_ENV === 'production' || process.env.ABT_NODE_SERVICE_ENV === 'production';
482
627
 
@@ -585,6 +730,7 @@ async function setupClient(app, options = {}) {
585
730
  * @property {boolean} [disableHmr=false] - Disable hmr plugin.
586
731
  * @property {boolean} [disableLoading=false] - Disable loading plugin.
587
732
  * @property {boolean} [disableDebug=false] - Disable debug plugin.
733
+ * @property {boolean} [disableEmbed=false] - Disable embed plugin.
588
734
  * @property {import('vite-plugin-node-polyfills').PolyfillOptions} [nodePolyfillsOptions]
589
735
  *
590
736
  * @property {string} [loadingElementId]
@@ -592,6 +738,10 @@ async function setupClient(app, options = {}) {
592
738
  * @property {string} [loadingImage]
593
739
  * @property {'all'|'mobile'|'desktop'} [debugPlatform='mobile']
594
740
  * @property {string} [debugScript]
741
+ * @param {object} [embeds={}] - The embeds to be built.
742
+ * @param {array} [embedExternals=['react', '@arcblock/ux/lib/Locale/context', '@arcblock/did-connect/lib/Session']] - The external modules to be used in the embeds.
743
+ * @param {array} [embedPlugins=[]] - The plugins to be used in the embeds.
744
+ * @param {number} [embedBuildConcurrency=0] - The plugins to be used in the embeds.
595
745
  * @property {'middleware'|'client'|'server'|'wsUpgrade'} [hmrMode='middleware'] - 当未传入任何 option 参数时,会自动变为 middleware 模式
596
746
  */
597
747
 
@@ -611,6 +761,7 @@ function createBlockletPlugin(options = {}) {
611
761
  disableHmr = false,
612
762
  disableLoading = false,
613
763
  disableDebug = false,
764
+ disableEmbed = false,
614
765
  nodePolyfillsOptions,
615
766
  ...restOptions
616
767
  } = options;
@@ -636,6 +787,9 @@ function createBlockletPlugin(options = {}) {
636
787
  if (!disableDebug) {
637
788
  plugins.push(createConfigPlugin(restOptions));
638
789
  }
790
+ if (!disableEmbed) {
791
+ plugins.push(createEmbedPlugin(restOptions));
792
+ }
639
793
 
640
794
  return plugins;
641
795
  }
@@ -646,6 +800,7 @@ Object.defineProperty(exports, "nodePolyfills", {
646
800
  });
647
801
  exports.createBlockletConfig = createConfigPlugin$1;
648
802
  exports.createBlockletDebug = createConfigPlugin;
803
+ exports.createBlockletEmbed = createEmbedPlugin;
649
804
  exports.createBlockletExpress = createExpressPlugin;
650
805
  exports.createBlockletHmr = createHmrPlugin;
651
806
  exports.createBlockletLoading = createLoadingPlugin;
package/index.js CHANGED
@@ -5,6 +5,7 @@ import createMetaPlugin from './libs/meta.js';
5
5
  import createLoadingPlugin from './libs/loading.js';
6
6
  import createDebugPlugin from './libs/debug.js';
7
7
  import createExpressPlugin from './libs/express.js';
8
+ import createEmbedPlugin from './libs/embed.js';
8
9
  import setupClient from './libs/client.js';
9
10
 
10
11
  /**
@@ -17,6 +18,7 @@ import setupClient from './libs/client.js';
17
18
  * @property {boolean} [disableHmr=false] - Disable hmr plugin.
18
19
  * @property {boolean} [disableLoading=false] - Disable loading plugin.
19
20
  * @property {boolean} [disableDebug=false] - Disable debug plugin.
21
+ * @property {boolean} [disableEmbed=false] - Disable embed plugin.
20
22
  * @property {import('vite-plugin-node-polyfills').PolyfillOptions} [nodePolyfillsOptions]
21
23
  *
22
24
  * @property {string} [loadingElementId]
@@ -24,6 +26,10 @@ import setupClient from './libs/client.js';
24
26
  * @property {string} [loadingImage]
25
27
  * @property {'all'|'mobile'|'desktop'} [debugPlatform='mobile']
26
28
  * @property {string} [debugScript]
29
+ * @param {object} [embeds={}] - The embeds to be built.
30
+ * @param {array} [embedExternals=['react', '@arcblock/ux/lib/Locale/context', '@arcblock/did-connect/lib/Session']] - The external modules to be used in the embeds.
31
+ * @param {array} [embedPlugins=[]] - The plugins to be used in the embeds.
32
+ * @param {number} [embedBuildConcurrency=0] - The plugins to be used in the embeds.
27
33
  * @property {'middleware'|'client'|'server'|'wsUpgrade'} [hmrMode='middleware'] - 当未传入任何 option 参数时,会自动变为 middleware 模式
28
34
  */
29
35
 
@@ -43,6 +49,7 @@ export function createBlockletPlugin(options = {}) {
43
49
  disableHmr = false,
44
50
  disableLoading = false,
45
51
  disableDebug = false,
52
+ disableEmbed = false,
46
53
  nodePolyfillsOptions,
47
54
  ...restOptions
48
55
  } = options;
@@ -68,6 +75,9 @@ export function createBlockletPlugin(options = {}) {
68
75
  if (!disableDebug) {
69
76
  plugins.push(createDebugPlugin(restOptions));
70
77
  }
78
+ if (!disableEmbed) {
79
+ plugins.push(createEmbedPlugin(restOptions));
80
+ }
71
81
 
72
82
  return plugins;
73
83
  }
@@ -80,5 +90,6 @@ export {
80
90
  createLoadingPlugin as createBlockletLoading,
81
91
  createDebugPlugin as createBlockletDebug,
82
92
  createExpressPlugin as createBlockletExpress,
93
+ createEmbedPlugin as createBlockletEmbed,
83
94
  nodePolyfills,
84
95
  };
package/libs/embed.js ADDED
@@ -0,0 +1,148 @@
1
+ import path from 'node:path';
2
+ import { promises as fs } from 'node:fs';
3
+ import { findExportNames } from 'mlly';
4
+ import externalGlobals from 'rollup-plugin-external-globals';
5
+ import { joinURL, withLeadingSlash, withoutLeadingSlash, getQuery, withQuery, parseURL } from 'ufo';
6
+ import { build } from 'vite';
7
+ import pMap from 'p-map';
8
+
9
+ const DEFINE_KEY = '__UNDER_BLOCKLET_EMBED_BUNDLE__';
10
+ const PROXY_SUFFIX = 'blocklet-embed-proxy';
11
+ const ENTRY_FILE = 'index.mjs';
12
+ const defaultExternals = [
13
+ // default externals
14
+ 'react',
15
+ '@arcblock/ux/lib/Locale/context',
16
+ '@arcblock/did-connect/lib/Session',
17
+ ];
18
+
19
+ /**
20
+ * @param {object} options - The options for the plugin.
21
+ * @param {object} [options.embeds={}] - The embeds to be built.
22
+ * @param {array} [options.embedExternals=['react', '@arcblock/ux/lib/Locale/context', '@arcblock/did-connect/lib/Session']] - The external modules to be used in the embeds.
23
+ * @param {array} [options.embedPlugins=[]] - The plugins to be used in the embeds.
24
+ * @param {number} [options.embedBuildConcurrency=0] - The plugins to be used in the embeds.
25
+ * @return {array} The Vite config plugin.
26
+ */
27
+ export default function createEmbedPlugin(options) {
28
+ const cache = {
29
+ config: {},
30
+ };
31
+
32
+ const inputEmbeds = options?.embeds || [];
33
+ const embedBuildConcurrency = options?.embedBuildConcurrency || 0;
34
+ let embedList = inputEmbeds;
35
+ if (!Array.isArray(inputEmbeds)) {
36
+ embedList = Object.keys(inputEmbeds).map((key) => {
37
+ return {
38
+ output: key,
39
+ entry: inputEmbeds[key],
40
+ };
41
+ });
42
+ }
43
+
44
+ if (inputEmbeds.length === 0) {
45
+ return [];
46
+ }
47
+
48
+ return [
49
+ {
50
+ name: 'blocklet:embed:serve',
51
+ apply: 'serve',
52
+ enforce: 'pre',
53
+ async resolveId(id, importer, options) {
54
+ const queryObject = getQuery(id);
55
+ if (queryObject[PROXY_SUFFIX] !== undefined) {
56
+ return id;
57
+ }
58
+ const entryId = parseURL(id).pathname;
59
+ const embedInput = embedList.find((x) => joinURL(withLeadingSlash(x.output), ENTRY_FILE) === entryId);
60
+ if (embedInput?.entry) {
61
+ const resolution = await this.resolve(embedInput.entry, importer, options);
62
+ return withQuery(resolution.id, { [PROXY_SUFFIX]: '' });
63
+ }
64
+ return null;
65
+ },
66
+ async load(id) {
67
+ const queryObject = getQuery(id);
68
+ if (queryObject[PROXY_SUFFIX] !== undefined) {
69
+ const entryId = parseURL(id).pathname;
70
+ const fileContent = await fs.readFile(entryId, { encoding: 'utf-8' });
71
+ const names = findExportNames(fileContent);
72
+ let code = `import ${JSON.stringify(entryId)};`;
73
+ code += `export * from ${JSON.stringify(entryId)};`;
74
+ if (names.includes('default')) {
75
+ code += `export { default } from ${JSON.stringify(entryId)};`;
76
+ }
77
+ return code;
78
+ }
79
+ return null;
80
+ },
81
+ },
82
+ {
83
+ name: 'blocklet:embed:build',
84
+ apply: 'build',
85
+ enforce: 'post',
86
+ config(config) {
87
+ cache.config = config;
88
+ },
89
+ async closeBundle() {
90
+ if (cache.config?.define?.[DEFINE_KEY]) {
91
+ return;
92
+ }
93
+
94
+ const external = options?.embedExternals ? options.embedExternals : defaultExternals;
95
+ const externalMaps = external.reduce((acc, cur) => {
96
+ acc[cur] = `window[Symbol.for('embedModules')]['${cur}']`;
97
+ return acc;
98
+ }, {});
99
+
100
+ const promiseList = pMap(
101
+ embedList,
102
+ async (embedItem) => {
103
+ const entryItem = embedItem.entry;
104
+ const outputItem = withoutLeadingSlash(embedItem.output);
105
+ // eslint-disable-next-line no-await-in-loop
106
+ await build({
107
+ ...cache.config,
108
+ configFile: false,
109
+ publicDir: false,
110
+ define: {
111
+ ...cache.config?.define,
112
+ 'process.env': {
113
+ NODE_ENV: 'production',
114
+ ...(cache.config?.define?.['process.env'] || {}),
115
+ },
116
+ [DEFINE_KEY]: true,
117
+ },
118
+ plugins: [
119
+ ...(cache.config?.plugins || []),
120
+ ...(options?.embedPlugins || []),
121
+ externalGlobals(externalMaps),
122
+ ],
123
+ build: {
124
+ lib: {
125
+ entry: entryItem,
126
+ formats: ['es'],
127
+ fileName: path.parse(ENTRY_FILE).name,
128
+ },
129
+ rollupOptions: {
130
+ external,
131
+ output: {
132
+ dir: joinURL(cache.config?.build?.outDir || 'dist', outputItem),
133
+ },
134
+ },
135
+ },
136
+ });
137
+ },
138
+ {
139
+ concurrency: embedBuildConcurrency || 1,
140
+ },
141
+ );
142
+ if (embedBuildConcurrency === 0) {
143
+ await promiseList;
144
+ }
145
+ },
146
+ },
147
+ ];
148
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vite-plugin-blocklet",
3
3
  "type": "module",
4
- "version": "0.8.17",
4
+ "version": "0.9.1",
5
5
  "description": "",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -24,7 +24,7 @@
24
24
  "author": "",
25
25
  "license": "ISC",
26
26
  "devDependencies": {
27
- "rollup": "^4.18.0"
27
+ "rollup": "^4.20.0"
28
28
  },
29
29
  "dependencies": {
30
30
  "@arcblock/did": "^1.18.128",
@@ -33,11 +33,14 @@
33
33
  "get-port": "^5.1.1",
34
34
  "http-proxy-middleware": "^3.0.0",
35
35
  "ismobilejs": "^1.1.1",
36
+ "mlly": "^1.7.1",
36
37
  "mri": "^1.2.0",
37
- "semver": "^7.6.2",
38
- "ufo": "^1.5.3",
38
+ "p-map": "^4.0.0",
39
+ "rollup-plugin-external-globals": "^0.12.0",
40
+ "semver": "^7.6.3",
41
+ "ufo": "^1.5.4",
39
42
  "vite-plugin-node-polyfills": "^0.22.0",
40
- "yaml": "^2.4.5"
43
+ "yaml": "^2.5.0"
41
44
  },
42
45
  "peerDependencies": {
43
46
  "vite": ">=5"