Recopilación de activos (Mix)

Introducción

Laravel Mix proporciona una API fluida para definir los pasos de construcción de Webpack para su aplicación Laravel utilizando varios preprocesadores comunes de CSS y JavaScript. A través de un simple método de encadenamiento, puedes definir con fluidez tu pipeline de activos. Por ejemplo:

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

Si alguna vez te has sentido confundido y abrumado por comenzar con Webpack y la compilación de activos, te encantará Laravel Mix. Sin embargo, no es necesario que lo uses mientras desarrollas tu aplicación; eres libre de usar cualquier herramienta de compilación de activos que desees, o incluso ninguna.

Instalación y configuración

Instalación Node

Antes de activar Mix, debes asegurarte primero de que Node.js y NPM están instalados en tu máquina.

node -v
npm -v

Por defecto, Laravel Homestead incluye todo lo que necesita; sin embargo, si no está usando Vagrant, entonces puede instalar fácilmente la última versión de Node y NPM usando simples instaladores gráficos de su página de descargas.

Laravel Mix

El único paso que queda es instalar Laravel Mix. Dentro de una nueva instalación de Laravel, encontrarás un archivo package.json en la raíz de tu estructura de directorios. El archivo package.json por defecto incluye todo lo que necesitas para empezar. Piensa en esto como tu archivo composer.json excepto que define las dependencias del Nodo en lugar de PHP. Puedes instalar las dependencias a las que hace referencia ejecutando:

npm install

Running Mix

Mix es una capa de configuración en la parte superior del Webpack, así que para ejecutar tus tareas de Mix sólo tienes que ejecutar uno de los scripts del NPM que se incluye con el archivo por defecto Laravel package.json:

// Run all Mix tasks...
npm run dev

// Run all Mix tasks and minify output...
npm run production

Vigilando los activos para los cambios

El comando npm run watch continuará ejecutándose en su terminal y observará todos los archivos relevantes para los cambios. Webpack entonces recompilará automáticamente sus activos cuando detecte un cambio:

npm run watch

Puede que descubras que en ciertos entornos Webpack no se actualiza cuando tus archivos cambian. Si este es el caso en tu sistema, considera usar el comando watch-poll:

npm run watch-poll

Trabajando con hojas de estilo

El archivo webpack.mix.js es su punto de entrada para toda la compilación de activos. Piensa en ello como una ligera configuración que envuelve a Webpack. Las tareas de Mix se pueden encadenar para definir exactamente cómo se deben compilar los activos.

Less

El método less puede ser usado para compilar Less en CSS. puede ser usado para compilar app.less a public/css/app.css.

mix.less('resources/less/app.less', 'public/css');

Se pueden utilizar múltiples llamadas al método less para compilar múltiples archivos:

mix.less('resources/less/app.less', 'public/css')
    .less('resources/less/admin.less', 'public/css');

Si desea personalizar el nombre de archivo del CSS compilado, puede pasar una ruta de archivo completa como segundo argumento al less:

mix.less('resources/less/app.less', 'public/stylesheets/styles.css');

Si necesita anular las opciones subyacentes del plug-in Lesss, puede pasar un objeto como tercer argumento a mix.less():

mix.less('resources/less/app.less', 'public/css', {
    strictMath: true
});

Sass

El método sass te permite compilar Sass en CSS. Puedes usar el método así:

mix.sass('resources/sass/app.scss', 'public/css');

De nuevo, como en el método less, puedes compilar múltiples archivos Sass en sus respectivos archivos CSS e incluso personalizar el directorio de salida del CSS resultante:

mix.sass('resources/sass/app.sass', 'public/css')
    .sass('resources/sass/admin.sass', 'public/css/admin');

Como tercer argumento, se pueden proporcionar opciones adicionales de Node-Sass plug-in options:

mix.sass('resources/sass/app.sass', 'public/css', {
    precision: 5
});

Stylus

