Create a SPA with Laravel and Nuxt
Cristian Pallarés

Cristian Pallarés @skyrpex

Joined:
Dec 25, 2016

Create a SPA with Laravel and Nuxt

Publish Date: Feb 13 '18
200 55

In this tutorial we'll use Laravel as an API and Nuxt as a Single Page Application. They can work together, but it's not an easy task at first. If you already tried, getting HMR to seamlessly work is a pain! For that reason I created laravel-nuxt and laravel-nuxt-js.

There are more reasons to use these packages, such as when using Laravel Passport and the CreateFreshApiToken. The middleware will create an api_token cookie on web routes that use the get http verb, and that's a problem if you're not serving your SPA from within Laravel.

Getting started

Install Laravel

Let's start with fresh new Laravel installation:

composer create-project laravel/laravel spa
Enter fullscreen mode Exit fullscreen mode

Go inside the spa directory with your terminal.

Install laravel-nuxt (for PHP)

# cd spa
composer require pallares/laravel-nuxt
Enter fullscreen mode Exit fullscreen mode

This package will be autodiscovered. If you're using old versions of Laravel, just add the service provider in config/app.php file:

<?php
return [
    // ...
    'providers' => [
        // ...
        Pallares\LaravelNuxt\LaravelNuxtServiceProvider::class,
    ],
];
Enter fullscreen mode Exit fullscreen mode

Add a fallback route that will render the SPA page in routes/web.php file. Be sure to remove the default route that comes with the framework:

<?php
// Route::get('/', function () {
//     return view('welcome');
// });

Route::get(
    '{uri}',
    '\\'.Pallares\LaravelNuxt\Controllers\NuxtController::class
)->where('uri', '.*');
Enter fullscreen mode Exit fullscreen mode

Now, your backend is ready to serve the compiled assets that Nuxt will generate for you. Every route that would return a 404 now will serve our SPA page.

Install laravel-nuxt (for JS)

It's time to install the JS package. Replace your package.json file with this:

{
    "private": true,
    "scripts": {
        "start": "laravel-nuxt dev",
        "build": "laravel-nuxt build"
    },
    "dependencies": {
        "laravel-nuxt": "^1.0.0"
    }
}
Enter fullscreen mode Exit fullscreen mode

Install the dependencies:

npm install
Enter fullscreen mode Exit fullscreen mode

The laravel-nuxt package will install Nuxt for you, along with Vue, vue-router, @nuxtjs/axios, etc. Let's create the nuxt.config.js file:

const laravelNuxt = require("laravel-nuxt");

module.exports = laravelNuxt({
  // Options such as mode, srcDir and generate.dir are already handled for you.
  modules: [],
  plugins: [],
});
Enter fullscreen mode Exit fullscreen mode

From now on, Nuxt will look for the source files in the resources/nuxt directory.

Create a hello world route in resources/nuxt/pages/index.vue:

<template>
  <h1>Hello {{ name }}!</h1>
</template>

