javascript type Haz que Grunt genere index.html para diferentes configuraciones




script type= text/javascript src= (10)

Encontré un plugin de gruñido llamado grunt-dev-prod-switch. Todo lo que hace es comentar ciertos bloques que busca en función de la opción --env que pasas a grunt (aunque te limita a dev, prod y test).

Una vez que lo configura como se explica here , puede ejecutar, por ejemplo:

grunt serve --env=dev , y todo lo que hace es comentar los bloques que están envueltos por

    <!-- env:test/prod -->
    your code here
    <!-- env:test/prod:end -->

y descomentará los bloques que están envueltos por

    <!-- env:dev -->
    your code here
    <!-- env:dev:end -->

También funciona en javascript, lo uso para configurar la dirección IP correcta para conectarme con mi API de back-end. Los bloques solo cambian a

    /* env:dev */
    your code here
    /* env:dev:end */

En tu caso, sería tan simple como esto:

<!DOCTYPE html>
<html>
    <head>
        <!-- env:dev -->
        <script src="js/module1.js" />
        <script src="js/module2.js" />
        <script src="js/module3.js" />
        ...
        <!-- env:dev:end -->
        <!-- env:prod -->
        <script src="js/MyApp-all.min.js" />
        ...
        <!-- env:prod:end -->
    </head>
    <body></body>
</html>

Estoy tratando de usar Grunt como una herramienta de compilación para mi aplicación web.

Quiero tener al menos dos configuraciones:

I. Configuración de desarrollo : cargue scripts desde archivos separados, sin concatenación,

así que mi index.html se vería algo así como:

<!DOCTYPE html>
<html>
    <head>
        <script src="js/module1.js" />
        <script src="js/module2.js" />
        <script src="js/module3.js" />
        ...
    </head>
    <body></body>
</html>

II. Configuración de producción : cargue mis scripts minificados y concatenados en un archivo,

con index.html en consecuencia:

<!DOCTYPE html>
<html>
    <head>
        <script src="js/MyApp-all.min.js" />
    </head>
    <body></body>
</html>

La pregunta es, ¿cómo puedo hacer que grunt haga que index.html dependa de la configuración cuando ejecuto grunt dev o grunt prod ?

¿O quizás estoy cavando en la dirección equivocada y sería más fácil generar siempre MyApp-all.min.js pero poner dentro de ella todos mis scripts (concatenados) o un script de carga que carga de forma asíncrona esos scripts desde archivos separados?

¿Cómo lo haces, chicos?


Estaba buscando una solución más simple y directa, así que combiné la respuesta de esta pregunta:

Cómo colocar, si no, bloquear en gruntfile.js

y se le ocurrieron los siguientes pasos simples:

  1. Conserve dos versiones de sus archivos de índice como aparece en la lista y asígnele el nombre index-development.html y index-prodoction.html.
  2. Use la siguiente lógica en el bloque de copia / concat de Gruntfile.js para su archivo index.html:

    concat: {
        index: {
            src : [ (function() {
                if (grunt.option('Release')) {
                  return 'views/index-production.html';
                } else {
                  return 'views/index-development.html';
                }
              }()) ],
           dest: '<%= distdir %>/index.html',
           ...
        },
        ...
    },
    
  3. ejecute 'grunt --Release' para elegir el archivo index-production.html y deje de marcar para tener la versión de desarrollo.

No hay nuevos complementos para agregar o configurar y no hay nuevas tareas grunt.


Recientemente descubrí estas tareas compatibles con Grunt v0.4.0 :

  • grunt-preprocess

    Tarea ronca alrededor del módulo preprocesamiento npm

  • grunt-env

    Tarea grunt para automatizar la configuración del entorno para tareas futuras.

A continuación hay fragmentos de mi Gruntfile.js .

Configuración ENV:

env : {

    options : {

        /* Shared Options Hash */
        //globalOption : 'foo'

    },

    dev: {

        NODE_ENV : 'DEVELOPMENT'

    },

    prod : {

        NODE_ENV : 'PRODUCTION'

    }

},

Preproceso

preprocess : {

    dev : {

        src : './src/tmpl/index.html',
        dest : './dev/index.html'

    },

    prod : {

        src : './src/tmpl/index.html',
        dest : '../<%= pkg.version %>/<%= now %>/<%= ver %>/index.html',
        options : {

            context : {
                name : '<%= pkg.name %>',
                version : '<%= pkg.version %>',
                now : '<%= now %>',
                ver : '<%= ver %>'
            }

        }

    }

}

Tareas:

grunt.registerTask('default', ['jshint']);

grunt.registerTask('dev', ['jshint', 'env:dev', 'clean:dev', 'preprocess:dev']);

grunt.registerTask('prod', ['jshint', 'env:prod', 'clean:prod', 'uglify:prod', 'cssmin:prod', 'copy:prod', 'preprocess:prod']);

Y en el archivo de plantilla /src/tmpl/index.html (por ejemplo):