Similar a Less y Sass, el método stylus permite compilar Stylus en CSS:

mix.stylus('resources/stylus/app.styl', 'public/css');

También puede instalar plug-ins adicionales de Stylus, como Rupture. Primero, instale el plug-in en cuestión a través de NPM (npm install rupture) y luego requiéralo en su llamada a mix.stylus():

mix.stylus('resources/stylus/app.styl', 'public/css', {
    use: [
        require('rupture')()
    ]
});

PostCSS

PostCSS, una poderosa herramienta para transformar su CSS, se incluye con Laravel Mix fuera de la caja. Por defecto, Mix aprovecha el popular plug-in Autoprefixer para aplicar automáticamente todos los prefijos de proveedor de CSS3 necesarios. Sin embargo, eres libre de añadir cualquier plug-in adicional que sea apropiado para tu aplicación. Primero, instala el plug-in deseado a través de NPM y luego haz referencia a él en tu archivo webpack.mix.js:

mix.sass('resources/sass/app.scss', 'public/css')
    .options({
        postCss: [
            require('postcss-css-variables')()
        ]
    });

Plain CSS

Si sólo quieres concatenar algunas hojas de estilo CSS simples en un solo archivo, puedes usar el método styles.

mix.styles([
    'public/css/vendor/normalize.css',
    'public/css/vendor/videojs.css'
], 'public/css/all.css');

URL Processing

Debido a que Laravel Mix está construido sobre Webpack, es importante entender algunos conceptos de Webpack. Para la compilación de CSS, Webpack reescribirá y optimizará cualquier llamada url() dentro de sus hojas de estilo. Aunque al principio pueda parecer extraño, es una funcionalidad increíblemente poderosa. Imaginen que queremos compilar Sass que incluya una URL relativa a una imagen:

.example {
    background: url('../images/example.png');
}

Absolute paths for any given url() will be excluded from URL-rewriting. For example, url('/images/thing.png') or url('http://example.com/images/thing.png') won't be modified.

Por defecto, Laravel Mix y Webpack encontrarán example.png, lo copiarán a su carpeta public/images, y luego reescribirán la url() dentro de su hoja de estilos generada. Como tal, tu CSS compilado será:

.example {
    background: url(/images/example.png?d41d8cd98f00b204e9800998ecf8427e);
}

Por muy útil que sea esta característica, es posible que la estructura de carpetas existente ya esté configurada de la manera que usted quiera. Si este es el caso, puedes deshabilitar la reescritura de url() de esta manera:

mix.sass('resources/sass/app.scss', 'public/css')
    .options({
        processCssUrls: false
    });

Con esta adición a su archivo webpack.mix.js, Mix ya no coincidirá con ninguna url() ni copiará activos a su directorio público. En otras palabras, el CSS compilado se verá tal como lo escribiste originalmente:

.example {
    background: url("../images/thing.png");
}

Source Maps

Aunque está desactivado por defecto, los mapas de origen pueden activarse llamando al método mix.sourceMaps() en su archivo webpack.mix.js. Aunque viene con un coste de compile/performance, esto proporcionará información extra de depuración a las herramientas de desarrollo de su navegador cuando utilice los activos compilados.

mix.js('resources/js/app.js', 'public/js')
    .sourceMaps();

Estilos de mapeo de fuentes

Webpack ofrece una variedad de estilos de mapeo de fuentes. Por defecto, el estilo de mapeo de fuentes de Mix está configurado como eval-source-map, lo que proporciona un rápido tiempo de reconstrucción. Si quieres cambiar el estilo de mapeo, puedes hacerlo usando el método sourceMaps:

let productionSourceMaps = false;

mix.js('resources/js/app.js', 'public/js')
    .sourceMaps(productionSourceMaps, 'source-map');

Trabajando con JavaScript

