Search code examples
laravelvue.jswebpacklaravel-mix

Config laravel mix to build specific vue app when component files change


My Laravel project with multiple Vue.js applications. The project directory structure is as follows:

├── public
│   ├── js
│   │   ├── app_the_first.js
│   │   ├── app_the_second.js
├── resources
│   ├── assets
│   │   ├── js
│   │   │   ├── the_first_components
│   │   │   │   ├── // Vue component files
│   │   │   ├── the_second_components
│   │   │   │   ├── // Vue component files
│   │   │   ├── app_the_first.js
│   │   │   ├── app_the_second.js
│   ├── sass
│   │   ├── app_the_first.js
│   │   ├── app_the_second.js
├── views
│   ├── the_first.blade.php
│   ├── the_second.blade.php
├── package.json
├── webpack.mix.js

when I change the_first_component and run npm run dev/prod, both app_the_first.js and app_the_second.js are re-build

My webpack.mix.js

const mix = require('laravel-mix');


mix.js('resources/assets/js/app_the_first.js', 'public/js').vue()
   .sass('resources/assets/sass/app_the_first.scss', 'public/css');

mix.js('resources/assets/js/app_the_second.js', 'public/js').vue()
   .sass('resources/assets/sass/app_the_second.scss', 'public/css');

I want to rebuild the app_the_first.js only, not rebuild the app_the_second.js


Solution

  • Laravel Mix does not natively support building selected assets out of the box because running npm run dev or npm run prod will trigger all tasks defined in webpack.mix.js. You can define an environment variable to specify which app you want to build:

    const mix = require('laravel-mix');
    
    const appName = process.env.APP_NAME;
    
    if (!appName || appName === 'the_first') {
        mix.js('resources/assets/js/app_the_first.js', 'public/js').vue()
           .sass('resources/assets/sass/app_the_first.scss', 'public/css');
    }
    
    if (!appName || appName === 'the_second') {
        mix.js('resources/assets/js/app_the_second.js', 'public/js').vue()
           .sass('resources/assets/sass/app_the_second.scss', 'public/css');
    }
    

    Then, you can use an environment variable when running your npm scripts to specify which app to compile:

    APP_NAME=the_first npm run dev
    
    APP_NAME=the_second npm run dev
    
    npm run dev
    

    modify your package.json scripts to include these new commands:

    "scripts": {
      "dev": "npm run development",
      "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
      "watch": "npm run development -- --watch",
      "watch-poll": "npm run watch -- --watch-poll",
      "hot": "cross-env NODE_ENV=development webpack-dev-server --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
      "prod": "npm run production",
      "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js",
      "dev-first": "cross-env APP_NAME=the_first npm run dev",
      "prod-first": "cross-env APP_NAME=the_first npm run production",
      "dev-second": "cross-env APP_NAME=the_second npm run dev",
      "prod-second": "cross-env APP_NAME=the_second npm run production"
    },
    

    Now you can use npm run dev-first to only compile the assets for the first app, and npm run dev-second for the second app.

    If you don’t have cross-env installed, you can install it with:

    npm install --save-dev cross-env