【问题标题】:Correctly accessing django static files from external javascript从外部 javascript 正确访问 django 静态文件
【发布时间】:2018-05-28 12:13:24
【问题描述】:

我有一个使用 AngularJS 和一堆 JavaScript 和模板文件的 django 应用程序。

在我的 django 模板中,我可以使用 {% static %} 标记来正确引用这些文件,如下所示:

<script src="{% static "angular/myapp.app.js" %}"></script>

但是,外部文件本身显然是do not get resolved through django's templating framework,所以这不是一个选项。所以人们最常做的就是硬编码那里的静态路径:

$routeProvider.when('/', {
   // this works but is not ideal
   templateUrl: '/static/pages/some-angular-template.html',  
})

我已经看到将STATIC_URL 加载到某个地方的javascript 并使用它来构造引用的建议。像这样的:

Django 模板

var STATIC_URL = {{ STATIC_URL }};
function getStaticUrl(templatePath) {
  return STATIC_URL + templatePath;
}

外部 JS

$routeProvider.when('/', {
   templateUrl: getStaticUrl('/pages/some-angular-template.html'),
})

这有点好,但仍然不完美,因为它只处理基本路径。如果您想使用 ManifestStaticFilesStorage 之类的东西(我会这样做),那么您仍然无法获得正确的文件分辨率。

这个问题有什么好的解决办法吗?我正在考虑的选项:

  • 将所有必要的 URL 引导到 django 模板内的 JS 变量中
  • 使用data标签(同样通过django模板)将url存储在一些隐藏的HTML标记中
  • 创建一个 API 来获取 URL(这看起来很疯狂,而且在性能方面会很糟糕)。

只是想知道是否有解决此问题的标准做法或库?我已经多次遇到这个问题,但从未找到满意的解决方案。

【问题讨论】:

  • 如果使用清单存储,这尤其棘手

标签: angularjs django django-staticfiles


【解决方案1】:

其他选项 1

使用您的getStaticUrl 函数,但使其也附加一个查询字符串,如?v=abc,其中abc 对于您的应用程序的每个部署版本都是唯一的,以破坏缓存。 (例如,您的 html 定义了window.ASSET_VERSION = 'abc',当您部署应用的新版本时,您的 html 定义了window.ASSET_VERSION = 'xyz'。)

优点:

  • 不需要庞大的全局字典。
    • 不需要维护。
    • 在一个地方寻找应用程序的用户(包括恶意用户)对应用程序的了解较少(如果重要的话)。 可能会节省服务器成本。

缺点:

  • 在部署新版本应用的过程中,当用户访问网站时,他们的浏览器会收到新的静态资源和旧的 html,不匹配可能会导致用户遇到错误。
  • 如果您使用 CDN,例如 CloudFront,则必须将其配置为在缓存键中包含查询字符串。
  • 可能无法进行 A/B 测试?
  • 在部署新版本应用时,必须先上传新的静态资源,然后再部署新的html服务器,否则旧静态资源会被部分用户长期误用。 (如果用户在部署期间访问您的站点,他们的浏览器将收到新的 html 和旧的静态资产,将使用新的查询字符串缓存这些旧资产,并将继续使用这些旧资产,直到用户手动清除缓存,缓存响应过期,或发生下一次部署。)

其他选项 2

类似于“创建 API 以获取 URL”:将包含 URL 的字典放入静态 json 文件中,并使您的 getStaticUrl 函数返回一个 Promise,该 Promise 在它获取 json 文件后解析为请求的 url。将版本 id 放在 json 文件名或缓存清除查询字符串(见上文)中,以便可以缓存 json 文件。

优点:

  • 性能可能会更好,因为 URL 数据缓存在浏览器中。
  • 可能会节省服务器成本。

缺点:

  • 所有需要这些 URL 之一的 JavaScript 都必须异步。 (可能会破坏交易。)
    • 软件工程师必须花费更多时间(昂贵)。

【讨论】:

    【解决方案2】:

    我当前的解决方案(即使不是最优雅的也可以正常工作)只是在 django 模板中创建一个巨大的全局常量字典,然后直接在 JS 中引用它们。

    Django 模板

    <script type="text/javascript">
        NG_STATIC_FILES = {
           "HOME": "{% static '/pages/home.html' %}",
           "SOMETHING_ELSE": "{% static '/pages/some-angular-template.html' %}",
        };
    </script>
    

    外部 JS

    $routeProvider.when('/', {
        templateUrl: NG_STATIC_FILES.SOMETHING_ELSE,
    })
    

    等等

    【讨论】:

    • 正在考虑做同样的事情,然后找到了你的答案。非常适合我。
    • 如果您打算这样做,使用未翻译的路径作为NG_STATIC_FILES 字典中的键可能会更简单。然后,您可以创建这些路径的列表并通过迭代该列表来生成字典,将已翻译的路径(值)分配给未翻译的路径(键)。
    猜你喜欢
    • 2017-12-23
    • 2017-12-06
    • 1970-01-01
    • 2011-02-25
    • 2013-11-22
    • 2021-05-20
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多