【问题标题】:How can I tell grunt-usemin to ignore Django's static template tags?如何告诉 grunt-usemin 忽略 Django 的静态模板标签?
【发布时间】:2013-08-17 15:42:38
【问题描述】:

我正在构建一个为单页 Angular 应用提供服务的 Django 应用。

Django 服务的 Angular 的 index.html 具有以下 usemin 脚本块:

<!-- build:js scripts/scripts.js -->
<script src="{% static "scripts/app.js" %}"></script>
<script src="{% static "scripts/controllers/main.js" %}"></script>
<script src="{% static "scripts/controllers/stats.js" %}"></script>
<script src="{% static "scripts/directives/highchart.js" %}"></script>
<!-- endbuild -->

Usemin 尝试在文件系统上查找“{% static "scripts/app.js" %}”,当然失败了,因为它真正应该尝试查找的是“scripts/app.js”。

有没有人看到解决方法?

【问题讨论】:

  • 您是否使用grunt build 构建了站点,不应该向客户端提供usemin 块,这仅用于grunt,与后端无关(afaik)。
  • 我正在尝试利用 Django 对静态 url 的反向 url 查找,所以我从 Django 路由提供 Angular 的 index.html,这允许我在 index.html 中使用 Django 模板标签。 html。我已经放弃了,现在将从静态 url 访问 index.html,而不是正确的 Django 路由。我会咬紧牙关,如果我的静态文件 url 发生变化,我会手动更新 index.html。
  • @davemckenna01 自从您最初问到 8 月以来,您在这方面有什么新发现吗?我目前正在将 grunt/yeoman 与 Angular 一起使用,并将工作流与 django 集成让我的速度慢了很多。
  • @kvseelbach 我也有同样的问题。您找到解决方法了吗?
  • @lakenen 我想继续使用 Grunt 和生成器,所以我编辑了配置并安装了 grunt-text-replace 并设置了一些搜索/替换。 replace: { example: { src: ['&lt;%= yeoman.dist %&gt;/*.html'], overwrite: true, replacements: [{ from: '&lt;script src="scripts', to: '&lt;script src="/static/mdb/scripts' }] } }

标签: django angularjs django-templates gruntjs grunt-usemin


【解决方案1】:

好的,我想我有一个解决方法。这是假设您希望构建的文件也指向构建资产的静态 url。

这将要求您在视图上下文中定义一个 STATIC_URL(而不是使用 src="{% static 'foo/bar.js' %}",您将使用 src="{{STATIC_URL}}foo/bar.js")。如果不破解 grunt-usemin 源,我无法让 {% static %} 工作。

所以用你的例子,这个:

<!-- build:js {{STATIC_URL}}scripts/scripts.js -->
<script src="{{STATIC_URL}}scripts/app.js"></script>
<script src="{{STATIC_URL}}scripts/controllers/main.js"></script>
<script src="{{STATIC_URL}}scripts/controllers/stats.js"></script>
<script src="{{STATIC_URL}}scripts/directives/highchart.js"></script>
<!-- endbuild -->

编译为:

<script src="{{STATIC_URL}}scripts/scripts.js"></script>

为了实现这一点,我必须添加以下 grunt 配置(在 Gruntfile.js 中):

// custom createConfig script for replacing Django {{STATIC_URL}} references
// when building config for concat and cssmin
var path = require('path');
function createDjangoStaticConcatConfig(context, block) {
  var cfg = {files: []};
  var staticPattern = /\{\{\s*STATIC_URL\s*\}\}/;

  block.dest = block.dest.replace(staticPattern, '');
  var outfile = path.join(context.outDir, block.dest);

  // Depending whether or not we're the last of the step we're not going to output the same thing
  var files = {
    dest: outfile,
    src: []
  };
  context.inFiles.forEach(function(f) {
    files.src.push(path.join(context.inDir, f.replace(staticPattern, '')));
  });
  cfg.files.push(files);
  context.outFiles = [block.dest];
  return cfg;
}