<!-- @if NODE_ENV == 'DEVELOPMENT' -->

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
    <script src="../src/js/foo1.js"></script>
    <script src="../src/js/foo2.js"></script>
    <script src="../src/js/jquery.blah.js"></script>
    <script src="../src/js/jquery.billy.js"></script>
    <script src="../src/js/jquery.jenkins.js"></script>

<!-- @endif -->

<!-- @if NODE_ENV == 'PRODUCTION' -->

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

    <script src="http://cdn.foo.com/<!-- @echo name -->/<!-- @echo version -->/<!-- @echo now -->/<!-- @echo ver -->/js/<!-- @echo name -->.min.js"></script>

<!-- @endif -->

Estoy seguro de que mi configuración es diferente a la mayoría de las personas, y la utilidad de lo anterior dependerá de su situación. Para mí, si bien es un código asombroso, el grunt-usemin es más robusto de lo que personalmente necesito.

NOTA: Acabo de descubrir las tareas enumeradas anteriormente hoy, por lo que podría faltar una función y / o mi proceso puede cambiar en el futuro. Por ahora, me encanta la simplicidad y las características que grunt-preprocess y grunt-env tienen para ofrecer. :)

Actualización de enero de 2014:

Motivado por un voto negativo ...

Cuando 0.4.x esta respuesta, no había muchas opciones para Grunt 0.4.x que ofrecieran una solución que funcionara para mis necesidades. Ahora, meses más tarde, creo que hay más opciones que podrían ser mejores que las que he publicado aquí. Si bien personalmente uso y disfruto usando esta técnica para mis versiones , le pido a los futuros lectores que se tomen el tiempo de leer las otras respuestas y que investiguen todas las opciones. Si encuentra una solución mejor, por favor publique su respuesta aquí.

Actualización de febrero de 2014:

No estoy seguro de que sirva de ayuda para nadie, pero he creado este repositorio de demostración en GitHub que muestra una configuración completa (y más compleja) utilizando la (s) técnica (s) que he descrito anteriormente.


Use una combinación de wiredep https://github.com/taptapship/wiredep y usemin grunt-usemin para que Grunt se encargue de estas tareas. Wiredep agregará sus dependencias un archivo de secuencia de comandos a la vez, y usemin las concatenará en un solo archivo para la producción. Esto se puede lograr con solo algunos comentarios html. Por ejemplo, mis paquetes de bower se incluyen automáticamente y se agregan al html cuando ejecuto bower install && grunt bowerInstall :

<!-- build:js /scripts/vendor.js -->
<!-- bower:js -->
<!-- endbower -->
<!-- endbuild -->

Considere processhtml . Permite la definición de múltiples "objetivos" para construcciones. Los comentarios se utilizan para incluir o excluir condicionalmente material del HTML:

<!-- build:js:production js/app.js -->
...
<!-- /build -->

se convierte en

<script src="js/app.js"></script>

Incluso pretende hacer cosas ingeniosas como esta (ver el README ):

<!-- build:[class]:dist production -->
<html class="debug_mode">
<!-- /build -->

<!-- class is changed to 'production' only when the 'dist' build is executed -->
<html class="production">

Esta tarea grunt llamada scriptlinker parece una forma fácil de agregar los scripts en modo dev. Probablemente podría ejecutar primero una tarea concat y luego apuntarla a su archivo concatenado en modo prod.


He encontrado mi propia solución. Aún no está pulido, pero creo que voy a avanzar en esa dirección.

En esencia, estoy usando grunt.template.process() para generar mi index.html partir de una plantilla que analiza la configuración actual y produce una lista de mis archivos de origen originales o enlaces a un solo archivo con código minificado. El siguiente ejemplo es para archivos js, pero el mismo enfoque puede extenderse a css y a cualquier otro archivo de texto posible.

grunt.js :

/*global module:false*/
module.exports = function(grunt) {
    var   // js files
        jsFiles = [
              'src/module1.js',
              'src/module2.js',
              'src/module3.js',
              'src/awesome.js'
            ];

    // Import custom tasks (see index task below)
    grunt.loadTasks( "build/tasks" );

    // Project configuration.
    grunt.initConfig({
      pkg: '<json:package.json>',
      meta: {
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
          '<%= grunt.template.today("yyyy-mm-dd") %> */'
      },

      jsFiles: jsFiles,

      // file name for concatenated js
      concatJsFile: '<%= pkg.name %>-all.js',

      // file name for concatenated & minified js
      concatJsMinFile: '<%= pkg.name %>-all.min.js',

      concat: {
        dist: {
            src: ['<banner:meta.banner>'].concat(jsFiles),
            dest: 'dist/<%= concatJsFile %>'
        }
      },
      min: {
        dist: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'dist/<%= concatJsMinFile %>'
        }
      },
      lint: {
        files: ['grunt.js'].concat(jsFiles)
      },
      // options for index.html builder task
      index: {
        src: 'index.tmpl',  // source template file
        dest: 'index.html'  // destination file (usually index.html)
      }
    });


    // Development setup
    grunt.registerTask('dev', 'Development build', function() {
        // set some global flags that all tasks can access
        grunt.config('isDebug', true);
        grunt.config('isConcat', false);
        grunt.config('isMin', false);

        // run tasks
        grunt.task.run('lint index');
    });

    // Production setup
    grunt.registerTask('prod', 'Production build', function() {
        // set some global flags that all tasks can access
        grunt.config('isDebug', false);
        grunt.config('isConcat', true);
        grunt.config('isMin', true);

        // run tasks
        grunt.task.run('lint concat min index');
    });

    // Default task
    grunt.registerTask('default', 'dev');
};