Mix proporciona varias características para ayudarle a trabajar con sus archivos JavaScript, como la compilación de ECMAScript 2015, la agrupación de módulos, la minificación y la concatenación de archivos JavaScript simples. Aún mejor, todo esto funciona perfectamente, sin requerir una onza de configuración personalizada:

mix.js('resources/js/app.js', 'public/js');

Con esta única línea de código, ahora puede aprovecharse:

  • ES2015 syntax.
  • Modules
  • Compilation of .vue files.
  • Minification for production environments.

Extracción del proveedor

Un posible inconveniente de la combinación de todas las aplicaciones específicas de JavaScript con las bibliotecas de sus proveedores es que dificulta el almacenamiento en caché a largo plazo. Por ejemplo, una sola actualización del código de la aplicación obligará al navegador a volver a descargar todas las bibliotecas de los proveedores, aunque no hayan cambiado.

Si tiene la intención de realizar actualizaciones frecuentes del JavaScript de su aplicación, debería considerar la posibilidad de extraer todas las bibliotecas de sus proveedores en su propio archivo. De esta manera, un cambio en el código de su aplicación no afectará al almacenamiento en caché de su gran archivo vendor.js. El método extract de Mix's hace que esto sea muy sencillo::

mix.js('resources/js/app.js', 'public/js')
    .extract(['vue'])

El método extract acepta un conjunto de todas las bibliotecas o módulos que desee extraer en un archivo vendor.js. Utilizando el fragmento anterior como ejemplo, Mix generará los siguientes archivos:

  • public/js/manifest.js: The Webpack manifest runtime
  • public/js/vendor.js: Your vendor libraries
  • public/js/app.js: Your application code

Para evitar errores de JavaScript, asegúrese de cargar estos archivos en el orden correcto:

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

React

Mix puede instalar automáticamente los plug-ins de Babel necesarios para el soporte de React. Para empezar, reemplace su llamada mix.js() por mix.react():

mix.react('resources/js/app.jsx', 'public/js');

Entre bastidores, Mix descargará e incluirá el plug-in de babel-preset-react apropiado.

Vanilla JS

De manera similar a la combinación de hojas de estilo con mix.styles(), también puedes combinar y minificar cualquier número de archivos de JavaScript con el método scripts():

mix.scripts([
    'public/js/admin.js',
    'public/js/dashboard.js'
], 'public/js/all.js');

Esta opción es particularmente útil para los proyectos de legado en los que no se requiere la compilación de Webpack para su JavaScript.

A slight variation of mix.scripts() is mix.babel(). Its method signature is identical to scripts; however, the concatenated file will receive Babel compilation, which translates any ES2015 code to vanilla JavaScript that all browsers will understand.

Configuración personalizada del Webpack

Entre bastidores, Laravel Mix hace referencia a un archivo webpack.config.js preconfigurado para ponerlo en marcha lo antes posible. Ocasionalmente, puede que necesites modificar manualmente este archivo. Puede que tengas un cargador especial o un plug-in que necesite ser referenciado, o tal vez prefieras usar Stylus en lugar de Sass. En tales casos, tienes dos opciones:

Fusión de la configuración personalizada

Mix proporciona un útil método de webpackConfig que permite fusionar cualquier configuración corta de Webpack anulada. Esta es una opción particularmente atractiva, ya que no requiere que copies y mantengas tu propia copia del archivo webpack.config.js. El método webpackConfig acepta un objeto, que debe contener cualquier configuración específica de Webpack que desees aplicar.

mix.webpackConfig({
    resolve: {
        modules: [
            path.resolve(__dirname, 'vendor/laravel/spark/resources/assets/js')
        ]
    }
});

Archivos de configuración personalizada.

Si desea personalizar completamente la configuración de su Webpack, copie el archivo node_modules/laravel-mix/setup/webpack.config.js al directorio raíz de su proyecto. A continuación, apunte todas las referencias --config de su archivo package.json al archivo de configuración recién copiado. Si elige este enfoque de personalización, cualquier futura actualización del webpack.config.js de Mix debe ser fusionada manualmente en su archivo personalizado.

