在 gruntjs minify/uglify 之后更改 html 中的链接或脚本文件名

Posted

技术标签:

【中文标题】在 gruntjs minify/uglify 之后更改 html 中的链接或脚本文件名【英文标题】:Change link or script filename in html after gruntjs minify/uglify 【发布时间】:2013-12-18 17:21:25 【问题描述】:

我对 css/js 文件使用标准的 minify/uglify 并将多个文件合并到 main.min.css 或 app.min.js... 但是我的 .html 文件需要修改以指向这些新文件名<link><script> 也是如此

有没有办法让这个自动化?或者如何使用gruntjs自动修改.html文件以重命名其中的文件名?

【问题讨论】:

您不应该在 HTML 中使用 main.min.css 吗?为什么你需要改变它?当你更新源文件时,它应该只是覆盖编译的文件。 这只是开发与产品的对比。我可以那样做。但在开发中,我习惯将文件分开保存以便于跟踪和调试 您是否在使用某种服务器端语言,例如 php?您可以在文件中放置一个条件 if 块,以检查您是处于开发阶段还是生产阶段。 是的,python。我想你的建议也是一个有效的观点。 【参考方案1】:

您可以使用grunt-string-replace 执行此操作。这是一个关于如何使用它的示例。

在我的 index.html 中,您可以找到以下导入标签:

<!--start PROD imports
<script src="assets/dist/traffic.min.js"></script>
end PROD imports-->

<!--start DEV imports-->
<script src="assets/js/app.js"></script>
<script src="assets/js/services.js"></script> 
<script src="assets/js/directives.js"></script>
<script src="assets/js/filters.js"></script>
<script src="assets/js/resources.js"></script>
<script src="assets/js/controller/homeControllers.js"></script>
<script src="assets/js/controller/adminControllers.js"></script>
<script src="assets/js/controller/reportsControllers.js"></script>
<!--end DEV imports-->

注意“开始导入”和“结束导入”cmets。默认情况下(在 DEV 中)我们注释掉 PROD 导入。

然后在我的 grunt 文件中添加以下任务:

    'string-replace': 
        inline: 
            files: 
                'index.html': 'index.html'
            ,
            options: 
                replacements: [
                    
                        pattern: '<!--start PROD imports',
                        replacement: '<!--start PROD imports-->'
                    ,
                    
                        pattern: 'end PROD imports-->',
                        replacement: '<!--end PROD imports-->'
                    ,
                    
                        pattern: '<!--start DEV imports-->',
                        replacement: '<!--start DEV imports'
                    ,
                    
                        pattern: '<!--end DEV imports-->',
                        replacement: 'end DEV imports-->'
                    
                ]
            
        
    

运行任务(grunt string-replace)给了我:

<!--start PROD imports-->
<script src="assets/dist/traffic.min.js"></script>
<!--end PROD imports-->

<!--start DEV imports
<script src="assets/js/app.js"></script>
<script src="assets/js/services.js"></script>
<script src="assets/js/directives.js"></script>
<script src="assets/js/filters.js"></script>
<script src="assets/js/resources.js"></script>
<script src="assets/js/controller/homeControllers.js"></script>
<script src="assets/js/controller/adminControllers.js"></script>
<script src="assets/js/controller/reportsControllers.js"></script>
end DEV imports-->

现在 DEV 导入已被注释掉,而 PROD 导入不再被注释掉。

【讨论】:

如何扭转这种局面?以防我注释掉 PROD 并取消注释 DEV ? 开发文件名仍将在 html 文件中可用,任何人都可以在页面源中查看!我更喜欢完全删除开发文件名并将构建的文件名添加到主 html 的东西。 @ram,对于完整的开发/产品设置,我将执行一项任务,将我的 HTML 从源目录复制到生产目录,只有生产目录会被上述任务更改。因此,如果您查看源代码,它们始终处于开发状态,而 prod 目录可以随时清理并再次生成。 @Kaustubh,我同意,可以使用另一个任务来删除 HTML cmets,或者,另一个开发设置基于:作为模板的源文件,使用模板生成的开发和也从模板生成的产品,但生产缩小文件的版本。【参考方案2】:

这很容易通过 grunt-processhtml 自动化。这是文档中的一个示例:

<!-- build:js app.min.js -->
<script src="my/lib/path/lib.js"></script>
<script src="my/deep/development/path/script.js"></script>
<!-- /build -->

<!-- changed to -->
<script src="app.min.js"></script>

阅读更多https://www.npmjs.org/package/grunt-processhtml

【讨论】:

如果您的min.js 文件名是在丑化时动态创建的。我怎样才能让它使用该文件名而不在&lt;!-- build:js app.min.js --&gt;下的html文件中硬编码? @hyprstack 看看我的回答,只要您可以使用通配符匹配动态名称,它也可以处理这种情况。 (即*.min.js 或其他用于缩小文件的目录)【参考方案3】:

一个非常合适的 grunt 任务是grunt-html-build

它可以将 HTML 的某些部分从开发版本替换为生产版本。见那里的例子,很容易设置。

现在,使用为grunt-html-build 提供的标准配置,如果缩小文件在构建过程中动态命名,例如:

some-file.js -> another-name.min.js

可以通过以下方式配置grunt-html-build:

[...]
scripts: 
   bundle: [
            '<%= fixturesPath %>/scripts/*.min.js'
   ]
,
[...]

一个 HTML 部分,如:

<!-- build:script bundle -->
<script type="text/javascript" src="/path/to/js/libs/jquery.js"></script>
<script type="text/javascript" src="/path/to/js/libs/knockout.js"></script>
<script type="text/javascript" src="/path/to/js/libs/underscore.js"></script>
<script type="text/javascript" src="/path/to/js/app/module1.js"></script>
<script type="text/javascript" src="/path/to/js/app/module2.js"></script>
<!-- /build -->

会屈服于:

<script type="text/javascript" src="scripts/other-name.min.js"></script>
<script type="text/javascript" src="scripts/another-other-name.min.js"></script>

这就是 @hyprstack 在 cmets 中的要求。

【讨论】:

【参考方案4】:

您可以使用 grunt 预处理来执行此操作:https://github.com/jsoverson/grunt-preprocess

基本上,您需要设置一个模板并让预处理替换相关部分。

Gruntfile 部分看起来像这样:

preprocess: 
    dev: 
            options: 
                    context: 
                            DEBUG: true,
                            HOST: '<%= env.dev.HOST %>'
                    
            ,
            files: 
                    'index.html': 'tpl/index.tpl'
            
    ,
    production: 
            options: 
                    context: 
                            DEBUG: false,
                            HOST: '<%= env.production.HOST %>
                    
            ,
            files: 
                    'index.html': 'tpl/index.tpl'
            
    

,

【讨论】:

这不是我想要的,因为所有的 html 代码都必须在模板中。我正在使用 Middleman App 在 gruntjs 之前即时编译我的 Haml。我想弄清楚是否有可以正则表达式匹配链接/脚本标签的搜索/替换功能。这样,一旦我完成了代码,我就可以只运行一次 gruntjs 来进行搜索/替换。【参考方案5】:

我正在使用 Middleman App 在我的 html 或 haml 文件中区分 dev 与 build:

- if development?

- if build?

【讨论】:

以上是关于在 gruntjs minify/uglify 之后更改 html 中的链接或脚本文件名的主要内容,如果未能解决你的问题,请参考以下文章

番外篇01:angularJS最佳实战

如何将使用 Gulp 的节点部署到 heroku

GruntJS学习(转)

在gruntjs中的ant -p等价物?

带有 grunt-nodemon、watch 和 jshint 的 Gruntjs

Grunt 之 watch 和 livereload