"About the fact that after I set up cross-domain resource sharing, it is still cross-domain"

origin

There is a department in our company that needs to do micro front-end, and there is a JS link for both the main application and the sub-application, but whether the JS of the sub-application is found to be cross-domain during deployment. image.pngAnd there is no problem when the sub-application is started alone.

Since it is a cross-domain problem, go to OSS to see if cross-domain is set. image.pngIt is found that cross-domain has been set up.image.png

At this time, the careful friends have found the problem and thought of a solution

decrypt

There are three reasons for this problem:

  • Micro frontend loading sub-application process
  • Cloud vendor strategy
  • Browser Caching Policy

Micro front terminal application process

image.pngCareful friends will find that the JS of the main application typeis script, but the JS of the sub- typeapplication is of fetchtype , which involves the process of loading sub-applications in the micro-frontend.

The entrance of the micro-frontend is an html address. In order to achieve JS sandbox and CSS isolation, the basic process is:

  1. First get the HTML text content
  2. Analyze HTML text content and get an array of JS and CSS links for external links
  3. Iterate over the array to fetchget each JS and CSS text via
  4. Execute JS text through eval function, and implement sandbox through proxy window object; CSS increases isolation by adding prefix

Let's take qiankun as an example to see the process of obtaining JS links:image.png

Source: github.com/kuitos/impo…

So the sub-app's typeis fetchnot normal script.

But if you think that it is fetchonly cross-domain, but fetchthere is no problem with it alone.image.png image.png

Cloud vendor strategy

我测试了两家国内知名云厂商,发现都是如下策略:对于非跨域请求,则不返回跨域头,对于跨域请求才返回跨域头。 image.png image.png 当然其目的当然是好的,因为跨域的情况下,在未设置 Access-Control-Max-Age或者其值过期的情况下,就算文件未改变的情况下,还是会导致发起请求,询问是否跨域,增加了请求量。

但是到这里我们还是不明白为什么两个同时请求时,就会 GG。 image.png

浏览器缓存策略

image.png 我们仔细观察报错的请求,发现 fetch 请求只有 Response Headers并没有 Request Headers,怎么回事呢?

原因也很简单,就是因为浏览器没有发起请求,此请求被认为其和上一个 JS 是同一个资源,所以返回了上一个请求的 Response。

真相大白

image.png 通过上述三点分析我们已经彻底明白了:

  • 首先是微前端的主应用先通过 script 请求到 JS,(云厂商 Response 里没有跨域头)
  • 然后微前端框架通过 fetch 方式获取子应用的 JS
  • 然后浏览器发现这个资源加载过了,于是就返回了 script 的 Response,但是由于没有跨域头,所以浏览器就报了跨域错误。

解决方案

1、子应用区分开发和生产环境

由于是同一份 JS,其实子应用没有必要重新加载一遍的,我们可以通过类似 html-webpack-plugin区分开发环境和生产环境。

  • 当子应用本地开发时,将 JS 添加到 HTML 模板中;
  • 当生产构建环境时,不将其打进,如此就可以完美解决上述问题。

2、资源无缓存

我们知道了,本质上其由于浏览器缓存策略引起的,那我们就可以增加 cache-control: no-cache 的方式,不允许浏览器利用缓存,也可以完美解决这个问题。 image.png

坏处:会导致流量增加

3. The main application script adds crossoriginattributes

Since the fetchrequest reuses the first response result, it would be fine if it returns the result with the cross-domain header for the first time, so we can let the script return the cross-domain header information through the crossorigin header.image.png

4. Increasevary: origin

image.pngWe saw that in Alibaba Cloud's cross-domain settings, there is a selection box that allows you to choose whether to add vary: originthis header.

Vary is an HTTP response header that determines whether a cached response should be used or a new response should be requested from the origin server for a future request header. It is used by the server to indicate which headers should be used when selecting a resource representative in the content negotiation algorithm.

So why Vary: originis it possible to distinguish between fetchrequest scriptand ?

It turns out that there scriptis no originsuch request header, and the fetch method is forced to be added by the browser because it is cross-domain Origin. image.png image.pngBecause of the vary: originresponse header, it leads to fetch and can reuse scriptthe response of the request, so it also avoids cross-domain.

concluding remarks

Although the problem is small, it still brings out a lot of knowledge. Have you learned it?20210720140344_ee130.jpg

Guess you like

Origin juejin.im/post/7079402762730995742