Copia de archivos y directorios

El método copy puede utilizarse para copiar archivos y directorios a nuevas ubicaciones. Esto puede ser útil cuando un activo particular dentro de su directorio node_modules necesita ser reubicado en su carpeta public.

mix.copy('node_modules/foo/bar.css', 'public/css/bar.css');

Al copiar un directorio, el método copy aplanará la estructura del mismo. Para mantener la estructura original del directorio, debes usar el método copyDirectory en su lugar:

mix.copyDirectory('resources/img', 'public/img');

Versionado / Cache Busting

Muchos desarrolladores añaden a sus activos compilados una marca de tiempo o un símbolo único para obligar a los navegadores a cargar los activos nuevos en lugar de servir copias viejas del código. Mix puede manejar esto por ti usando el método version.

El método version añadirá automáticamente un hash único a los nombres de todos los archivos compilados, lo que permite una mayor facilidad para romper la caché:

mix.js('resources/js/app.js', 'public/js')
    .version();

Después de generar el archivo versionado, no sabrás el nombre exacto del archivo. Por lo tanto, deberías usar la función global de Laravel mix dentro de tus vistas para cargar el activo de hash de manera apropiada. La función mix determinará automáticamente el nombre actual del archivo hasheado:

<script src="{{ mix('/js/app.js') }}"></script>

Dado que los archivos versionados suelen ser innecesarios en el desarrollo, puede ordenar que el proceso de versionado sólo se ejecute durante npm run production:

mix.js('resources/js/app.js', 'public/js');

if (mix.inProduction()) {
    mix.version();
}

URLs de la base de la mezcla personalizada

Si los activos compilados de la mezcla se despliegan en un CDN separado de su aplicación, tendrá que cambiar la URL base generada por la función mix. Puede hacerlo añadiendo una opción de configuración mix_url a su archivo de configuración config/app.php:

'mix_url' => env('MIX_ASSET_URL', null)

Después de configurar la URL de la mezcla, la función mix antepondrá el URL configurado cuando genere las URL a los activos:

https://cdn.example.com/js/app.js?id=1964becbdd96414518cd

Recarga de Browsersync

BrowserSync puede monitorear automáticamente sus archivos en busca de cambios, e inyectar sus cambios en el navegador sin necesidad de refrescarlos manualmente. Puedes habilitar el soporte llamando al método mix.browserSync():

mix.browserSync('my-domain.test');

// Or...

// https://browsersync.io/docs/options
mix.browserSync({
    proxy: 'my-domain.test'
});

Puede pasar una cadena (proxy) o un objeto (configuración de BrowserSync) a este método. A continuación, inicia el servidor de desarrollo de Webpack usando el comando npm run watch. Ahora, cuando modifiques un script o un archivo PHP, observa cómo el navegador actualiza instantáneamente la página para reflejar tus cambios.

Variables del entorno

Puedes inyectar variables de entorno en Mix, anteponiendo una clave en tu archivo .env con MIX_:

MIX_SENTRY_DSN_PUBLIC=http://example.com

Una vez definida la variable en su archivo .env puede acceder a ella a través del objeto process.env. ISi el valor cambia mientras se está ejecutando una tarea de watch, tendrá que reiniciar la tarea:

process.env.MIX_SENTRY_DSN_PUBLIC

Notificaciones

Cuando esté disponible, Mix mostrará automáticamente las notificaciones del sistema operativo para cada paquete. Esto te dará una respuesta instantánea, para saber si la compilación tuvo éxito o no. Sin embargo, puede haber casos en los que prefieras desactivar estas notificaciones. Un ejemplo de ello podría ser activar Mix en tu servidor de producción. Las notificaciones pueden ser desactivadas, a través del método disableNotifications.

mix.disableNotifications();