Change link or script filename in html after gruntjs minify/uglify
Asked Answered
H

5

22

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?

Heine answered 2/12, 2013 at 21:5 Comment(4)
shouldn't you just use main.min.css in your HTML? why do you need to change it? When you update the source files it should just overwrite the compiled file.Horned
It's just dev vs. prod. I could do that. But in dev, it's just my habit to keep files separately for easy tracking and debuggingHeine
Are you using some kind of server side language like PHP? You could put a conditional if block in the file to check if you are in dev or production.Horned
Yes, python. I guess your suggestion is also a valid point.Heine
H
0

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

- if development?

and

- if build?

Heine answered 11/12, 2013 at 19:10 Comment(0)
T
17

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.

Trifling answered 10/1, 2014 at 12:33 Comment(4)
How can this be reversed ? in case i have of comment out PROD and uncomment DEV ?Bitumen
The development file names will still be available in the html file for anyone to see in the page source!! I would prefer something which would remove the development filenames altogether and add the built filenames to the main html.Jermaine
@ram, for a complete dev/prod setup I would make a task to copy my HTML from a source dir to a production dir, only the production dir would be altered by the task above. So if you look source they are always in dev state while prod dir can be cleaned up anytime and generated again.Kutzenco
@Kaustubh, I agree, another task can be used to remove HTML comments or, another dev setup based on: sources files as templates, dev generated using templates and prod also generated from templates but with production minified version of files.Kutzenco
V
14

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

Valora answered 30/5, 2014 at 20:44 Comment(2)
What if your min.js filename is dynamically created on uglification. How can I get it to use that filename without having it hardcoded in the html file under <!-- build:js app.min.js --> ?Dashtikavir
@Dashtikavir take a look at my answer, it handles this situation also as long as you can use wildcard to match dynamic names. (i.e. *.min.js or another directory for minified files)Kutzenco
K
1

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.

Kutzenco answered 1/7, 2016 at 19:21 Comment(0)
A
0

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

},

Audet answered 2/12, 2013 at 21:16 Comment(1)
This is not quite what I'm looking for because all the html code has to be in the template. I'm using Middleman App to compile my Haml on the fly BEFORE gruntjs. I like to figure out if there is a search/replace feature that can Regex match link/script tag. That way once I'm done with the code, I can run gruntjs just once to do search/replace.Heine
H
0

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

- if development?

and

- if build?

Heine answered 11/12, 2013 at 19:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.