plugin - script type= text/javascript src=




Haz que Grunt genere index.html para diferentes configuraciones (8)

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?


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

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>

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.


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.


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.


No me gustan las soluciones aquí (incluida la que di anteriormente ) y he aquí por qué:

  • El problema con la respuesta más votada es que tiene que sincronizar manualmente la lista de etiquetas de script cuando agrega / renombra / elimina un archivo JS.
  • El problema con la respuesta aceptada es que su lista de archivos JS no puede tener coincidencia de patrones. Esto significa que tienes que actualizarlo a mano en el Gruntfile.

He descubierto cómo resolver estos dos problemas. He configurado mi tarea grunt para que cada vez que se agregue o elimine un archivo, las etiquetas de script se generen automáticamente para reflejar eso. De esta manera, no necesita modificar su archivo html o su archivo grunt cuando agrega / elimina / renombra sus archivos JS.

Para resumir cómo funciona, tengo una plantilla html con una variable para las etiquetas de script. Uso https://github.com/alanshaw/grunt-include-replace para rellenar esa variable. En el modo dev, esa variable proviene de un patrón global de todos mis archivos JS. La tarea de observación recalcula este valor cuando se agrega o elimina un archivo JS.

Ahora, para obtener diferentes resultados en modo dev o prod, simplemente rellena esa variable con un valor diferente. Aquí hay un código:

var jsSrcFileArray = [
    'src/main/scripts/app/js/Constants.js',
    'src/main/scripts/app/js/Random.js',
    'src/main/scripts/app/js/Vector.js',
    'src/main/scripts/app/js/scripts.js',
    'src/main/scripts/app/js/StatsData.js',
    'src/main/scripts/app/js/Dialog.js',
    'src/main/scripts/app/**/*.js',
    '!src/main/scripts/app/js/AuditingReport.js'
];

var jsScriptTags = function (srcPattern, destPath) {
    if (srcPattern === undefined) {
        throw new Error("srcPattern undefined");
    }
    if (destPath === undefined) {
        throw new Error("destPath undefined");
    }
    return grunt.util._.reduce(
        grunt.file.expandMapping(srcPattern, destPath, {
            filter: 'isFile',
            flatten: true,
            expand: true,
            cwd: '.'
        }),
        function (sum, file) {
            return sum + '\n<script src="' + file.dest + '" type="text/javascript"></script>';
        },
        ''
    );
};

...

grunt.initConfig({

    includereplace: {
        dev: {
            options: {
                globals: {
                    scriptsTags: '<%= jsScriptTags(jsSrcFileArray, "../../main/scripts/app/js")%>'
                }
            },
            src: [
                'src/**/html-template.html'
            ],
            dest: 'src/main/generated/',
            flatten: true,
            cwd: '.',
            expand: true
        },
        prod: {
            options: {
                globals: {
                    scriptsTags: '<script src="app.min.js" type="text/javascript"></script>'
                }
            },
            src: [
                'src/**/html-template.html'
            ],
            dest: 'src/main/generatedprod/',
            flatten: true,
            cwd: '.',
            expand: true
        }

...

    jsScriptTags: jsScriptTags

jsSrcFileArray es su patrón típico de agrupamiento de archivos. jsScriptTags toma el jsSrcFileArray y los concatena junto con etiquetas de script en ambos lados. destPath es el prefijo que quiero en cada archivo.

Y aquí está el aspecto del HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Example</title>

</head>

<body>    
@@scriptsTags
</body>
</html>

Ahora, como se puede ver en la configuración, genero el valor de esa variable como una etiqueta de script codificada cuando se ejecuta en modo prod . En el modo dev, esta variable se expandirá a un valor como este:

<script src="../../main/scripts/app/js/Constants.js" type="text/javascript"></script>
<script src="../../main/scripts/app/js/Random.js" type="text/javascript"></script>
<script src="../../main/scripts/app/js/Vector.js" type="text/javascript"></script>
<script src="../../main/scripts/app/js/StatsData.js" type="text/javascript"></script>
<script src="../../main/scripts/app/js/Dialog.js" type="text/javascript"></script>

Hazme saber si tienes alguna pregunta.

PD: esta es una cantidad de código para algo que querría hacer en cada aplicación JS del lado del cliente. Espero que alguien pueda convertir esto en un complemento reutilizable. Tal vez algún día lo haga.


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

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.





gruntjs