Skip to content
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

callback function required #6

Closed
ghost opened this issue Nov 5, 2016 · 18 comments
Closed

callback function required #6

ghost opened this issue Nov 5, 2016 · 18 comments

Comments

@ghost
Copy link

ghost commented Nov 5, 2016

Hey!

I'm getting this error:

throw new Error('callback function required');

My code is the example code

const http = require('http');
const express = require('express');
const expressVue = require('express-vue');

const app = express();

app.set('vue', {
    rootPath: __dirname + '/',
    layoutsDir: 'routes/',
    componentsDir: 'components/',
    defaultLayout: 'layout'
});
app.engine('vue', expressVue);
app.set('view engine', 'vue');

app.get('/', (req, res) => {
  res.render('main', {
      data : {
          otherData: 'Something Else'
      },
      vue: {
          meta: {
              title: 'Page Title',
          },
          components: ['myheader', 'myfooter']
      }

  });
});

http.createServer(app).listen(config['http-port'], config.ipAddress);

Why does express is telling me there is no callback?

@danielcherubini
Copy link
Collaborator

I'll take a look. But remember. You need to have those component files in the right place. You can't just add components in that don't exist.

So the library is going to expect these to exist.

app/layout.vue
app/routes/main.vue
app/components/myheader.vue
app/components/myfooter.vue

That's what it's going to expect looking at your config. If your stuck go have a look at the example project

https://github.com/danmademe/express-vue-example

I'll come back and look at this in a few hours.

@itsMapleLeaf
Copy link

Since the library is written as an ES6 module, export default x translates to exports.default = x. Then, when using require(), the usage becomes

app.engine('vue', expressVue.default) // and not just expressVue

When you pass in expressVue instead of expressVue.default, express gets confused, thinking you're not passing a valid plugin and raises an error.

@danielcherubini
Copy link
Collaborator

Looks like I forgot that the new babel doesn't include the default plugin anymore. I'll add it later and rebuild.

@danielcherubini
Copy link
Collaborator

If this solves the issue I'll close it. Thanks @just-nobody

@danielcherubini
Copy link
Collaborator

OK I've fixed the .defaults issue in the latest release
https://github.com/danmademe/express-vue/releases/tag/v3.0.1

@danielcherubini
Copy link
Collaborator

@jerome724 can you verify this and close the issue

@ghost
Copy link
Author

ghost commented Nov 7, 2016

Now i'm getting

C:\Users\jerom\git\web\node_modules\express-vue\dist\parser\index.js:97
            var layoutString = content.toString();
                                      ^

TypeError: Cannot read property 'toString' of undefined
    at ReadFileContext.callback (C:\Users\jerom\git\web\node_modules\express-vue\dist\parser\index.js:97:39)
    at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:335:13

directory structure is the one from the example.

@danielcherubini
Copy link
Collaborator

@jerome724 what version of node are you using?

@ghost
Copy link
Author

ghost commented Nov 7, 2016

I'm on v7.0.0

danielcherubini added a commit that referenced this issue Nov 7, 2016
@danielcherubini
Copy link
Collaborator

danielcherubini commented Nov 7, 2016

New version pushed to NPM

@3.0.2

@danielcherubini
Copy link
Collaborator

Issue was fs.readFile outputs a buffer, so instead of doing buffer.toString() i changed the way FS works by changing the output to UTF-8.

http://stackoverflow.com/questions/6456864/why-does-node-js-fs-readfile-return-a-buffer-instead-of-string

@ghost
Copy link
Author

ghost commented Nov 7, 2016

const express = require('express');
const expressVue = require('express-vue');

const app = express();

app.set('views', './views');

app.set('vue', {
  rootPath: './',
  layoutsDir: 'views/layouts',
  components: 'views/components',
  defaultLayout: 'main'
});

app.engine('vue', expressVue);
app.set('view engine', 'vue');

app.get('/', (req, res) => {
  res.render('index', {
    vue: {
      meta: {
        title: 'www.jerome724.com'
      }
    }
  });
});

app.listen(8080);

Is with this something wrong? Because i'm getting now

C:\Users\jerom\git\web\node_modules\express-vue\dist\parser\index.js:32
    var bodyString = body.match(htmlRegex)[0];
                         ^

TypeError: Cannot read property 'match' of undefined
    at htmlParser (C:\Users\jerom\git\web\node_modules\express-vue\dist\parser\index.js:32:26)
    at ReadFileContext.callback (C:\Users\jerom\git\web\node_modules\express-vue\dist\parser\index.js:98:24)
    at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:335:13)

@danielcherubini
Copy link
Collaborator

This is the function its calling

function htmlParser(body, minify) {
    let bodyString = body.match(htmlRegex)[0];
    ........
    return bodyString;
}

The error is that the body argument is undefined/null, it's getting called from the component parser

const body = htmlParser(content, true);

(the true is to minimise the output or not)

it means that the output from fs.readFile isn't being passed into it... which tells me it's unable to read the index.vue file..

Looking at your setup..
Assuming you're running this from a js file in the root

index.vue is in views/components/index.vue
and main.vue is in views/layouts/main.vue

so if this was run from say, the root, so your structure was like

your-app
   |- server.js   
   |- views
        |- components
               |-index.vue
        |- layouts
               |-main.vue

So if you ran node server.js it should be fine..

@danielcherubini
Copy link
Collaborator

remember if the component you're trying to access is in a sub directory of the components directory... so something like views/components/index/index.vue

you'd have to change the res.render('index', {}) to res.render('index/index', {})

@danielcherubini
Copy link
Collaborator

i made a test version

https://github.com/danmademe/express-vue-example-basic

git pull
npm install
node server.js

@danielcherubini
Copy link
Collaborator

the big difference?

app.set('vue', {
  rootPath: __dirname + '/views/',
  layoutsDir: 'layouts/',
  components: 'components/',
  defaultLayout: 'main'
});

......

app.get('/', (req, res) => {
  res.render('components/index', {
    vue: {
      meta: {
        title: 'www.jerome724.com'
      }
    }
  });
});

the rootpath was not set to where the root of the views were.. I will update this logic to fit better.

the second part was that when res.render is called, it is looking for a file relative to the rootPath... this logic won't be changed, because the components part of the config you set in app.set is for what I call sub-components, that is, components inside a component..

The way to think of it is like this

You have a Layout, that's your main file.. then what you set in res.render.. that's your route, or what i call your COMPONENT... if that component has components .. its what I call a "SUBCOMPONENT", which gets built into a vue component and placed in the route's components section...

@danielcherubini
Copy link
Collaborator

A better way of doing this... is like this

your-app
   |- server.js   
   |- views
        |- routes
               |- index.vue
        |- components
               |- header.vue
        |- layouts
               |- main.vue

So when you do res.render() it would be res.render('routes/index', {})

Separating the routes from components, so its a cleaner directory structure... the idea of components is the tiny reusable subcomponents that you use in your routes :)

@danielcherubini
Copy link
Collaborator

@jerome724 did this solve the issue?

onebesky pushed a commit to onebesky/express-vue that referenced this issue Oct 5, 2017
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

2 participants