index.js (the index task) :

module.exports = function( grunt ) {
    grunt.registerTask( "index", "Generate index.html depending on configuration", function() {
        var conf = grunt.config('index'),
            tmpl = grunt.file.read(conf.src);

        grunt.file.write(conf.dest, grunt.template.process(tmpl));

        grunt.log.writeln('Generated \'' + conf.dest + '\' from \'' + conf.src + '\'');
    });
}

Finalmente, index.tmpl , con lógica de generación index.tmpl :

<doctype html>
<head>
<%
    var jsFiles = grunt.config('jsFiles'),
        isConcat = grunt.config('isConcat');

    if(isConcat) {
        print('<script type="text/javascript" src="' + grunt.config('concat.dist.dest') + '"></script>\n');
    } else {
        for(var i = 0, len = jsFiles.length; i < len; i++) {
            print('<script type="text/javascript" src="' + jsFiles[i] + '"></script>\n');
        }
    }
%>
</head>
<html>
</html>

UPD. Descubrió que Yeoman , que se basa en el gruñido, tiene una tarea usemin de usemin que se integra con el sistema de construcción de Yeoman. Genera una versión de producción de index.html a partir de la información en la versión de desarrollo de index.html, así como otras configuraciones del entorno. Un poco sofisticado pero interesante a la vista.


Me he estado preguntando lo mismo durante un tiempo, y creo que este complemento de grunt podría configurarse para hacer lo que quieras: https://npmjs.org/package/grunt-targethtml . Implementa etiquetas html condicionales, que dependen del objetivo de grunt.


grunt-bake es un guión fantástico que funcionaría muy bien aquí. Lo uso en mi script de compilación automática JQM.

https://github.com/imaginethepoet/autojqmphonegap

Echa un vistazo a mi archivo grunt.coffee:

bake:
    resources: 
      files: "index.html":"resources/custom/components/base.html"

Esto analiza todos los archivos en base.html y los absorbe para crear index.html que funciona de forma fantástica para aplicaciones de varias páginas (phonegap). Esto permite un desarrollo más fácil ya que todos los desarrolladores no están trabajando en una aplicación de una sola página larga (lo que evita muchos controles de conflictos). En su lugar, puede dividir las páginas y trabajar en trozos más pequeños de código y compilar la página completa con un comando de observación.

Bake lee la plantilla desde base.html e inyecta las páginas html del componente en el reloj.

<!DOCTYPE html>

Demostraciones móviles de jQuery

app.initialize ();

<body>
    <!--(bake /resources/custom/components/page1.html)-->
    <!--(bake /resources/custom/components/page2.html)-->
    <!--(bake /resources/custom/components/page3.html)-->
</body>

Puede llevar esto un paso más allá y agregar inyecciones en sus páginas para los "menús", "elementos emergentes", etc., de modo que realmente pueda dividir las páginas en componentes más pequeños y manejables.


Esta respuesta no es para los noobs!

Use Jade Templating ... pasar variables a una plantilla de Jade es un caso de uso estándar de bog

Estoy usando grunt (grunt-contrib-jade) pero no tienes que usar grunt. Sólo tiene que utilizar el módulo de jade npm estándar

Si usas gruñido, a tu archivo gruñón le gustaría algo como ...

jade: {
    options: {
      // TODO - Define options here
    },
    dev: {
      options: {
        data: {
          pageTitle: '<%= grunt.file.name %>',
          homePage: '/app',
          liveReloadServer: liveReloadServer,
          cssGruntClassesForHtmlHead: 'grunt-' + '<%= grunt.task.current.target %>'
        },
        pretty: true
      },
      files: [
        {
          expand: true,
          cwd: "src/app",
          src: ["index.jade", "404.jade"],
          dest: "lib/app",
          ext: ".html"
        },
        {
          expand: true,
          flatten: true,
          cwd: "src/app",
          src: ["directives/partials/*.jade"],
          dest: "lib/app/directives/partials",
          ext: ".html"
        }
      ]
    }
  },

Ahora podemos acceder fácilmente a los datos pasados ​​por grunt en la plantilla de Jade.

Al igual que el enfoque utilizado por Modernizr, establezco una clase CSS en la etiqueta HTML de acuerdo con el valor de la variable pasada y puedo usar la lógica de JavaScript desde allí en función de si la clase CSS está presente o no.

Esto es genial si usa Angular ya que puede hacer ng-if para incluir elementos en la página en función de si la clase está presente.

Por ejemplo, podría incluir un script si la clase está presente ...

(Por ejemplo, podría incluir el script de recarga en vivo en dev pero no en producción)

<script ng-if="controller.isClassPresent()" src="//localhost:35729/livereload.js"></script> 






gruntjs