Skip to content

Is the idea to eschew blade templates? #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wishinghand opened this issue Sep 10, 2018 · 12 comments
Closed

Is the idea to eschew blade templates? #11

wishinghand opened this issue Sep 10, 2018 · 12 comments

Comments

@wishinghand
Copy link

We have a landing page that is a blade template(landing.blade.php) so we can use Laravel directives to handle authentication. Once authorized we send the user to an authorized page(spa.blade.php) with a Laravel $user object being passed in as a prop to the top level Vue component. Working with the instructions on this repo's README I got the feeling that this is not the workflow Evan You had in mind.

Should we instead switch to only using API calls to handle authentication?

@emanuelmutschlechner
Copy link
Contributor

You're right. This repo shows how to completely replace Laravel's frontend with Vue.

You could change the build process and write your Vue frontent to spa.blade.php. This will allow you to use the authentication system of Laravel.

https://github.com/yyx990803/laravel-vue-cli-3/blob/master/frontend/vue.config.js#L13-L15

And don't forget to apply the auth middleware in the controller.
https://github.com/yyx990803/laravel-vue-cli-3/blob/master/app/Http/Controllers/SpaController.php#L7-L13

@tsekka
Copy link

tsekka commented Nov 18, 2018

Hi, any tips on how I can add <meta name="csrf-token" content="{{ csrf_token() }}"> to spa.blade.php automatically each time i run npm run build command?

Update: Silly me. Just had to add it to public/index.html.

@wishinghand
Copy link
Author

None. We couldn't figure out a way around it without greatly altering our authentication so we didn't upgrade to vue-cli 3.

@TheJoeSchr
Copy link

After banging my head against it the whole of yesterday and today, I got figured out how to still use it with a blade file.

This is more a hack/workaround until it is better supported, but works at my end. The goal is to still use my index.blade.html which has the <meta name="csrf-token" content="{{ csrf_token() }}"> inside, because I still need to use it until I build my authentication with Vue.
Also I wanted to get a HMRis beheavior work, so I could still use yarn serve while developing instead of having to rerun yarn build everytime I change anything. For this we will create our own vuemix helper to replace laravel-mix mix() in our .blade.html files. I used best practices described here for this.

So without further ado:

We need to create 2 new files:

  • /bootstrap/helpers.php
  • /frontend/hmr/hot

helper.php:
this file adds a new laravel/blade/php helper vuemix() which we will use in our blade file instead of mix()

<?php
use Illuminate\Support\Str;
use Illuminate\Support\HtmlString;

if (! function_exists('vuemix')) {
    /**
     * Get the path to a versioned Mix file.
     *
     * @param  string  $path
     * @param  string  $manifestDirectory
     * @return \Illuminate\Support\HtmlString|string
     *
     * @throws \Exception
     */
    function vuemix($path, $manifestDirectory = '')
    {
        if (! Str::startsWith($path, '/')) {
            $path = "/{$path}";
        }

        // check if HMR server is running via helper file 'hot'
        if (file_exists(public_path($manifestDirectory.'/hot'))) {
            $url = file_get_contents(public_path($manifestDirectory.'/hot'));
            $main = '/app.js'; // only use this as path, because css, etc are already packed in HMR mode

            if (Str::startsWith($url, ['http://', 'https://'])) {
                return new HtmlString(Str::after($url, ':').$main);
            }

            return new HtmlString('//localhost:8080'.$main);
        }
        return new HtmlString($path); // return path without changing anything aka production
    }
}

after we have to also add our new "helpers.php" to
/composer.json so laravel knows to load it:

  "autoload": {
            ...              
        "files": [
            ...
            "bootstrap/helpers.php" 
        ]
    },

with that out of the way, in your index.blade.html file replace all occurrences of mix() e.g.

    <body>
        <div id="app"> </div><!-- #app -->
        <!-- Scripts -->
        @stack('before-scripts')
                {!! script(mix('js/app.js')) !!}
    </body>

with

   <body>
        <div id="app"> </div><!-- #app -->
        <!-- Scripts -->
        @stack('before-scripts')
           {{script(vuemix('js/app.js'))}}
           {{script(vuemix('js/chunk-vendors.js'))}}
    </body>

