【问题标题】:Grails Resources modules: programmatic equivalent to r:require?Grails 资源模块:编程等效于 r:require?
【发布时间】:2014-02-22 03:06:00
【问题描述】:

我正在使用模块来处理 Grails 应用程序中的资源依赖和捆绑:

'module1' {
    resource url: '/path/to/resource1-1.js';
    resource url: '/path/to/resource1-2.js';
}

'module2' {
    dependsOn 'module1';

    resource url: '/path/to/resource2-1.js';
    resource url: '/path/to/resource2-2.js';
}

这将为上面的示例创建 2 个包,每个模块一个(注意:确切的包名称可能因某些配置而异):

/app/static/bundle-bundle_module1_defer.js
/app/static/bundle-bundle_module2_defer.js

现在,我正在实现一个使用 module2 的 Web Worker。在构建 Worker 时,需要指定它将使用的 JS 文件的 URL,所以如果我知道生成的 bundle 的名称,它会是这样的:

var worker = new Worker('/app/static/bundle-bundle_module1_defer.js', '/app/static/bundle-bundle_module2_defer.js');

问题是:如何以编程方式获取与“module2”(及其依赖项)相对应的这 2 个 URL? 我正在寻找类似 @​​987654321@ 标记的东西,不同之处在于require 标签生成完整的<script> 标签

<script src="/app/static/bundle-bundle_module1_defer.js" type="text/javascript" ></script>
<script src="/app/static/bundle-bundle_module2_defer.js" type="text/javascript" ></script>

我只需要上面的 2 个网址。

更新在 Web Worker 部分添加了一些示例。

【问题讨论】:

  • 我不明白您在这里要做什么...也许提供一些您想要生成的“特定 URL”的示例以及为什么您不能简单地将其放入 GSP带有require标签。
  • 希望现在更清楚了。 r:require 添加完整的脚本标签,但我需要它们的 URL。
  • 看看github.com/grails-plugins/grails-resources/blob/master的源代码,也许你能找到有用的东西。

标签: javascript grails groovy resources


【解决方案1】:

开发了一个实用程序类,它试图尽可能地重用现有代码:

class ResourceProcessorUtil {
    def static externalURLPattern = /^((https?:?)?\/\/).*/

    static Map getResources(grailsApplication, moduleNameList) {
        def grailsResourceProcessor = grailsApplication.mainContext.getBean('grailsResourceProcessor')
        def resourceTagLib = grailsApplication.mainContext.getBean('org.grails.plugin.resource.ResourceTagLib')

        def modulesNeeded = grailsResourceProcessor.getAllModuleNamesRequired(moduleNameList)
        def modulesInOrder = grailsResourceProcessor.getModulesInDependencyOrder(modulesNeeded)

        def resources = [:]
        for (moduleName in modulesInOrder) {
            def module = grailsResourceProcessor.getModule(moduleName)
            for (r in module.resources) {
                if (!r.exists() && !isExternalURL(r.actualUrl)) {
                    throw new IllegalArgumentException("Module [$moduleName] depends on resource [${r.sourceUrl}] but the file cannot be found")
                }

                def info = resourceTagLib.resolveLinkUriToUriAndResource([uri: "${r.actualUrl}"])
                resources.put(info.uri, info.resource)
            }
        }

        return resources
    }

    static Boolean isExternalURL(url){
        return url ==~ externalURLPattern
    }
}

从控制器调用它(例如)

ResourceProcessorUtil.getResources(grailsApplication, ['some-module', 'an-additional-module'])

将返回一个包含所有资源的 Map &lt;key,value&gt; = &lt;'uri', ResourceMeta&gt;,根据插件的依赖解析正确排序。

注意:使用资源插件 1.2.1 测试。 isExternalURL 方法已经在 URLUtils 的开发版本中实现。

注意 2:在 http://jira.grails.org/browse/GPRESOURCES-249 上对此提出了建议

【讨论】:

    【解决方案2】:

    我在 Grails 中找不到任何可以轻松执行此操作的内容,但您可以尝试在客户端执行此操作吗?假设您可以在页面中包含脚本文件,那么您可以提取它们的 src 属性并从中创建工作 url:

    <script id="script1" src="/js/script1.js"></script>
    

    var script1Url = document.getElementById("script1").src;
    var worker = new Worker(script1Url);
    

    是的,这似乎是一种 hack,如果脚本很大,那么它可能会影响渲染,让浏览器加载它们两次(?)。

    【讨论】:

    • 会有你提到的缺点,但我认为它会起作用!尽管如此,仍然更喜欢实用程序类,重用大多数代码,所以我想它并不太糟糕。
    【解决方案3】:

    According to the docs,您可以更改将使用您的资源生成的捆绑包的名称:

    'module1' {
        resource url: '/path/to/resource1-1.js'
        resource url: '/path/to/resource1-2.js'
        defaultBundle 'module1'
    }
    
    'module2' {
        dependsOn 'module1';
        resource url: '/path/to/resource2-1.js'
        resource url: '/path/to/resource2-2.js'
    
        defaultBundle 'module2'
    }
    

    【讨论】:

    • 这仍然需要我手动包含模块 2、模块 1 和所有其他可能存在的依赖项(所以我不会使用资源模块依赖机制)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 2020-11-25
    • 2023-03-13
    • 1970-01-01
    相关资源
    最近更新 更多