grunt.initConfig({
    /*...*/

    // add a preprocessor to modify the concat config to parse out {{STATIC_URL}} using the above method
    useminPrepare: {
      html: 'app/index.html',
      options: {
        dest: 'dist',
        flow: {
          steps: {
            js: [
              {
                name: 'concat',
                createConfig: createDjangoStaticConcatConfig
              },
              'uglifyjs'
            ],
            // also apply it to css files
            css: [
              {
                name: 'cssmin',
                createConfig: createDjangoStaticConcatConfig
              }
            ]
          },
          // this property is necessary
          post: {}
        }
      }
    },

    // add a pattern to parse out the actual filename and remove the {{STATIC_URL}} bit
    usemin: {
      html: ['dist/{,*/}*.html'],
      css: ['dist/styles/{,*/}*.css'],
      options: {
        assetsDirs: ['dist'],
        patterns: {
          html: [[/\{\{\s*STATIC_URL\s*\}\}([^'"]*)["']/mg, 'django static']]
        }
      }
    },


    // if you are using bower, also include the jsPattern to automatically 
    // insert {{STATIC_URL}} when inserting js files
    'bower-install': {
      app: {
        html: 'app/index.html',
        jsPattern: '<script type="text/javascript" src="{{STATIC_URL}}{{filePath}}"></script>'
      }
    }
});

【讨论】:

  • 干得好,但输出不会产生 {{STATIC_URL}} 前缀
  • 嘿,谢谢,这解决了我的 php 问题。对于对此有疑问的人,'post: {}' 属性是必要的
  • @stalin 是的,是的。我会在那里做一个注释,这样会更明显。谢谢!
  • @mouse,我遇到了同样的问题,没有 {{STATIC_URL}} - 我必须添加一个 blockReplacements 部分,返回类似return '&lt;script src="{{STATIC_URL}}path/'+block.dest+'"&gt;&lt;/script&gt;';
【解决方案2】:

(我在谷歌搜索解决方案时不断发现这个问题,所以我只是在这里分享我找到的解决方案,以便像我这样的其他人可以找到它。)

我刚刚发现了一个名为 grunt-bridge 的 grunt 插件,它可以将静态文件包装在带有 static 标签的 html 模板中。文档不是很好,但我想出了如何让它为我的项目工作。

如果你有这样的脚本:

<!-- build:js({.tmp,app}) /scripts/scripts.js -->
    <script src="scripts/app.js"></script>
    <script src="scripts/util/util.js"></script>
    ...

而最终的输出是这样的:

<script src="{% static 'adjangoappname/scripts/94223d51.scripts.js' %}"></script>

使用npm install grunt-bridge --save-dev 安装 gruntbridge 和 在 Gruntfile.js 的 grunt.initConfig 中添加这样的配置:

bridge: {
  distBaseHtml: {
      options: {
          pattern: '{% static \'adjangoappname{path}\' %}',
          html: '<%= yeoman.minifiedDir %>/index.html', dest: '<%= yeoman.templateDir %>/index.html'
      }
  },
  distIndexHtml: {
      options: {
          pattern: '{% static \'adjangoappname{path}\' %}',
          html: '<%= yeoman.minifiedDir %>/index.html', dest: '<%= yeoman.templateDir %>/index.html'
      }
  },
  // ... etc for each html file you want to modify
},

其中&lt;%= yeoman.minifiedDir %&gt;是最终缩小的html文件的输出目录,&lt;%= yeoman.minifiedDir %&gt;是目标模板目录。 将 adjangoappname 替换为您的 django 应用程序的名称或您想要的任何目录前缀。

然后在 registerTask 列表中最后添加 grunt-bridge,如下所示:

grunt.registerTask('build', [
    //...
    'htmlmin',
    'bridge'
]);

(我认为可以使配置更紧凑,但这是我发现的第一个有效的方法)

【讨论】:

  • grunt-bridge 插件很棒。我用 yeoman-webapp 对其进行了测试。我需要从“构建”任务中删除“htmlmin”,因为 grunt-bridge 不喜欢“htmlmin”产生的缺失引号。
猜你喜欢
  • 1970-01-01
  • 2018-10-07
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多