<script>
export default {
  data: () => {
    return { name: 'world' };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Finally, run:

npm start
Enter fullscreen mode Exit fullscreen mode

Go to http://localhost:8000. You should see this: hello-world-picture

That's it! Laravel artisan's server and Nuxt's dev server are up and working together transparently. Try editing your home page now, it's very enjoyable to see the live reload in action.

Under the hood, Nuxt's dev server is proxying every call to the Laravel's server, including the SPA rendering. Since @nuxtjs/axios module is included (and proxied, too), you can make API calls normally.

Calling the API from the SPA

The SPA will surely need to call our API, so let's add a route to routes/api.php to retrieve the user information:

<?php
Route::get('me', function () {
    // Let's return fake information.
    return [
        'name' => 'John Doe',
    ];
});
Enter fullscreen mode Exit fullscreen mode

Now, edit resources/nuxt/pages/index.vue:

<template>
  <h1>Hello {{ user.name }}!</h1>
</template>

<script>
export default {
    // https://github.com/nuxt-community/axios-module
    async asyncData({ app }) {
        const user = await app.$axios.$get('api/me');
        return { user };
    },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Voila! Your page should now look like this!

api-call-picture

In order to keep the tutorial simple, we aren't using any kind of authentication here. Integrating Passport should be almost trivial here.

Deployment

If you want to deploy your application, just run npm run build. The compiled assets will be placed in the public/_nuxt directory.

You can preview your final app with the well known artisan command php artisan serve.

You may want to add the .nuxt and public/_nuxt directories to your .gitignore.

Final thoughts

This is my first tutorial. I hope everything is clear and concise! Please, don't hesitate to ask questions here or create issues in the laravel-nuxt repositories. Thanks!

Comments 55 total

  • leob
    leobFeb 27, 2018

    That's an impressive piece of work, a full Laravel/Nuxt integration! How did you get all of this 'magic' working? I'm planning to read your source code to understand how it works under the hood.

    Searching for "laravel" and "nuxt" I saw that there were only a few Github projects dealing with this, that's a bit surprising since Laravel has a heavy 'bias' towards Vue.js and SSR (and hence Nuxt.js) seems a good fit for many Laravel projects (especially content-focused apps/websites).

    I saw one other Laravel/Nuxt starter repo, but yours seems a bit more clean and lightweight.

    Definitely want to try this out (another option would be to go for a pure Javascript approach, using node/express for the API/backend/server part rather than PHP/Laravel).

    However the ease of development and the vibrant community are what attract me to a Laravel based solution (compared to for instance Django).

    • Cristian Pallarés
      Cristian PallarésFeb 27, 2018

      Thanks! I think you'll an easy time reading from the source: there isn't much code and part of it is documented using docblocks.

      I also searched for a Laravel&Nuxt integration, but found none that fit my tastes. I expect your feedback on it soon! :)

      The ease of development and the code quality is what attracts me to using Laravel as an API too. There are a few things I'd change from Laravel, but I still love it!

      I'll create another tutorial about authorization using LaravelNuxt in the next weeks... maybe you'll be interested.

      • leob
        leobFeb 28, 2018

        Great job ... what surprised me is that while Laravel "ships" with Vue.js you can hardly find anything about integrating Laravel with Nuxt, even though the two seem a natural combo. Your repo seems to be one of the very few solutions!

        What I understood is that in fact you need Javascript on the server (node/express) to support SSR. So what you did (if I understood correctly) is run a separate node/express server and proxy requests between the node server and the Laravel server, right? And then you just code your app in Laravel (the API part) and Vue (the client part), no need to worry about the node/express part.

        Sounds pretty nifty, I'll read your source code to understand the details.

        Yes I would definitely be interested in your authorization tutorial with LaravelNuxt!

  • Mohamed  AbdAlAzim
    Mohamed AbdAlAzimMar 7, 2018

    I can't get it! the api/me should have been requested from the server and pre-rendered before reaching the client side, am I right?

    I can see the request in the network inspection, that should make no difference between acyncData and normal data?

    please clarify this for me, thanks :).

    • Cristian Pallarés
      Cristian PallarésMar 7, 2018

      Hi! There's no prerendering when using laravel-nuxt. The api/me request is sent from client side when activating the JS route.

      You should use async data if you need your page to wait to be rendered until the data is fetched.

  • olivedev
    olivedevMar 31, 2018

    Really good app. But it is also possible to create Laravel single page app without using vue-router, but that would mean using Laravel for backend rendering. This may not be that efficient but it is easier to do.

  • Mathew Paret
    Mathew ParetApr 1, 2018

    It fails at npm start command:

    @ start /Users/mathewparet/eclipse/workspace/getitdone
    laravel-nuxt dev

    /Users/mathewparet/eclipse/workspace/getitdone/node_modules/laravel-nuxt/bin/laravel-nuxt-dev.js:52
    ...process.env,
    ^

    SyntaxError: Unexpected token ...
    at createScript (vm.js:74:10)
    at Object.runInThisContext (vm.js:116:10)
    at Module._compile (module.js:533:28)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Function.Module.runMain (module.js:605:10)
    at startup (bootstrap_node.js:158:16)
    at bootstrap_node.js:575:3
    npm ERR! code ELIFECYCLE
    npm ERR! errno 1
    npm ERR! @ start: laravel-nuxt dev
    npm ERR! Exit status 1
    npm ERR!
    npm ERR! Failed at the @ start script.
    npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

    npm ERR! A complete log of this run can be found in:
    npm ERR! /Users/mathewparet/.npm/_logs/2018-04-01T14_39_48_780Z-debug.log
    gMac:getitdone mathewparet$

    • Cristian Pallarés
      Cristian PallarésApr 1, 2018

      Hi there. You need to upgrade your node version: v8 and v9 are tested, but not sure if v6 works.

  • Eduardo Lulichac
    Eduardo Lulichac Apr 2, 2018

    Hello Cristian I have a question, when I see the source code of my view, I don't see the rendered text of Hello Eduardo, why? help me please.
    thepracticaldev.s3.amazonaws.com/i...

    • Cristian Pallarés
      Cristian PallarésApr 3, 2018

      Hello Eduardo. What you're seeing is the generic page that Nuxt provides to you (it's always the same because there's no server side rendering). When the JS is loaded, the Vue Router will render the correct HTML (depending on the actual URL).

      • alfredriesen
        alfredriesenApr 22, 2018

        Hello Cristian. But the major feature to use nuxt is server side rendering from my point of view. How can I achieve that with laravel-nuxt and laravel-nuxt-js?

        • Cristian Pallarés
          Cristian PallarésApr 23, 2018

          This is not at the scope as for now. If you want to use SSR you'll need to solve some problems like starting node from within PHP and passing some data. laravel-nuxt offers a simple and easy solution to get started, but without SSR.

          • Josué Artaud
            Josué ArtaudSep 24, 2018

            What's the point of using Nuxtjs if not for ssr?

            • Cristian Pallarés
              Cristian PallarésSep 25, 2018

              You can still benefit from:

              • The already configured Webpack and the dev and build commands.
              • The Nuxt ecosystem: any existing module and plugin is already done for you.
              • The routes autoloading.
              • The Vuex modules autoloading.
              • The asyncData and other meta methods.
              • Peyas  chandra das
                Peyas chandra dasFeb 17, 2020

                vue routing is not working as in nuxt working . how can i config vue routing .. ? looking for solution thanks.

  • Jagroop Singh
    Jagroop SinghApr 6, 2018

    Nice and clean !, <3 Thanks !

  • Mariusz Franciszczak
    Mariusz FranciszczakApr 27, 2018

    I have a question (I do not know if I understood correctly) or will it work on a production server without noda? I am a beginner so I ask, and I would love to use NUXT in my application

    • Cristian Pallarés
      Cristian PallarésMay 22, 2018

      You don't need node in production, only in development. You must include your compiled assets in the deployment process.

  • Gal Jakič
    Gal JakičApr 29, 2018

    Can Laravel Mix still be used as part of the build process? I’m using Tailwind for utility-based CSS approach & would like to utilize their PurgeCSS setup as part of it. Mix makes that in incredibly elegant solution. Thanks!

    • Cristian Pallarés
      Cristian PallarésSep 22, 2018

      This is tightly coupled to nuxt... I don't think they can be merged, but you can still setup PurgeCSS and use Tailwind!

  • Grover Sean Reyes
    Grover Sean ReyesJun 16, 2018

    How can I use valet to run my app?

    ( somehow okay, I just used "npm run build")

    but How can I use valet while constantly editing my *.vue files?

    • Cristian Pallarés
      Cristian PallarésJun 23, 2018

      I'm not sure how Laravel Valet works, but the laravel-nuxt package assumes you have php installed.

  • almokhtar bekkour
    almokhtar bekkourSep 21, 2018

    that was so helpful , thank you

  • jintoples
    jintoplesApr 24, 2019

    I have problem with static resouces images, not found 404 after npm run build.

    • Cristian Pallarés
      Cristian PallarésApr 24, 2019

      Hi there! Are the images in the public/_nuxt directory after building? If not, do you use the resources/nuxt/static directory to publish images?

      You could also try to import the images in your components (you'll receive the URL string) and use it in the views.

      • RobertBar
        RobertBarJul 7, 2019

        Hi Cristian. What about the files that are stored in the Laravel storage folder? I am not able to access them. Should I try another approach or I am on the right path?

        UPDATE: I have created a symlink for storage/ inside static folder. Everyhting is working as expected.

      • rdigitalg
        rdigitalgDec 19, 2019

        Hello, Cristian. On npm run build i can't access the files from static directory. There is something extra I need to do in order to access them? Thank you!

    • rdigitalg
      rdigitalgDec 19, 2019

      Hi, @jintoples . How did you managed to fix this error? My files can be accessed when I run npm run start but when I run npm run build the files are not available anymore.

  • Hein Htet Aung (Hnhtag)
    Hein Htet Aung (Hnhtag)Apr 26, 2019

    That's impressive. I got a chance to learn. Thanks

  • deoraczo
    deoraczoApr 30, 2019

    php artisan serve --host=domain --port=8000 not working

  • RobertBar
    RobertBarJun 9, 2019

    Great tutorial Cristian. I have already implemented a login system using JWT authentication and @nuxtjs/auth.

  • RobertBar
    RobertBarJun 18, 2019

    Hi, Cristian!
    Do you have any idea why baseURL it is recognized only when using "npm run build" and "php artisan serve" commands? When I run "npm run start" the baseURL it is not using the provided value
    axios: {
    baseURL: development ? 'devsite/api' : "livesite/api"
    },

    • RobertBar
      RobertBarJun 18, 2019

      Found a solution: browserbaseURL should be provided also.

      axios: {
      baseURL: development ? 'devsite/api' : "livesite/api",
      browserBaseURL: development ? 'devsite/api' : "livesite/api"
      },

  • Bilell Ghersa
    Bilell GhersaSep 6, 2019

    Easy and simpl, kind of tutorials i lieke

  • Charlie Rydholm
    Charlie RydholmOct 7, 2019

    I've deployed an application built with laravel-nuxt. But after I've deployed it gives me alot of 404 error messages.

    searching for files with random letters and numbers in it.

    In the /_nuxt/ file. But my _nuxt file is no longer in the ./public folder, it's in a sibling folder to the root, named public_html. How can I fix this?

    • Cristian Pallarés
      Cristian PallarésOct 7, 2019

      Did you change the configuration to change the public directory? The /_nuxt directory should be accessible publicly, so it should be at public/_nuxt, along with the index.php.

      • Charlie Rydholm
        Charlie RydholmOct 7, 2019

        Yeah but I've deployed it to shared hosting so I was needed to place everything in my public folder into public_html So my folder structure does look like this now

        -app
        ---everything except public folder
        -public_html
        ---everything that was in the the public folder

        So i need to change the path, when I try to launch my website it gives me 404 errors on the wierd file names. looking for it in myHostAddress/_nuxt/
        But instead it should look for it in myHostAddress/myName/public_html/_nuxt

        This happened directly after i built it and launched even if I keep the same folder structure, it seeks in myHostAddress/_nuxt/ instead of myHostAddress/myName/MyApp/public

        Been trying to solve it for days now..

        • Charlie Rydholm
          Charlie RydholmOct 7, 2019

          Do I need to build a new application, because this does not support shared hosting?

  • Nathaniel David
    Nathaniel DavidNov 1, 2019

    Please which directory should I create the nuxt.config.js, I'm new to nuxt.

    • rdigitalg
      rdigitalgDec 19, 2019

      On the root of your app. Eg: my-laravel-app/nuxt.config.js

  • Florence Comajes
    Florence ComajesNov 15, 2019

    is it fully support on deploying to vapor ?

    • Cristian Pallarés
      Cristian PallarésNov 15, 2019

      I think it should work out of the box, providing that you run the build script.

  • ThisIsntMyId
    ThisIsntMyIdNov 30, 2019

    Can I still use this in 2019?

  • lordroseman
    lordrosemanFeb 15, 2020

    Hi, why I cant add vuetify in this laravel-nuxt? After I follow your instructions, I added nuxt/vuetify by running:

    "npm install @nuxtjs/vuetify -D" 
    

    then I add the buildModules in nuxt.config.js it looks like this:

    const laravelNuxt = require("laravel-nuxt");
    
    module.exports = laravelNuxt({
        // Options such as mode, srcDir and generate.dir are already handled for you.
        modules: [],
        plugins: [],
        buildModules: [
            // Simple usage
            '@nuxtjs/vuetify',
        ]
    });
    


    `

    then I run: npm start and it gives me error:

    `

    [laravel] Laravel development server started: http://127.0.0.1:8001
    npm ERR! code ELIFECYCLE
    npm ERR! errno 1
    npm ERR! @ start: `laravel-nuxt dev`
    npm ERR! Exit status 1
    npm ERR!
    npm ERR! Failed at the @ start script.
    npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
    
    npm ERR! A complete log of this run can be found in:
    npm ERR!     C:\Users\HP\AppData\Roaming\npm-cache\_logs\2020-02-15T04_21_37_327Z-debug.log
    

    What did I do wrong? Can you please help me? Thanks! :D

  • BELHARRADI JAMAL
    BELHARRADI JAMALApr 4, 2020

    how to use mutiple nuxt projects ??

    • Cristian Pallarés
      Cristian PallarésApr 7, 2020

      The package targets one Nuxt project per Laravel API. I suggest using Laravel Sanctum now, which handles SPA authentication for you easily (with support for any number of projects).

  • Anatoli
    AnatoliJun 13, 2020

    If I add the universal mode to the nuxt.config.js file, the spa mode still remains when the application starts (npm run start).

    What does it take to get the SSR to turn on?

    • keetamhoang
      keetamhoangJul 20, 2020

      hello, Have you solved this problem yet?

  • Kousar Rahman
    Kousar RahmanAug 6, 2020

    @ start /opt/lampp/htdocs/nuxt

    laravel-nuxt dev

    [laravel] Laravel development server started: 127.0.0.1:8001
    [nuxt] › [HPM] Proxy created: [ '*/', '!/laravel_nuxt' ] -> 127.0.0.1:8001
    [nuxt] › baseURL: /
    [nuxt] › browserBaseURL: /
    [nuxt] 2020-08-06T19:30:00.853Z nuxt:build App root: /opt/lampp/htdocs/nuxt/resources/nuxt
    [nuxt] 2020-08-06T19:30:00.854Z nuxt:build Generating /opt/lampp/htdocs/nuxt/.nuxt files...
    [nuxt] 2020-08-06T19:30:00.886Z nuxt:build Generating files...
    [nuxt] 2020-08-06T19:30:00.888Z nuxt:build Generating routes...
    [nuxt] 2020-08-06T19:30:00.937Z nuxt:build Building files...
    [nuxt] 2020-08-06T19:30:01.694Z nuxt:build Adding webpack middleware...
    [nuxt] ERROR Failed to compile with 1 errors1:30:03 AM
    [nuxt]
    [nuxt] error in ./.nuxt/client.js
    [nuxt] Module build failed: TypeError: /opt/lampp/htdocs/nuxt/.nuxt/client.js: this.setDynamic is not a function
    at PluginPass.pre (/opt/lampp/htdocs/nuxt/node_modules/babel-plugin-transform-runtime/lib/index.js:31:12)
    at transformFile (/opt/lampp/htdocs/nuxt/node_modules/@babel/core/lib/transformation/index.js:96:27)
    at transformFile.next ()
    at run (/opt/lampp/htdocs/nuxt/node_modules/@babel/core/lib/transformation/index.js:35:12)
    at run.next ()
    at Function.transform (/opt/lampp/htdocs/nuxt/node_modules/@babel/core/lib/transform.js:27:41)
    at transform.next ()
    at step (/opt/lampp/htdocs/nuxt/node_modules/gensync/index.js:254:32)
    at gen.next (/opt/lampp/htdocs/nuxt/node_modules/gensync/index.js:266:13)
    at async.call.value (/opt/lampp/htdocs/nuxt/node_modules/gensync/index.js:216:11)
    at errback.call (/opt/lampp/htdocs/nuxt/node_modules/gensync/index.js:184:28)
    at runGenerator.errback (/opt/lampp/htdocs/nuxt/node_modules/@babel/core/lib/gensync-utils/async.js:72:7)
    at val (/opt/lampp/htdocs/nuxt/node_modules/gensync/index.js:108:33)
    at step (/opt/lampp/htdocs/nuxt/node_modules/gensync/index.js:280:14)
    at gen.next (/opt/lampp/htdocs/nuxt/node_modules/gensync/index.js:266:13)
    at async.call.value (/opt/lampp/htdocs/nuxt/node_modules/gensync/index.js:216:11)

    @ multi webpack-hot-middleware/client?name=client&reload=true&timeout=30000&path=/__webpack_hmr ./.nuxt/client.js
    [nuxt] OPEN 127.0.0.1:8000

  • ramirezfer772
    ramirezfer772Aug 21, 2020

    Hi, I'm having a problem compiling tailwind runnning npm run build, however I can see all the tailwind stuff with nuxt running npm start, I configured the nuxt.config.js file with buildModules: ['@nuxtjs/tailwindcss'], but unable to compile tailwind in the public/_nuxt, Do you have any idea how to have tailwind styles in with npm run build? Thank you, amazing work anyway.

  • Jenuel Oras Ganawed
    Jenuel Oras GanawedMar 15, 2021

    any update on this? for 2021?

  • Kousar Rahman
    Kousar RahmanMar 31, 2021

    Hi I have build a application with laravel + nuxt js using pallares/laravel-nuxt package but after deploy this app it take too much time to load and show a preloader , how speed up this app .
    this this the app url :
    zanaj.com

  • Phạm Đức Huy
    Phạm Đức HuyDec 17, 2021

    It's not working for me. When I run npm start and open localhost:8000, it shows Error occured while trying to proxy to: 127.0.0.1:8000/ . There was no other process that occupying that port. What could be the problem? ([HPM] Error occurred while trying to proxy request /favicon.ico from 127.0.0.1:8000 to 127.0.0.1:8001 (ECONNREFUSED) (nodejs.org/api/errors.html#errors_...)

Add comment