运行远程文件(远程方法调用rmi)

最近项目里需要依赖 200 多个 json 文件,每次打包的时候都会编译成几十个 js 文件,这样打完包导致项目体积非常大。并且在第一次加载加载页面的时候,那些 js 文件也都会一并加载,占用非常多的网络资源。

那我们能不能减少生产包大小,减少首次渲染的请求,说直白一些就是优化整个项目的 json 文件,把 json 文件放到静态服务器,需要的时候引入文件即可。

直接 import

当然下意识的就想到了 import(\\’https://…china.json\\’) 这样直接调用静态服务器资源,当做模块引用来处理了。但 import 有个限制,就是导入的方法或者文件,它是依赖于本地环境的,必须在编译阶段可以解析路径。

所以 import 不允许引入外部链接文件,如果直接引入的话会报错:

Can\\\'t resolve \\\'https://...\\\'

在编译阶段不能通过,所以 import 的方法不能用。import 不行,相应 require 也不可以,所以 import 和 require 的方法直接宣告失败。

我们的主要目的是减少首次请求,这个问题可以配置 webpack 的按需引入 … 此处不详细探讨,这也不是文章的重点。重点是,如何 import 一个外部文件到项目里。

Jsonp 下载

在项目里,每次需要使用 json 文件的时候,执行一个方法,去创建 script 标签,在 src 上赋值外部链接,再插入到 head 里面。因为 script 是没有跨域限制的,所以我们访问外部链接是没有问题,我们可以下载 js、json 文件。

虽然我们可以下载文件,但还是获取不到文件的内容。这样呢,只是下载了文件,如果外部链接是 js 自执行函数还好,可以直接执行文件。

那怎样执行呢?或者是说怎样获取里面的内容呢?我们可以让 js 文件返回 callback 方法,之前文章写过 jsonp 的解决方案。

想要获取远程文件内容,需要和后端约定好,文件返回的 callback 函数,但这也只仅限于 js 文件,而我项目需要使用的是 json 文件,我总不能一个文件一个文件转成 js ,并重新写 callback 函数吧?

这一听起来就不可取,这种方式的局限性在于:只适用于 js 文件,并且还要约定好 calback 方法名。

如果页面只需要执行一个或某些个 js 文件那还好说,我们可以使用创建 script 标签的方法。这样可以动态的调用到 js 文件,需要在什么时候引用,就什么时候引用。

创建 script 标签,来实现访问外部链接的具体代码:

const loadMapJson = (url: string) =>new Promise((resolve) => {    const script = document.createElement(\\\'script\\\')    script.type = \\\'text/javascript\\\'    script.src = url    script.onerror = () => {        window.history.back()    }    script.onload = (res) => {        resolve(res)    }    document.head.appendChild(script)})
XMLHttpRequest

好,回到我最终的问题上。如何动态引入我需要的 json 文件?

我最终借用的是 XMLHttpRequest 方法。

使用 Request 方法去请求下载静态服务器文件。我先用了一个 CDN 的地址去测试,可以正常调用,并且可以获取到文件内容。

如果是创建 script 标签,那就不需要考虑跨域问题,但现在走的是 Request 方法,面临跨域问题。

这种方法可以请求到 js、json 等格式的数据,但有一个跨域问题需要注意下。跨域的解决方案之前也提过,可以使用 jsonp 方案,但还是针对于 js 文件来做。

目前的 json 文件,是后端同事帮忙放开了线上域名和本地域名端口,上传到静态服务器的资源只允许某些个域名访问,这样来实现一些简单的安全策略。

XMLHttpRequest 的解决方案代码:

const getJsonFile = (url: string) =>new Promise((resole, reject) => {    const xhr = new XMLHttpRequest()    xhr.open(\\\'GET\\\', url, true)    xhr.overrideMimeType(\\\'application/json\\\')    xhr.send(null)    xhr.onreadystatechange = () => {        if (xhr.readyState === 4) {            if (xhr.status === 200) {                resole(xhr.responseText)            } else {                reject(xhr)            }        }    }})export default getJsonFile

这样最终实现了打包体积直线下降,打包速度也快了很多,最主要的是解决了动态引入 json 文件的功能。

点击关注公众号,查看更多 Vue 的内容

图片授权基于 www.pixabay.com 相关协议

原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34563.html

(0)
小道研究's avatar小道研究
上一篇 2024年4月21日 上午10:36
下一篇 2024年4月21日 上午10:38

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注