you can do the same with your css files, it will then load app.js for it, since yarn serve seems to pack the css into the livereload app.js.

VERY IMPORTANT

one detailed which took me forever: if you are coming from laravel-mix you probably only link your app.js and you are done. but here you also have to link chunk-vendors.js, which for some reason get's splitted and I can't turn off, because it's a feature. so if you only had 1 line of linked JS, you now need two.

Almost done.
Now we just have to edit your package.json and vue.config.json so it creates and temporary hot file when yarn serve is started and also doesn't overwrite your index.php and creates your js files without version hashes when you use yarn build. because we have linked them above directly without these hashed. the hot file modus operanti I got from laravel-mix as a way to figure out if we are using yarn serve or yarn build. don't hit me for it, I told you it's hackish ;)

package.json:
edit this scripts, to copy and remove our hot file

  "scripts": {
    "serve": "cp ./hmr/hot ../public/ && vue-cli-service serve",
    "build": "rm -rf ../public/{js,css,img,hot} && vue-cli-service build --no-clean",
  }

pay attention to hot on the build line, it looks almost the same then the original line.

now create /frontend/hmr/hot and fill it with this:

http://localhost:8080/

now vue.config.json add this lines, from vue-cli documentation:

  ////  Disable Index.html Generation
  // disable hashes in filenames
  filenameHashing: false,
  // delete HTML related webpack plugins
  chainWebpack: config => {
    if (process.env.NODE_ENV === "production") {
      config.plugins.delete('html')
      config.plugins.delete('preload')
      config.plugins.delete('prefetch')
    }
  },

you can also edit indexPath back, since index isn't generated anymore while building:

  // modify the location of the generated HTML file.
  // make sure to do this only in production.
  indexPath: "index.html",

And with this it should now be possible to use yarn serve and yarn build with a "classical" laravel blade setup.

@tsekka
Copy link

tsekka commented Jan 3, 2019

I ended up modifying laravel-vue-cli-3 example project like this
(i have 2 separate folders: project/backend and project/frontend ):

  1. To frontend/public/index.html , add:
    <meta name="csrf-token" content="{{ csrf_token() }}">

  2. frontend/vue.config.js:

outputDir: '../backend/public/',
assetsDir: '1',
...
  1. package.json scripts:
"serve": "vue-cli-service serve",
"build": "rm -rf ../backend/public/1 && vue-cli-service build --no-clean",

@yob-yob
Copy link

yob-yob commented May 24, 2019

now create /frontend/hmr/hot and fill it with this:

http://localhost:8080/

what is /frontend/hmr/hot ?
is it a file? what's the ext?
is /hmr the vue-cli project folder?
why should I put http://localhost:8080/

whos package.json file did you modify? Vue's or Laravel's?

EDIT

never got mine working.. thank you by the way 😄

@TheJoeSchr
Copy link

TheJoeSchr commented May 24, 2019

now create /frontend/hmr/hot and fill it with this:

http://localhost:8080/

what is /frontend/hmr/hot ?
is it a file? what's the ext?

it's a text file we created, no extension

is /hmr the vue-cli project folder?

yes

why should I put http://localhost:8080/

because:

 $url = file_get_contents(public_path($manifestDirectory.'/hot'));

whos package.json file did you modify? Vue's or Laravel's?

vue. laravel is php

EDIT
never got mine working.. thank you by the way 😄

sorry, still works here

@yob-yob
Copy link

yob-yob commented May 26, 2019

GREAT.. got it working finally .. thank you sooo much 💋 I love you man..

@TheJoeSchr
Copy link

anytime!

@mudin
Copy link

mudin commented Jul 1, 2019

I changed laravel-mix to laravel-vue-cli-3 in order to solver hot loading issue, but seems complicated here too. Plus I need to keep filenameHashing = true. production mode is fine. But in development mode not all APIs are working because of csrf_token`

@shpeedle
Copy link

shpeedle commented Oct 6, 2020

@JoeSchr Did you mean index.blade.php?

I kinda want to set this up, are you still using your imp? Looks cool. Laravel-mix is just not working for us on a real app right now w/ vue.

@TheJoeSchr
Copy link

TheJoeSchr commented Oct 8, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants