Laravel 9 (with Vite) and Vue 3 integration [For Metronic v8.1.6+]

Requirement

  • Metronic version v8.1.6+
  • PHP 8.1.9+
  • Composer 2.4.1+
  • Node 16.16.0+


  • Create a new Laravel 9 project


    1. In the beginning, we need to create a Laravel+Vue project (in this example, we will create a project named vue_laravel) by running a command.

      composer create-project --prefer-dist laravel/laravel vue_laravel


    2. Navigate to the newly created folder with the command below.

      cd vue_laravel


    Install dependencies


    1. Metronic 8 Vue theme already contains almost all required dependencies for this integration, to get started we can copy a list of "dependencies" from package.json in Vue and place them into vue_laravel/package.json.

      Also, include "devDependencies" listed below.

      "array-sort": "^1.0.0",
      "sass": "^1.44.0",
      "sass-loader": "^12.4.0",

    2. Let's install vue vite plugin.

      npm install --save-dev @vitejs/plugin-vue

    3. Install all dependencies by running the following command.
      npm install


    Prepare vue files and theme resources


    1. Copy public/media folder from Vue project into vue_laravel/public/ folder.

    2. From public folder in vue project copy files listed below and paste them into public folder in Laravel folder.
      > favicon.ico
      > splash-screen.css

    3. Copy vite variables from .env file in vue project and paste them to vue_laravel/.env and vue_laravel/.env.example files.

    4. Create ts folder inside vue_laravel/resources/ts and inside this folder create file app.ts.

    5. Copy src folder and paste it into vue_laravel/resources/ts.

    6. The main entry point of the vue project is main.ts, we need to import it in app.ts, copy import below and paste it to your vue_laravel/resources/ts/app.ts.
      import "./src/main";


    Configure vite.config.js


    1. Copy vite.js configuration below and paste it to your vue_laravel/vite.config.js.

      import { defineConfig } from "vite";
      import laravel from "laravel-vite-plugin";
      import vue from "@vitejs/plugin-vue";
      import path from "path";

      export default defineConfig({
      base: "/",
      plugins: [
      vue({
      template: {
      transformAssetUrls: {
      base: null,
      includeAbsolute: false,
      },
      },
      }),
      laravel({
      input: ["resources/css/app.css", "resources/js/app.js"],
      refresh: true,
      }),
      ],
      resolve: {
      alias: {
      "@/": path.join(__dirname, "/resources/ts/src/"),
      "~": path.join(__dirname, "/node_modules/"),
      },
      },
      build: {
      chunkSizeWarningLimit: 1600,
      },
      });



    Prepare app.blade.php


    1. Now we can add a new file inside resources/views. Let's call it app.blade.php

    2. Copy the code below and paste it to your app.blade.php.
      <!DOCTYPE html>
      <html>

      <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>Metronic Vue and Laravel Starterkit</title>
      <link rel="icon" href="./favicon.ico">
      <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,400,500,600,700">
      <link rel="stylesheet" href="./splash-screen.css">

      @vite('resources/css/app.css')
      </head>

      <body class="page-loading">
      <!--begin::Theme mode setup on page load-->
      <script>
      if (document.documentElement) {
      var defaultThemeMode = "system";

      var name = document.body.getAttribute("data-kt-name");
      var themeMode = localStorage.getItem("kt_" + (name ? name + "_" : "") + "theme_mode_value");

      if (themeMode === null) {
      if (defaultThemeMode === "system") {
      themeMode = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
      } else {
      themeMode = defaultThemeMode;
      }
      }
      document.documentElement.setAttribute("data-theme", themeMode);
      }
      </script>
      <!--end::Theme mode setup on page load-->


      <div id="app"></div>
      <!--begin::Loading markup-->
      <div class="splash-screen">
      <img src="./media/logos/default-small.svg" alt="Metronic logo" />
      <span>Loading ...</span>
      </div>
      <!--end::Loading markup-->

      @vite('resources/ts/app.ts')
      </body>
      </html>



    3. Now we can add a new route to file routes/web.php.
      Route::get('/', function () {
      return view('app');
      });


    Run project


    1. Firstly we need to build the client, let's run the command.
      npm run dev


    2. This command will build our js/css files and will listen for changes in our vue folder to hot-reload them. Keep client-server running.

    3. In another tab navigate the project and run laravel project with the command below.
      php artisan serve


    4. Wait for the app to display that it is running on http://127.0.0.1:8000 then open this URL in your browser.

    Text formatting options
    Submit
    Here's a how to add some HTML formatting to your comment:
    • <pre></pre> for JS codes block
    • <pre lang="html"></pre> for HTML code block
    • <pre lang="scss"></pre> for SCSS code block
    • <pre lang="php"></pre> for PHP code block
    • <code></code> for single line of code
    • <strong></strong> to make things bold
    • <em></em> to emphasize
    • <ul><li></li></ul>  to make list
    • <ol><li></li></ol>  to make ordered list
    • <h3></h3> to make headings
    • <a></a> for links
    • <img> to paste in an image
    • <blockquote></blockquote> to quote somebody
    • happy  :)
    • shocked  :|
    • sad  :(

    Replies (8)

    Hi,
    Thanks for the update.

    I've a few questions about the vite config.
    1. Why is base: "/assets" ? Probably when you npm run dev it will become http://127.0.0.1:8000/assets.
    2. Why is inpunt resources/js/app.js and not resources/ts/app.ts
    3. Can you also describe how to prepare the other files like .eslintrc.cjs and tsconfig.json?

    Update
    I've followed the steps and when I run 'npm run dev', I'm getting the following error:

    failed to load config from ./vite.config.js
    error when starting dev server:
    Error: Cannot find module 'laravel-vite-plugin'
    Require stack:
    - ./vite.config.js
    - ./rijsoftware/node_modules/vite/dist/node/chunks/dep-5605cfa4.js

    Hi,


    1. If you want you can avoid this by removing the base path property from vite.config.js and then updating paths in file vue_laravel/resources/ts/src/core/helpers/assets.ts. For getIllustrationsPath and getAssetPath you will need to remove / before media in a path otherwise you will have two slashes before the path and non of the media files will be found.

    2. It was the default configuration code if you are planning to handle all your frontend with vue you can just remove this plugin from the list.

      app.ts file is specified inside your view:

      @vite('resources/ts/app.ts')


    3. I will add this to our backlog. For now to add eslint you can refer to https://gist.github.com/EmadAdly/b356690a4cb3b9a79d6757d5ebd6c93c

    This package should be in the list of devDependencies by default, you should keep default devDependencies and add those I described in the post.

    Regards,
    Lauris Stepanovs,
    Keenthemes Support Team

    Well, I followed the steps and changed resources/js/app.js to resources/ts/app.ts. I had to install laravel-vite-plugin too. After doing this I run the command

    npm run build-only

    because npm run build wasn't working
    transforming (1) resources/ts/app.tsERROR: "type-check" exited with 1.

    Finally it's working, but with a lot of console errors, because the assets are not found. e.g.:
    - http://127.0.0.1:8000/assets/assets/LayoutService.73065d7f.js net::ERR_ABORTED 404 (Not Found)
    - http://127.0.0.1:8000/assets/assets/SignIn.37bee318.js net::ERR_ABORTED 404 (Not Found)
    - http://127.0.0.1:8000/assets/assets/assets.1bc0fb6f.js net::ERR_ABORTED 404 (Not Found)
    - http://127.0.0.1:8000/assets/assets/sweetalert2.all.31f6258e.js net::ERR_ABORTED 404 (Not Found)

    and many more...

    Is it working on your side? Can you maybe create a video tutorial or just a simple starter kit with laravel vue? Chatting is taking to much time sadsadsad. I've waited 1 week for the doc update, but it's still not complete and not working!!!

    During the testing, we didn't have these errors.

    Did you include all of the devDependencies?

    "devDependencies": {
    "@vitejs/plugin-vue": "^4.0.0",
    "array-sort": "^1.0.0",
    "axios": "^1.1.2",
    "laravel-vite-plugin": "^0.7.2",
    "lodash": "^4.17.19",
    "postcss": "^8.1.14",
    "sass": "^1.44.0",
    "sass-loader": "^12.4.0",
    "vite": "^4.0.0"
    }

    Regards,
    Lauris Stepanovs,
    Keenthemes Support Team

    Yes, those packages are included. I'll write down step by step what I did:
    1. Create a new Laravel 9 project
    2. Install dependencies

    3. Prepare vue files and theme resources
    Copied public/media to public/assets/ and public (for to be sure). So now I have public/media and public/assets/media

    4. Configure vite.config.js

    export default defineConfig({
    plugins: [
    vue({
    template: {
    transformAssetUrls: {
    base: null,
    includeAbsolute: false,
    },
    },
    }),
    laravel({
    input: ["resources/css/app.css", "resources/ts/app.ts"],
    refresh: true,
    }),
    ],
    resolve: {
    alias: {
    "@/": path.join(__dirname, "/resources/ts/src/"),
    "~": path.join(__dirname, "/node_modules/"),
    },
    },
    build: {
    chunkSizeWarningLimit: 3000,
    },
    });

    5. Prepare app.blade.php

    6. Remove / from vue_laravel/resources/ts/src/core/helpers/assets.ts.
    I have also added BASE_URL to .env; BASE_URL=BASE_URL=https://demo:8890

    export const getIllustrationsPath = (illustrationName: string): string => {
    const extension = illustrationName.substring(
    illustrationName.lastIndexOf("."),
    illustrationName.length
    );
    const illustration =
    useThemeStore().mode == "dark"
    ? `${illustrationName.substring(
    0,
    illustrationName.lastIndexOf(".")
    )}-dark`
    : illustrationName.substring(0, illustrationName.lastIndexOf("."));
    return (
    import.meta.env.BASE_URL +
    `media/illustrations/${illustrationsSet.value}/${illustration}${extension}`
    );
    };

    export const getAssetPath = (path: string): string => {
    return import.meta.env.BASE_URL + path;
    };

    6. Run project
    npm run dev

    VITE v3.2.5 ready in 1084 ms

    ➜ Local: http://127.0.0.1:5173/
    ➜ Network: use --host to expose

    LARAVEL v9.45.1 plugin v0.7.3

    ➜ APP_URL: https://demo:8890

    php artisan serve

    INFO Server running on [http://127.0.0.1:8000]. 

    Press Ctrl+C to stop the server

    When I go to http://127.0.0.1:8000 or https://demo:8890 app is running, but media or icons are not loaded. I see many errors, e.g.:
    - GET https://media/misc/auth-screens.png net::ERR_NAME_NOT_RESOLVED
    - GET https://media/stock/600x400/img-20.jpg net::ERR_NAME_NOT_RESOLVED

    Maybe it helps; I am working Mac with Mamp PRO.

    Hi,

    You need to remove BASE_URL property from your .env file. You overrided BASE_URL property, which refers to public folder by default.

    Regards,
    Lauris Stepanovs,
    Keenthemes Support Team

    Hello,

    I have tried this solution with Metronic version 8.1.7 but it does not work. I have several errors with the imports, it seems that the alias does not pass? I don't know what is happening.

    Can you help me to install Metronic 8.1.7 in laravel 9 with fast and Vue?


    Thanks in advance, pray

    Hi,

    Could you please send us your error messages?

    Regards,
    Lauris Stepanovs,
    Keenthemes Support Team

    Text formatting options
    Submit
    Here's a how to add some HTML formatting to your comment:
    • <pre></pre> for JS codes block
    • <pre lang="html"></pre> for HTML code block
    • <pre lang="scss"></pre> for SCSS code block
    • <pre lang="php"></pre> for PHP code block
    • <code></code> for single line of code
    • <strong></strong> to make things bold
    • <em></em> to emphasize
    • <ul><li></li></ul>  to make list
    • <ol><li></li></ol>  to make ordered list
    • <h3></h3> to make headings
    • <a></a> for links
    • <img> to paste in an image
    • <blockquote></blockquote> to quote somebody
    • happy  :)
    • shocked  :|
    • sad  :(
    Text formatting options
    Submit
    Here's a how to add some HTML formatting to your comment:
    • <pre></pre> for JS codes block
    • <pre lang="html"></pre> for HTML code block
    • <pre lang="scss"></pre> for SCSS code block
    • <pre lang="php"></pre> for PHP code block
    • <code></code> for single line of code
    • <strong></strong> to make things bold
    • <em></em> to emphasize
    • <ul><li></li></ul>  to make list
    • <ol><li></li></ol>  to make ordered list
    • <h3></h3> to make headings
    • <a></a> for links
    • <img> to paste in an image
    • <blockquote></blockquote> to quote somebody
    • happy  :)
    • shocked  :|
    • sad  :(