Change link or script filename in html after grunt

2019-03-14 10:58发布

问题:

I am using standard minify/uglify for css/js files and combine multiple files to main.min.css or app.min.js... However my .html file needs to be modified to point to these new file names too in <link> or <script>

Is there a way to automate this? Or how to modify .html files automatically to rename the file names in there using gruntjs?

回答1:

You can do this with grunt-string-replace. Here's an example on how you could use it.

In my index.html you find the following import tags:

<!--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-->

Notice the 'start imports' and 'end imports' comments. By default (in DEV) we comment out the PROD import.

In my grunt file I then add the following task:

    '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-->'
                    }
                ]
            }
        }
    }

Running the task (grunt string-replace) gives me:

<!--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-->

Now the DEV imports have been commented out, while the PROD import is no longer commented out.



回答2:

This is easily automated with grunt-processhtml. Here's an example from the docs:

<!-- 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>

Read more at https://www.npmjs.org/package/grunt-processhtml



回答3:

A very suitable grunt task for this is grunt-html-build

It can substitute some some parts of the HTML from dev to a production version. See examples there, it is easy to setup.

Now, using the standard configuration presented for grunt-html-build, if minified files are dynamically named during build process like:

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

One can configure grunt-html-build with:

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

A HTML section like:

<!-- 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 -->

Would yield to something like:

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

That is what @hyprstack is asking for in comments.



回答4:

You could use grunt preprocess to do this: https://github.com/jsoverson/grunt-preprocess

Basically, you need to set up a template and have preprocess replace the relevant parts.

The Gruntfile part will look something like this:

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'
            }
    }

},



回答5:

I am using Middleman App do distinguish between dev vs build in my html or haml file:

- if development?

and

- if build?