brillout / goldpage

Page Builder.
Creative Commons Zero v1.0 Universal
57 stars 3 forks source link

Pass express `req` object to `addInitialProps()`? #10

Closed chriscalo closed 4 years ago

chriscalo commented 4 years ago

Might it be possible to pass the express req object to addInitialProps() so I don't have to do nested destructuring?

Here's how I can access the req object today:

import page from "./index.vue";

export default {
  route: "/",
  view: page,
  renderToHtml: true,
  addInitialProps({ res: { req }, res, next }) {
    // ...
  },
};

But this would be better:

import page from "./index.vue";

export default {
  route: "/",
  view: page,
  renderToHtml: true,
  addInitialProps({ req, res, next }) {
    // ...
  },
};
brillout commented 4 years ago

The req object is already deconstructed into initialProps.

This is how initialProps is assembled:

    return ({
      isNodejs,
      ...requestObject,
      ...pageConfig,
      ...urlProps.query,
      ...urlProps,
      ...routeArguments,
      ...addInitialProps__result,
      __sources: {
        pageConfig,
        addInitialProps: addInitialProps__result,
        requestObject,
        urlProps,
        routeArguments,
        isNodejs,
      },
    });

When using Express requestObject===req.

Source code: https://github.com/reframejs/goldpage/blob/master/helpers/repage/common/getInitialProps.js

So you should be able to access all req props directly at initialProps.

chriscalo commented 4 years ago

That makes a lot more sense now. Thanks.

Thoughts on not merging all of those objects and simplifying the names somewhat?

import page from "./index.vue";

export default {
  route: "/",
  view: page,
  renderToHtml: true,
  addInitialProps({ req, url, params, page, isServer }) {
    // ...
  },
};

To explain what I mean, I ended up creating this utility function for transforming the initialProps object that gets passed to addInitialProps() functions.

// transform `initialProps` parameter that Goldpage passes `addInitialProps()`
export function simplifyContext(context) {
  const {
    __sources: {
      requestObject: req,
      urlProps: url,
      routeArguments: params,
      pageConfig: page,
      isNodejs: isServer,
    },
  } = context;

  return {
    req,
    url,
    params,
    page,
    isServer,
  };
}
brillout commented 4 years ago

You can do:

import page from "./index.vue";
import assert from "assert";

export default {
  route: "/hello/:name",
  view: page,
  addInitialProps(initialProps) {
    const {pathname, name, headers, query, url} = intialProps;
    assert(pathname==='/hello/chris');
    assert(name==='chris');
    assert(headers.cookie); // (every prop of `req` is merged into `initialProps`)
    // You can even access URL query paramaters:
    assert(url==='http://localhost:8000/hello/chris?pageNumber=3');
    assert(query.pageNumber==='3');

    // Etc.
  },
};

Basically, everything is flat merged into initialProps. I know it's unusual at first but it's actually super comfy. And __sources is there in case of collisions; you should use __sources only when you have collision problems, that is almost never.

chriscalo commented 4 years ago

I’ll give that a try 👍