现在客户有一个需求,要在我们的一个包 /package ( React, typescript,编写的,用于显示数据的),展示数据的之前,要从客户的一个服务器上,下载一个.js 文件,执行一下,生成一些数据,导入到我们的数据中,然后再渲染展示数据。
这个 js 文件,是动态决定的。甚至可能不止一个。
这个有没有比较好的实践方法?
1
puzzle9 2022-03-31 11:39:41 +08:00
无头浏览器?
|
2
terranboy 2022-03-31 11:45:01 +08:00
定时任务?
|
3
nicevar 2022-03-31 11:53:49 +08:00
在客户端执行?看 js 多复杂了,简单的 js 解释器就行,如果复杂的话创建一个不可见的 webview 来处理,服务端可以用 headless chrome 。
|
4
shintendo 2022-03-31 11:58:04 +08:00
创建 script 标签不就行了
|
5
DrakeXiang 2022-03-31 11:59:03 +08:00
为啥不能在服务端干这个,客户端的话只能 eval 了吧,看起来挺不安全的样子
|
6
crysislinux 2022-03-31 12:01:33 +08:00
动态 import 就可以了,如果文件名会变化或者可能会加载多个文件,可以先 import 一个动态的列表,然后再根据列表 import 其他的。以前我用 systemjs 做过,现在可以用 dynamic import
|
7
ysc3839 2022-03-31 12:04:52 +08:00
先说清楚运行环境?是浏览器吗?
|
8
3dwelcome 2022-03-31 12:05:51 +08:00
|
9
3dwelcome 2022-03-31 12:08:43 +08:00
而且浏览器环境下,chrome 插件拥有至高无上的权利,JS 代码随时随地会被入侵。
本来就没指望 JS 运行绝对的安全,用个 eval 或者创建 script 标签,都是常规操作了。 |
10
seakingii 2022-03-31 12:36:44 +08:00
浏览器的话,可以动态插入 script 到 dom 里.
var script = document.createElement('script'), script.type = 'text/javascript'; .... 后面自己搞定 |
11
Puteulanus 2022-03-31 13:15:49 +08:00 1
这不就是 JSONP 吗
|
12
icyalala 2022-03-31 13:24:48 +08:00 4
@3dwelcome 它要是拿了用户 token 传走,或者挂马攻击别人,再或者挂个挖矿的导致运营商封禁,这都有可能啊。
对面这种显然没有安全意识,如果你选择相信对面,结果对面被攻击了导致你程序影响用户,那最终你还得背锅。 另外浏览器插件里面乱搞这个屡见不鲜了: https://www.v2ex.com/t/390135 ,但使用插件的时候你的角色是用户,不是开发者了,你可以做出合理选择来保护自己。 |
13
DOLLOR 2022-03-31 13:53:15 +08:00
第三方应该只提供接口返回数据,而不是返回 js 代码。
|
14
dany813 2022-03-31 14:19:45 +08:00
6 楼说的不错,如果就一个 js 直接动态加载就行,你现在是没发确定有多少个 js ,需要一个 js 映射文件
|
15
libook 2022-03-31 14:37:38 +08:00
JS 动态在 DOM 树里插 script 标签就行。
或者浏览器比较新就动态 import 。 当然安全问题还是得考虑的,否则会有扯皮风险,可以考虑让客户的服务端提供处理数据的接口,或者前端加个沙盒机制从沙盒里跑客户的 js 文件。 |
16
ychost 2022-03-31 14:50:46 +08:00
为啥一定要 js ,他们给接口返回 JSON 不行吗,js 太 hack 了
|
18
yazoox OP @libook
"或者前端加个沙盒机制从沙盒里跑客户的 js 文件。"兄弟,这段话是什么意思?怎么在前端添加沙盒? 开一个 worker.js ?跑在这个里面,然后通过 postmessage 通讯?,etc. |
19
seakingii 2022-03-31 17:27:23 +08:00
@yazoox 动态导入的 JS 你们约定好,里面有约定好的方法
比如你动态导入一个名字为 get_user_info_1.js ,里面必定有个同名的方法 get_user_info1_(你传入的数据) |
20
seakingii 2022-03-31 17:28:45 +08:00
@yazoox
下面是例子代码,不一定能直接跑,没测试过 ``` function importJsFile(jsUrl){ let jsId = hash(jsUrl);//根据 jsUrl 生成一个唯一的 hash 值,避免重复 import if(document.getElementById(jsId)) return; let newElement=document.createElement("script"); newElement.type="text/javascript"; newElement.id = jsId; newElement.src=jsUrl; var head=document.getElementsByTagName("head")[0]; head.appendChild(newElement); } function importJsAndInvoke(userId){ let functionName = 'get_user_info_1'; let jsUrl = 'http://baidu.com/js/get_user_info_1.js'; //导入外部 JS importJsFile(jsUrl); //调用外部 JS 里的一个方法 let result = window[functionName](userId); console.dir(result); } ``` |
21
libook 2022-03-31 18:39:39 +08:00
@yazoox #16 我没有具体做过,我的思路就是用 WebWorkers 、WebAssembly 等天然提供沙盒的机制来跑,注意它们的沙盒基本是运行方面的隔离,一些同域的资源也可能可以访问,具体可以去 MDN 上仔细研究一下。
还可以找找看有没有一些前端沙盒的库,我听说 Deno 可以在浏览器端作为一个沙盒环境运行(本质好像也是 WebAssembly ),本人没用过,你可以去看一下是不是满足需要。 沙盒和外界程序之间使交流用 postmessage 等机制,对数据交流进行严格管制,就可以避免安全问题,同时记得记录关键日志(可以从前端发到你们自己的日志服务器),以便于审计和回溯。 |
22
yazoox OP |
23
han3sui 2022-04-01 17:25:33 +08:00
npm i loadjs
|
24
SmiteChow 2022-04-02 16:05:21 +08:00
|