大家有没有在自己的代码里面,动态的下载并执行一段第三方的 js 文件或者代码? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
yazoox
V2EX    Javascript

大家有没有在自己的代码里面,动态的下载并执行一段第三方的 js 文件或者代码?

  •  
  •   yazoox 2022-03-31 11:34:56 +08:00 4070 次点击
    这是一个创建于 1364 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在客户有一个需求,要在我们的一个包 /package ( React, typescript,编写的,用于显示数据的),展示数据的之前,要从客户的一个服务器上,下载一个.js 文件,执行一下,生成一些数据,导入到我们的数据中,然后再渲染展示数据。

    这个 js 文件,是动态决定的。甚至可能不止一个。

    这个有没有比较好的实践方法?

    24 条回复    2022-04-02 16:05:21 +08:00
    puzzle9
        1
    puzzle9  
       2022-03-31 11:39:41 +08:00
    无头浏览器?
    terranboy
        2
    terranboy  
       2022-03-31 11:45:01 +08:00
    定时任务?
    nicevar
        3
    nicevar  
       2022-03-31 11:53:49 +08:00
    在客户端执行?看 js 多复杂了,简单的 js 解释器就行,如果复杂的话创建一个不可见的 webview 来处理,服务端可以用 headless chrome 。
    shintendo
        4
    shintendo  
       2022-03-31 11:58:04 +08:00
    创建 script 标签不就行了
    DrakeXiang
        5
    DrakeXiang  
       2022-03-31 11:59:03 +08:00
    为啥不能在服务端干这个,客户端的话只能 eval 了吧,看起来挺不安全的样子
    crysislinux
        6
    crysislinux  
       2022-03-31 12:01:33 +08:00
    动态 import 就可以了,如果文件名会变化或者可能会加载多个文件,可以先 import 一个动态的列表,然后再根据列表 import 其他的。以前我用 systemjs 做过,现在可以用 dynamic import
    ysc3839
        7
    ysc3839  
       2022-03-31 12:04:52 +08:00
    先说清楚运行环境?是浏览器吗?
    3dwelcome
        8
    3dwelcome  
       2022-03-31 12:05:51 +08:00
    @DrakeXiang 为什么都说客户端用 eval 不安全呢,我觉得挺安全啊。

    又不是服务器远程调用 RPC 不安全,本地就算 JS 被注入修改,也不会影响到其他用户。
    3dwelcome
        9
    3dwelcome  
       2022-03-31 12:08:43 +08:00
    而且浏览器环境下,chrome 插件拥有至高无上的权利,JS 代码随时随地会被入侵。

    本来就没指望 JS 运行绝对的安全,用个 eval 或者创建 script 标签,都是常规操作了。
    seakingii
        10
    seakingii  
       2022-03-31 12:36:44 +08:00
    浏览器的话,可以动态插入 script 到 dom 里.

    var script = document.createElement('script'),
    script.type = 'text/Javascript';


    ....

    后面自己搞定
    Puteulanus
        11
    Puteulanus  
       2022-03-31 13:15:49 +08:00   1
    这不就是 JSONP 吗
    icyalala
        12
    icyalala  
       2022-03-31 13:24:48 +08:00   4
    @3dwelcome 它要是拿了用户 token 传走,或者挂马攻击别人,再或者挂个挖矿的导致运营商封禁,这都有可能啊。
    对面这种显然没有安全意识,如果你选择相信对面,结果对面被攻击了导致你程序影响用户,那最终你还得背锅。

    另外浏览器插件里面乱搞这个屡见不鲜了: t/390135 ,但使用插件的时候你的角色是用户,不是开发者了,你可以做出合理选择来保护自己。
    AV1
        13
    AV1  
       2022-03-31 13:53:15 +08:00
    第三方应该只提供接口返回数据,而不是返回 js 代码。
    dany813
        14
    dany813  
       2022-03-31 14:19:45 +08:00
    6 楼说的不错,如果就一个 js 直接动态加载就行,你现在是没发确定有多少个 js ,需要一个 js 映射文件
    libook
        15
    libook  
       2022-03-31 14:37:38 +08:00
    JS 动态在 DOM 树里插 script 标签就行。
    或者浏览器比较新就动态 import 。

    当然安全问题还是得考虑的,否则会有扯皮风险,可以考虑让客户的服务端提供处理数据的接口,或者前端加个沙盒机制从沙盒里跑客户的 js 文件。
    ychost
        16
    ychost  
       2022-03-31 14:50:46 +08:00
    为啥一定要 js ,他们给接口返回 JSON 不行吗,js 太 hack 了
    yazoox
        17
    yazoox  
    OP
       2022-03-31 17:12:38 +08:00
    @seakingii 如果这段 js 运行完,有返回值,比如回返一个 json 文件,怎么获取到呢?
    yazoox
        18
    yazoox  
    OP
       2022-03-31 17:18:23 +08:00
    @libook
    "或者前端加个沙盒机制从沙盒里跑客户的 js 文件。"兄弟,这段话是什么意思?怎么在前端添加沙盒?
    开一个 worker.js ?跑在这个里面,然后通过 postmessage 通讯?,etc.
    seakingii
        19
    seakingii  
       2022-03-31 17:27:23 +08:00
    @yazoox 动态导入的 JS 你们约定好,里面有约定好的方法

    比如你动态导入一个名字为 get_user_info_1.js ,里面必定有个同名的方法 get_user_info1_(你传入的数据)
    seakingii
        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);

    }
    ```
    libook
        21
    libook  
       2022-03-31 18:39:39 +08:00
    @yazoox #16 我没有具体做过,我的思路就是用 WebWorkers 、WebAssembly 等天然提供沙盒的机制来跑,注意它们的沙盒基本是运行方面的隔离,一些同域的资源也可能可以访问,具体可以去 MDN 上仔细研究一下。
    还可以找找看有没有一些前端沙盒的库,我听说 Deno 可以在浏览器端作为一个沙盒环境运行(本质好像也是 WebAssembly ),本人没用过,你可以去看一下是不是满足需要。

    沙盒和外界程序之间使交流用 postmessage 等机制,对数据交流进行严格管制,就可以避免安全问题,同时记得记录关键日志(可以从前端发到你们自己的日志服务器),以便于审计和回溯。
    yazoox
        22
    yazoox  
    OP
       2022-04-01 09:01:00 +08:00
    @seakingii
    let result = window[functionName](userId);
    加载的 script 中的函数是通过 window[name]访问的啊。got it. thx

    @libook 嗯,用 WebWorkers 试试~ thx
    han3sui
        23
    han3sui  
       2022-04-01 17:25:33 +08:00
    npm i loadjs
    SmiteChow
        24
    SmiteChow  
       2022-04-02 16:05:21 +08:00
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2936 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 13:47 PVG 21:47 LAX 05:47 JFK 08:47
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86