@cloudbase/container 2.5.37-beta.0 → 2.5.38-alpha.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/cjs/index.d.ts +9 -0
- package/dist/cjs/index.js +70 -155
- package/dist/cjs/utils/index.d.ts +1 -1
- package/dist/cjs/utils/index.js +31 -13
- package/dist/cjs/utils/loader.d.ts +8 -0
- package/dist/cjs/utils/loader.js +185 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.js +69 -151
- package/dist/esm/utils/index.d.ts +1 -1
- package/dist/esm/utils/index.js +31 -13
- package/dist/esm/utils/loader.d.ts +8 -0
- package/dist/esm/utils/loader.js +177 -0
- package/dist/miniprogram/index.js +1 -0
- package/package.json +11 -7
- package/src/index.ts +77 -167
- package/src/utils/index.ts +29 -11
- package/src/utils/loader.ts +138 -0
- package/webpack/web.prod.js +84 -0
- package/webpack/webpack.miniprogram.js +22 -0
package/src/index.ts
CHANGED
|
@@ -2,20 +2,42 @@ import { ICloudbase } from '@cloudbase/types'
|
|
|
2
2
|
import { ICloudbaseComponent } from '@cloudbase/types/component'
|
|
3
3
|
import { ICallContainerOptions, IContianerConfig } from '@cloudbase/types/container'
|
|
4
4
|
import { constants, utils, helpers } from '@cloudbase/utilities'
|
|
5
|
-
// import brotliPromise from 'brotli-dec-wasm' // Import the default export
|
|
6
|
-
import decompress from 'brotli/decompress'
|
|
7
|
-
|
|
8
|
-
import Go from './go_wams_exec'
|
|
9
5
|
import { isBuffer, parseURL, serializeRequestBody } from './utils'
|
|
10
|
-
import { request } from './utils/request'
|
|
11
6
|
import { COMPONENT_NAME } from './constants'
|
|
12
7
|
|
|
13
8
|
declare const cloudbase: ICloudbase
|
|
14
|
-
|
|
15
9
|
const { ERRORS, COMMUNITY_SITE_URL } = constants
|
|
16
10
|
const { execCallback, printWarn } = utils
|
|
17
11
|
const { catchErrorsDecorator } = helpers
|
|
18
12
|
|
|
13
|
+
/* eslint-disable */
|
|
14
|
+
let getExportFunction: Function = () => {
|
|
15
|
+
throw new Error('getExportFunction 未实现')
|
|
16
|
+
}
|
|
17
|
+
let loadJSExportFunction: Function = () => {
|
|
18
|
+
throw new Error('loadJSExportFunction 未实现')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (globalThis.IS_MP_BUILD) {
|
|
22
|
+
getExportFunction = function () {
|
|
23
|
+
new Error('小程序不支持 wasm 加载')
|
|
24
|
+
}
|
|
25
|
+
loadJSExportFunction = function (jsUrl) {
|
|
26
|
+
if (jsUrl) {
|
|
27
|
+
new Error('小程序不支持动态 js 加载')
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
initContainer: (globalThis as any).cloudbase_private_link.initContainer,
|
|
31
|
+
callContainer: (globalThis as any).cloudbase_private_link.callContainer,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
const loader = require('./utils/loader')
|
|
36
|
+
getExportFunction = loader.getExportFunction
|
|
37
|
+
loadJSExportFunction = loader.loadJSExportFunction
|
|
38
|
+
}
|
|
39
|
+
/* eslint-enable */
|
|
40
|
+
|
|
19
41
|
class InvalieParamsError extends Error {
|
|
20
42
|
code: any
|
|
21
43
|
constructor(scope, message) {
|
|
@@ -51,43 +73,45 @@ function genContainerError(data, scope = COMPONENT_NAME, defaultMessage = 'call
|
|
|
51
73
|
return error
|
|
52
74
|
}
|
|
53
75
|
|
|
54
|
-
class CloudbaseContainers {
|
|
55
|
-
private readonly config: IContianerConfig
|
|
76
|
+
export class CloudbaseContainers {
|
|
77
|
+
private readonly config: IContianerConfig & { jsUrl?: { vender?: string; vm: string } }
|
|
56
78
|
private wasm: Promise<WebAssembly.Exports>
|
|
57
79
|
private containerInitPromise: /* Promise<any>*/ any | null
|
|
58
80
|
|
|
59
81
|
constructor(config: IContianerConfig) {
|
|
60
82
|
this.config = {
|
|
61
83
|
...config,
|
|
84
|
+
jsUrl:
|
|
85
|
+
typeof config.jsUrl === 'string'
|
|
86
|
+
? {
|
|
87
|
+
vm: config.jsUrl,
|
|
88
|
+
}
|
|
89
|
+
: (config.jsUrl as any),
|
|
62
90
|
}
|
|
63
91
|
|
|
64
|
-
if (!this.config.wasmUrl &&
|
|
92
|
+
if (!this.config.wasmUrl && this.config.publicKey) {
|
|
93
|
+
// 非 wams 且有 public key 则可使用默认的 js-sdk,无需校验
|
|
94
|
+
} else if (!this.config.wasmUrl && !this.config.jsUrl?.vm && !(globalThis as any).cloudbase_private_link) {
|
|
65
95
|
throw new InvalieParamsError(`${COMPONENT_NAME}`, '缺少 privatelink sdk 地址')
|
|
66
96
|
}
|
|
67
97
|
|
|
68
98
|
if (this.config.wasmUrl) {
|
|
69
|
-
this.wasm = getExportFunction(this.config.wasmUrl
|
|
70
|
-
utils: {
|
|
71
|
-
info(e) {
|
|
72
|
-
console.log(e)
|
|
73
|
-
},
|
|
74
|
-
request,
|
|
75
|
-
},
|
|
76
|
-
}).catch((e) => {
|
|
99
|
+
this.wasm = getExportFunction(this.config.wasmUrl).catch((e) => {
|
|
77
100
|
if (this.config.jsUrl) {
|
|
78
101
|
console.warn('load wams error, fall back to use js', e)
|
|
79
102
|
return loadJSExportFunction(this.config.jsUrl)
|
|
80
|
-
}
|
|
81
|
-
|
|
103
|
+
}
|
|
104
|
+
if ((globalThis as any).cloudbase_private_link) {
|
|
105
|
+
return (globalThis as any).cloudbase_private_link
|
|
82
106
|
}
|
|
83
107
|
throw e
|
|
84
108
|
})
|
|
85
|
-
} else if (this.config.jsUrl) {
|
|
109
|
+
} else if (this.config.jsUrl || this.config.publicKey) {
|
|
86
110
|
this.wasm = loadJSExportFunction(this.config.jsUrl)
|
|
87
111
|
} else {
|
|
88
112
|
this.wasm = Promise.resolve({
|
|
89
|
-
initContainer: (
|
|
90
|
-
callContainer: (
|
|
113
|
+
initContainer: (globalThis as any).cloudbase_private_link.initContainer,
|
|
114
|
+
callContainer: (globalThis as any).cloudbase_private_link.callContainer,
|
|
91
115
|
})
|
|
92
116
|
}
|
|
93
117
|
}
|
|
@@ -138,36 +162,44 @@ class CloudbaseContainers {
|
|
|
138
162
|
url,
|
|
139
163
|
method,
|
|
140
164
|
header,
|
|
141
|
-
data: serializeRequestBody(header, data),
|
|
165
|
+
data: serializeRequestBody(header, data, method),
|
|
142
166
|
timeout,
|
|
143
167
|
dataType,
|
|
144
168
|
responseType,
|
|
145
169
|
...restOptions,
|
|
146
170
|
}
|
|
147
171
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
172
|
+
if (
|
|
173
|
+
data
|
|
174
|
+
&& (isBuffer(params.data) || typeof params.data === 'string')
|
|
175
|
+
&& (data as any)?.length > 1000 * 1024 * 10
|
|
176
|
+
) {
|
|
177
|
+
reject(new InvalieParamsError(SCOPE, 'body too large'))
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (method === 'GET') {
|
|
182
|
+
let { data: getBody } = params
|
|
183
|
+
if (getBody) {
|
|
184
|
+
params.data = undefined
|
|
185
|
+
}
|
|
186
|
+
if (!isBuffer(getBody) && typeof getBody !== 'string') {
|
|
187
|
+
const list = Object.entries(getBody || {}).reduce(
|
|
188
|
+
(list, [key, value]: [string, string | number | boolean]) => {
|
|
189
|
+
list.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
|
|
190
|
+
return list
|
|
191
|
+
},
|
|
192
|
+
[],
|
|
193
|
+
)
|
|
194
|
+
if (list.length) {
|
|
195
|
+
getBody = list.join('&')
|
|
196
|
+
}
|
|
165
197
|
}
|
|
166
198
|
|
|
167
|
-
if (
|
|
199
|
+
if (typeof params.data === 'string') {
|
|
168
200
|
const parsedUrl = parseURL(url)
|
|
169
201
|
if (parsedUrl.search) {
|
|
170
|
-
parsedUrl.search += params.data
|
|
202
|
+
parsedUrl.search += `&${params.data}`
|
|
171
203
|
} else {
|
|
172
204
|
parsedUrl.search = `?${params.data}`
|
|
173
205
|
}
|
|
@@ -176,15 +208,6 @@ class CloudbaseContainers {
|
|
|
176
208
|
}
|
|
177
209
|
}
|
|
178
210
|
|
|
179
|
-
if (
|
|
180
|
-
data
|
|
181
|
-
&& (isBuffer(params.data) || typeof params.data === 'string')
|
|
182
|
-
&& (data as any)?.length > 1000 * 1024 * 10
|
|
183
|
-
) {
|
|
184
|
-
reject(new InvalieParamsError(SCOPE, 'body too large'))
|
|
185
|
-
return
|
|
186
|
-
}
|
|
187
|
-
|
|
188
211
|
callContainer({
|
|
189
212
|
...params,
|
|
190
213
|
success: resolve,
|
|
@@ -206,15 +229,15 @@ class CloudbaseContainers {
|
|
|
206
229
|
this.containerInitPromise = new Promise((resolve, reject) => {
|
|
207
230
|
initContainer({
|
|
208
231
|
config,
|
|
209
|
-
success(res) {
|
|
232
|
+
success: (res) => {
|
|
210
233
|
if (String(res.statusCode) !== '200') {
|
|
211
234
|
reject(genContainerError(res.data, `${COMPONENT_NAME}.initContainer`, 'init container fail'))
|
|
212
235
|
}
|
|
213
236
|
resolve(res)
|
|
214
237
|
},
|
|
215
|
-
fail(res) {
|
|
238
|
+
fail: (res) => {
|
|
216
239
|
reject(genContainerError(res.data, `${COMPONENT_NAME}.initContainer`, 'init container fail'))
|
|
217
|
-
this.
|
|
240
|
+
this.containerInitPromise = null
|
|
218
241
|
},
|
|
219
242
|
})
|
|
220
243
|
})
|
|
@@ -251,116 +274,3 @@ export function registerContainers(app: Pick<ICloudbase, 'registerComponent'>) {
|
|
|
251
274
|
console.warn(e)
|
|
252
275
|
}
|
|
253
276
|
}
|
|
254
|
-
|
|
255
|
-
async function getExportFunction(url, module, mode = 'go') {
|
|
256
|
-
async function instantiateStreaming(resp, importObject, brotliCompressed = false) {
|
|
257
|
-
if (brotliCompressed || !WebAssembly.instantiateStreaming) {
|
|
258
|
-
const source = await (await resp).arrayBuffer()
|
|
259
|
-
const buffer = brotliCompressed ? decompress(new Int8Array(source)) : source
|
|
260
|
-
return WebAssembly.instantiate(buffer, importObject)
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return WebAssembly.instantiateStreaming(resp, importObject)
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
let importObject = {
|
|
267
|
-
env: {
|
|
268
|
-
memoryBase: 0,
|
|
269
|
-
tableBase: 0,
|
|
270
|
-
memory: new WebAssembly.Memory({
|
|
271
|
-
initial: 256,
|
|
272
|
-
}),
|
|
273
|
-
// table: new WebAssembly.Table({
|
|
274
|
-
// initial: 2,
|
|
275
|
-
// element: 'anyfunc',
|
|
276
|
-
// }),
|
|
277
|
-
},
|
|
278
|
-
...module,
|
|
279
|
-
}
|
|
280
|
-
let go
|
|
281
|
-
const brotliCompressed = isBrotliCompressed(url)
|
|
282
|
-
|
|
283
|
-
if (mode === 'go') {
|
|
284
|
-
go = new Go()
|
|
285
|
-
go._initedModulePromise = new Promise((resolve) => {
|
|
286
|
-
go._initedModuleResolve = resolve
|
|
287
|
-
})
|
|
288
|
-
importObject = {
|
|
289
|
-
...go.importObject,
|
|
290
|
-
env: {
|
|
291
|
-
...go.importObject.env,
|
|
292
|
-
exportModule(module) {
|
|
293
|
-
return go._initedModuleResolve(module)
|
|
294
|
-
},
|
|
295
|
-
},
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const reuslt = await instantiateStreaming(fetch(url), importObject, brotliCompressed)
|
|
300
|
-
|
|
301
|
-
if (mode === 'go') {
|
|
302
|
-
await Promise.race([
|
|
303
|
-
go.run(reuslt.instance),
|
|
304
|
-
new Promise(resolve => setTimeout(() => {
|
|
305
|
-
resolve(null)
|
|
306
|
-
}, 500),),
|
|
307
|
-
])
|
|
308
|
-
|
|
309
|
-
return {
|
|
310
|
-
callContainer: (window as any).callContainer,
|
|
311
|
-
initContainer: (window as any).initContainer,
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// if (mode === 'go') {
|
|
316
|
-
// go.run(reuslt.instance)
|
|
317
|
-
// const module = await go._initedModulePromise
|
|
318
|
-
// return module
|
|
319
|
-
// }
|
|
320
|
-
|
|
321
|
-
return reuslt.instance.exports
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
function loadUmdModule(jsUrl: string, umdModuleName: string, targetDoc: Document = document) {
|
|
325
|
-
return new Promise<any>((resolve, reject) => {
|
|
326
|
-
const win = targetDoc.defaultView
|
|
327
|
-
|
|
328
|
-
const script = targetDoc.createElement('script')
|
|
329
|
-
script.setAttribute('src', jsUrl)
|
|
330
|
-
script.setAttribute('class', umdModuleName)
|
|
331
|
-
script.addEventListener('load', () => {
|
|
332
|
-
if (Object.prototype.hasOwnProperty.call(win, umdModuleName)) {
|
|
333
|
-
return resolve(win[umdModuleName as any])
|
|
334
|
-
}
|
|
335
|
-
const error = new Error(`Fail to load UMD module ${umdModuleName} from [${jsUrl}].`)
|
|
336
|
-
return reject(error)
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
script.addEventListener('error', (e) => {
|
|
340
|
-
const error = new Error(`main bundle [${umdModuleName}] load failed from [${jsUrl}]: ${e?.message || ''}`)
|
|
341
|
-
reject(error)
|
|
342
|
-
})
|
|
343
|
-
targetDoc.body.appendChild(script)
|
|
344
|
-
})
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
async function loadJSExportFunction(url) {
|
|
348
|
-
return loadUmdModule(url, 'cloudbase_private_link')
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
function isBrotliCompressed(url) {
|
|
352
|
-
let brotliCompressed = false
|
|
353
|
-
|
|
354
|
-
let pathname = ''
|
|
355
|
-
try {
|
|
356
|
-
const location = parseURL(url)
|
|
357
|
-
pathname = location.pathname
|
|
358
|
-
} catch (e) {
|
|
359
|
-
pathname = url
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
if (/\.br$/.test(pathname)) {
|
|
363
|
-
brotliCompressed = true
|
|
364
|
-
}
|
|
365
|
-
return brotliCompressed
|
|
366
|
-
}
|
package/src/utils/index.ts
CHANGED
|
@@ -15,15 +15,36 @@ export function isBuffer(buf: any) {
|
|
|
15
15
|
return buf instanceof ArrayBuffer || ArrayBuffer.isView(buf)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
function object2Qs(data) {
|
|
19
|
+
const list = Object.entries(data || {}).reduce((list, [key, value]: [string, string]) => {
|
|
20
|
+
list.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|
21
|
+
return list
|
|
22
|
+
}, [])
|
|
23
|
+
if (list.length) {
|
|
24
|
+
return list.join('&')
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function serializeRequestBody<T>(headers, data: T, method = 'POST'): T | string {
|
|
19
29
|
let res: T | string = data
|
|
20
|
-
const
|
|
30
|
+
const contentTypeKey = 'Content-Type'
|
|
21
31
|
if (typeof data === 'object' && !isBuffer(data)) {
|
|
22
|
-
if (!headers[
|
|
23
|
-
headers[
|
|
32
|
+
if (!headers[contentTypeKey] && !headers['content-type']) {
|
|
33
|
+
headers[contentTypeKey] = 'application/json'
|
|
24
34
|
}
|
|
25
35
|
|
|
26
|
-
const contentType = headers[
|
|
36
|
+
const contentType = headers[contentTypeKey] || headers['content-type']
|
|
37
|
+
|
|
38
|
+
if (method === 'GET') {
|
|
39
|
+
try {
|
|
40
|
+
return object2Qs(data) || ''
|
|
41
|
+
} catch (e) {
|
|
42
|
+
throw new Error(JSON.stringify({
|
|
43
|
+
code: ERRORS.INVALID_PARAMS,
|
|
44
|
+
msg: `[${COMPONENT_NAME}.callContainer] invalid data in query method, ${e.message}`,
|
|
45
|
+
}),)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
27
48
|
|
|
28
49
|
switch (contentType) {
|
|
29
50
|
case 'application/json': {
|
|
@@ -39,12 +60,9 @@ export function serializeRequestBody<T>(headers, data: T): T | string {
|
|
|
39
60
|
}
|
|
40
61
|
case 'application/x-www-form-urlencoded': {
|
|
41
62
|
try {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}, [])
|
|
46
|
-
if (list.length) {
|
|
47
|
-
res = list.join('&')
|
|
63
|
+
const qs = object2Qs(data)
|
|
64
|
+
if (qs) {
|
|
65
|
+
res = qs
|
|
48
66
|
}
|
|
49
67
|
} catch (e) {
|
|
50
68
|
throw new Error(JSON.stringify({
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// import decompress from 'brotli/decompress'
|
|
2
|
+
import Go from '../go_wams_exec'
|
|
3
|
+
import { parseURL } from '.'
|
|
4
|
+
|
|
5
|
+
async function instantiateStreaming(resp, importObject, brotliCompressed = false) {
|
|
6
|
+
if (brotliCompressed || !WebAssembly.instantiateStreaming) {
|
|
7
|
+
const source = await (await resp).arrayBuffer()
|
|
8
|
+
if (brotliCompressed) {
|
|
9
|
+
throw new Error('do not support *.br')
|
|
10
|
+
}
|
|
11
|
+
// const buffer = brotliCompressed ? decompress(new Int8Array(source)) : source
|
|
12
|
+
const buffer = source
|
|
13
|
+
return WebAssembly.instantiate(buffer, importObject)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return WebAssembly.instantiateStreaming(resp, importObject)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isBrotliCompressed(url) {
|
|
20
|
+
let brotliCompressed = false
|
|
21
|
+
|
|
22
|
+
let pathname = ''
|
|
23
|
+
try {
|
|
24
|
+
const location = parseURL(url)
|
|
25
|
+
pathname = location.pathname
|
|
26
|
+
} catch (e) {
|
|
27
|
+
pathname = url
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (/\.br$/.test(pathname)) {
|
|
31
|
+
brotliCompressed = true
|
|
32
|
+
}
|
|
33
|
+
return brotliCompressed
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function getExportFunction(url, module, mode = 'go') {
|
|
37
|
+
let importObject = {
|
|
38
|
+
env: {
|
|
39
|
+
memoryBase: 0,
|
|
40
|
+
tableBase: 0,
|
|
41
|
+
memory: new WebAssembly.Memory({
|
|
42
|
+
initial: 256,
|
|
43
|
+
}),
|
|
44
|
+
// table: new WebAssembly.Table({
|
|
45
|
+
// initial: 2,
|
|
46
|
+
// element: 'anyfunc',
|
|
47
|
+
// }),
|
|
48
|
+
},
|
|
49
|
+
...module,
|
|
50
|
+
}
|
|
51
|
+
let go
|
|
52
|
+
const brotliCompressed = isBrotliCompressed(url)
|
|
53
|
+
|
|
54
|
+
if (mode === 'go') {
|
|
55
|
+
go = new Go()
|
|
56
|
+
go._initedModulePromise = new Promise((resolve) => {
|
|
57
|
+
go._initedModuleResolve = resolve
|
|
58
|
+
})
|
|
59
|
+
importObject = {
|
|
60
|
+
...go.importObject,
|
|
61
|
+
env: {
|
|
62
|
+
...go.importObject.env,
|
|
63
|
+
exportModule(module) {
|
|
64
|
+
return go._initedModuleResolve(module)
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const reuslt = await instantiateStreaming(fetch(url), importObject, brotliCompressed)
|
|
71
|
+
|
|
72
|
+
if (mode === 'go') {
|
|
73
|
+
await Promise.race([
|
|
74
|
+
go.run(reuslt.instance),
|
|
75
|
+
new Promise(resolve => setTimeout(() => {
|
|
76
|
+
resolve(null)
|
|
77
|
+
}, 500),),
|
|
78
|
+
])
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
callContainer: (window as any).callContainer,
|
|
82
|
+
initContainer: (window as any).initContainer,
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// if (mode === 'go') {
|
|
87
|
+
// go.run(reuslt.instance)
|
|
88
|
+
// const module = await go._initedModulePromise
|
|
89
|
+
// return module
|
|
90
|
+
// }
|
|
91
|
+
|
|
92
|
+
return reuslt.instance.exports
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function loadJSExportFunction(config?: { vm: string; vender?: string }) {
|
|
96
|
+
const { vm, vender } = config || {}
|
|
97
|
+
const VENDER_KEY = 'cloudbase_private_link_vender'
|
|
98
|
+
|
|
99
|
+
if (vender || !Object.prototype.hasOwnProperty.call(document.defaultView, VENDER_KEY)) {
|
|
100
|
+
await loadUmdModule(
|
|
101
|
+
vender
|
|
102
|
+
|| 'https://cdn.jsdelivr.net/npm/@cloudbase/privatelink-vender@0.0.1-alpha.3/dist/cdn/cloudbase.privatelink.vender.js',
|
|
103
|
+
VENDER_KEY,
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return loadUmdModule(
|
|
108
|
+
vm || 'https://cdn.jsdelivr.net/npm/@cloudbase/privatelink@0.0.1-alpha.0/dist/cdn/cloudbase.privatelink.vm.js',
|
|
109
|
+
'cloudbase_private_link',
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function loadUmdModule(jsUrl: string, umdModuleName: string, targetDoc: Document = document) {
|
|
114
|
+
return new Promise<any>((resolve, reject) => {
|
|
115
|
+
const win = targetDoc.defaultView
|
|
116
|
+
|
|
117
|
+
const script = targetDoc.createElement('script')
|
|
118
|
+
script.setAttribute('src', jsUrl)
|
|
119
|
+
script.setAttribute('class', umdModuleName)
|
|
120
|
+
script.addEventListener('load', () => {
|
|
121
|
+
if (Object.prototype.hasOwnProperty.call(win, umdModuleName)) {
|
|
122
|
+
return resolve(win[umdModuleName as any])
|
|
123
|
+
}
|
|
124
|
+
const error = new Error(`Fail to load UMD module ${umdModuleName} from [${jsUrl}].`)
|
|
125
|
+
return reject(error)
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
script.addEventListener('error', (e) => {
|
|
129
|
+
const error = new Error(`main bundle [${umdModuleName}] load failed from [${jsUrl}]: ${e?.message || ''}`)
|
|
130
|
+
reject(error)
|
|
131
|
+
})
|
|
132
|
+
if (targetDoc.body) {
|
|
133
|
+
targetDoc.body.appendChild(script)
|
|
134
|
+
} else {
|
|
135
|
+
targetDoc.head.appendChild(script)
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const webpack = require('webpack')
|
|
2
|
+
const TerserPlugin = require('terser-webpack-plugin')
|
|
3
|
+
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
|
4
|
+
|
|
5
|
+
module.exports = function (options) {
|
|
6
|
+
const { context, entry, output, mode, watch, externals, definePlugin = {}, optimization = {} } = options
|
|
7
|
+
const isDevelopment = mode !== 'production'
|
|
8
|
+
let plugins = [
|
|
9
|
+
// new WatchRunPlugin()
|
|
10
|
+
new webpack.DefinePlugin(
|
|
11
|
+
Object.assign(
|
|
12
|
+
{
|
|
13
|
+
'globalThis.IS_MP_BUILD': false,
|
|
14
|
+
},
|
|
15
|
+
definePlugin,
|
|
16
|
+
),
|
|
17
|
+
),
|
|
18
|
+
// new BundleAnalyzerPlugin(),
|
|
19
|
+
].filter((item) => !!item)
|
|
20
|
+
return {
|
|
21
|
+
context,
|
|
22
|
+
entry,
|
|
23
|
+
mode,
|
|
24
|
+
watch,
|
|
25
|
+
watchOptions: {
|
|
26
|
+
ignored: [output.path],
|
|
27
|
+
},
|
|
28
|
+
output,
|
|
29
|
+
externals,
|
|
30
|
+
cache: {
|
|
31
|
+
type: 'memory',
|
|
32
|
+
},
|
|
33
|
+
devtool: false,
|
|
34
|
+
resolve: {
|
|
35
|
+
extensions: ['.ts', '.js', '.json'],
|
|
36
|
+
},
|
|
37
|
+
module: {
|
|
38
|
+
rules: [
|
|
39
|
+
{
|
|
40
|
+
test: /\.ts$/,
|
|
41
|
+
exclude: [/node_modules/],
|
|
42
|
+
use: ['babel-loader', 'ts-loader'],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
test: /\.js$/,
|
|
46
|
+
exclude: [/node_modules/],
|
|
47
|
+
use: ['babel-loader'],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
test: /package\.json$/,
|
|
51
|
+
loader: 'package-json-cleanup-loader',
|
|
52
|
+
options: {
|
|
53
|
+
only: ['version'],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
noParse: [/sjcl\.js$/],
|
|
58
|
+
},
|
|
59
|
+
plugins,
|
|
60
|
+
optimization: {
|
|
61
|
+
moduleIds: 'deterministic',
|
|
62
|
+
emitOnErrors: false,
|
|
63
|
+
removeEmptyChunks: true,
|
|
64
|
+
usedExports: true,
|
|
65
|
+
splitChunks: false,
|
|
66
|
+
...optimization,
|
|
67
|
+
...(isDevelopment
|
|
68
|
+
? {
|
|
69
|
+
minimize: false,
|
|
70
|
+
removeAvailableModules: false,
|
|
71
|
+
concatenateModules: true,
|
|
72
|
+
}
|
|
73
|
+
: {
|
|
74
|
+
minimizer: [
|
|
75
|
+
new TerserPlugin({
|
|
76
|
+
test: /\.js(\?.*)?$/i,
|
|
77
|
+
cache: false,
|
|
78
|
+
parallel: true,
|
|
79
|
+
}),
|
|
80
|
+
],
|
|
81
|
+
}),
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
|
|
3
|
+
const params = {
|
|
4
|
+
context: path.resolve(__dirname, '../../'),
|
|
5
|
+
mode: 'production',
|
|
6
|
+
watch: false,
|
|
7
|
+
entry: path.resolve(__dirname, '../src/index.ts'),
|
|
8
|
+
output: {
|
|
9
|
+
path: path.resolve(__dirname, '../dist/miniprogram'),
|
|
10
|
+
filename: 'index.js',
|
|
11
|
+
library: `cloudbase_container`,
|
|
12
|
+
libraryTarget: 'umd',
|
|
13
|
+
umdNamedDefine: true,
|
|
14
|
+
globalObject: 'typeof window !== "undefined"?window:this',
|
|
15
|
+
},
|
|
16
|
+
externals: {},
|
|
17
|
+
definePlugin: {
|
|
18
|
+
'globalThis.IS_MP_BUILD': true, // 注入环境变量,用于业务代码判断
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = require('./web.prod.js')(params)
|