如何使用 ManifestStaticFilesStorage 从散列中排除路径

How to exclude paths from hashing with ManifestStaticFilesStorage

我参与了一个使用 whitenoise 提供静态文件的应用程序。它被配置为使用 CompressedManifestStaticFilesStorage,后者又使用 ManifestStaticFilesStorage.

静态文件是指我们提供的静态文件,以及来自第三方的leaflet等库

Django 提供的 ManifestStaticFilesStorage class 将重命名文件名以包含散列。用于缓存清除。它过滤资源并更改对文件的未散列引用以包含散列。

这又破坏了 leaflet 中的一个函数:

_detectIconPath: function () {
    var el = DomUtil.create('div',  'leaflet-default-icon-path', document.body);
    var path = DomUtil.getStyle(el, 'background-image') ||
               DomUtil.getStyle(el, 'backgroundImage'); // IE8

    document.body.removeChild(el);

    return path.indexOf('url') === 0 ?
        path.replace(/^url\([\"\']?/, '').replace(/marker-icon\.png[\"\']?\)$/, '') : '';
}

问题是 path 的值看起来像:

url("https://example.org/static/path/leaflet/dist/images/marker-icon.2273e3d8ad92.png")

由于文件名不匹配,第二次替换不会做任何事情。这反过来将 return:

https://example.org/static/path/leaflet/dist/images/marker-icon.2273e3d8ad92.png")

当 leaflet 尝试将文件名附加到此 "directory" 时,我们得到:

https://example.org/static/path/leaflet/dist/images/marker-icon.2273e3d8ad92.png")marker-icon.png

这显然是错误的。

那么解决方法是什么?我被告知我们不应该尝试散列第三方包的文件名,可能会有其他破坏。但是我没有看到 ManifestStaticFilesStorage 的任何选项来排除某些目录被散列。

我创建了以下 class 来尝试解决这个问题。我在设置中引用此 class 而不是 CompressedManifestStaticFilesStorage.

class MyStorage(CompressedManifestStaticFilesStorage):
    """ This class overrides the built in class and turns off file name hashing for selected directories. """

    def _nonhashed_name_func(self, name, hashed_files=None):
        name = posixpath.normpath(name)
        cleaned_name = self.clean_name(name)
        return cleaned_name

    def _url(self, hashed_name_func, name, force=False, hashed_files=None):
        split = name.split("/")
        if split[0] in ['bower_components', 'node_modules']:
            hashed_name_func = self._nonhashed_name_func
        return super()._url(hashed_name_func=hashed_name_func, name=name, force=force, hashed_files=hashed_files)

这可行,但似乎是一个不太优雅的解决方案。这里有没有人有更好的建议?

我在 Angular2 的上下文中找到了描述类似问题的页面:

https://www.npmjs.com/package/@asymmetrik/angular2-leaflet#a-note-about-markers

在传单的特定情况下,解决方案似乎是覆盖默认图标路径。当我使用 vue2-leaflet 时,可以使用:

<v-icondefault :image-path="path"></v-icondefault>

根据随源代码提供的 example

Leaflet 项目认可 leaflet-defaulticon-compatibility 作为此问题的官方解决方案。

Retrieve all Leaflet Default Icon options from CSS, in particular all icon images URL's, to improve compatibility with bundlers and frameworks that modify URL's in CSS. In particular for webpack (with style-, css-, file- and url-loader's), Rails Asset Pipeline and Django pipeline. Should solve all use cases linked to issue #4968. (Source)