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

Using next-routes with prefix #30

Closed
davidnguyen11 opened this issue Apr 28, 2017 · 6 comments
Closed

Using next-routes with prefix #30

davidnguyen11 opened this issue Apr 28, 2017 · 6 comments

Comments

@davidnguyen11
Copy link

Hi I have an issue like below:

server.js

app.prepare().then(() => {
  const server = express();
  const router = express.Router();

  router.get('/:area', (req, res) => {
    return app.render(req, res, '/index', req.query);
  });

  router.get('*', (req, res) => handle(wrappedRequest(req), res));

  server.use('/prefix', router);
  server.use('/prefix/static', express.static('static'));

  server.listen(3000, err => {
    if (err)
      throw err;
    console.log(`> Ready on http://localhost:3000/prefix`);
  });
});

what I want to do is using next-routes? It worked fine when not using prefix.

Is there any way to integrate prefix to next-route?

@fridays
Copy link
Owner

fridays commented Apr 28, 2017

I think you can't globally prefix a Next.js app like it's /static or /_next folders.

But you could do this in routes.js:

routes.add('index', '/prefix/:area')

And in server.js:

const routes = require('./routes')
const handle = routes.getRequestHandler(app)

app.prepare().then(() => {
  const server = express();
  server.use('/prefix/static', express.static('static'));
  server.use(handle);

  server.listen(3000, err => {
    if (err)
      throw err;
    console.log(`> Ready on http://localhost:3000/prefix`);
  });
});

@davidnguyen11
Copy link
Author

davidnguyen11 commented Apr 29, 2017

Hi @fridays!

Thanks for quick replying.

My solution is just exactly like you & I added some changes to it.

nextjs: ver 2.1.1

routes.js

const nextRoutes = require('next-routes');
const routes = module.exports = nextRoutes();

routes.add('index', '/prefix/:area');

server.js

const routes = require('./routes')
const handle = routes.getRequestHandler(app)

app.prepare().then(() => {
  const server = express();

  // create router from express
  const router = express.Router();

  // this will prevent 404 not found when copy & parse url in browser's address bar
  router.get('/:area', (req, res) => {
    return app.render(req, res, '/index', req.query);
  });

  router.get('*', (req, res) => {
    handle(req, res);
  });

  // bind prefix to resource url
  server.use('/prefix', router); 
  server.use('/prefix/static', express.static('static'));
  server.use(handle);

  server.listen(3000, err => {
    if (err)
      throw err;
    console.log(`> Ready on http://localhost:3000/prefix`);
  });
});

_document.js
Because I use prefix so that I have to modified _document.js to override <NextScript /> component to serve resource with prefix like this: vercel/next.js#257 (comment)

@AliasT
Copy link

AliasT commented Dec 19, 2017

@davidnguyen179 @fridays
it's working,but how about a route scope like express router

scope = routes.addScope("/prefix")
scope.add(somename, "/user")     // ===> "/prefix/user"

@sean256
Copy link

sean256 commented Apr 1, 2018

I'm using Next 5.0 which supports "zones" and asset prefixes. I was running into an issue where next-routes was not working well with 5.0's prefixes.

In case someone else has this issue, here is my hack until something better comes along:

const routes = require('next-routes')();

routes
  .add('postsPrefix', '/prefix/posts/:id?', 'posts')
  .add('posts', '/posts/:id?', 'posts'); // both have to exist

module.exports = routes;

Then to go to a prefixed page supported by next-routes:

Router.pushRoute('postsPrefix', { id });

@zvictor
Copy link

zvictor commented Apr 12, 2018

I wanted to have all my routes prefixed with assetPrefix, but I didn't manage to export it from the config file in a clean way.

My solution was to replicate assetPrefix in the public settings and override Link with it:

next.config.js

const PREFIX = '/myAppPrefix'

module.exports = {
  assetPrefix: PREFIX,
  publicRuntimeConfig: {
    assetPrefix: PREFIX,
  },
}

routes.js

const { mapProps } = require('recompose')
const NextLink = require('next/link').default
const config = require('next/config').default()

const mapper = ({ as, href, ...props }) => {
  const { assetPrefix } = config.publicRuntimeConfig

  return {
    ...props,
    as: `${assetPrefix}${as}`,
    href: `${assetPrefix}${href}`,
  }
}

const Link = mapProps(mapper)(NextLink)
const routes = (module.exports = require('next-routes')({ Link }))

routes.add('home', '/', 'index')
...

@stanleyfok
Copy link

stanleyfok commented Apr 22, 2018

My solution is to modify the findAndGetUrls method. I am using the ENV var named basedPath. It works nicely

next.config.js

module.exports = {
  assetPrefix: envConfig.ASSET_PREFIX,

  publicRuntimeConfig: {
    basePath: envConfig.BASE_PATH,
  },
}

server.js

...
          const server = express();
          const router = express.Router();

          router.get('*', (req, res) => handle(req, res));

          server.use(envConfig.BASE_PATH, router);

          server.listen(envConfig.PORT, (err) => {
            if (err) throw err;

            console.log(`> Ready on http://localhost:${envConfig.PORT}`);
          });
...

routes.js

const escapeRegExp = require('lodash/escapeRegExp');
const config = require('next/config').default();

const routes = require('next-routes')();

const oldFindAndGetUrls = routes.findAndGetUrls.bind(routes);

routes.findAndGetUrls = (nameOrUrl, params) => {
  const { basePath } = config.publicRuntimeConfig;

  let mNameOrUrl = nameOrUrl;
  if (basePath && basePath !== '/') {
    const re = new RegExp(`^${escapeRegExp(basePath)}`);
    mNameOrUrl = nameOrUrl.replace(re, '');
  }

  const findAndGetUrls = oldFindAndGetUrls(mNameOrUrl, params);

  if (basePath && basePath !== '/') {
    findAndGetUrls.urls.as = `${basePath}${findAndGetUrls.urls.as}`;
  }

  return findAndGetUrls;
};

// usage: routes.add(name, pattern, page);
routes
  .add('index', '/', 'index')
  .add('login', '/login', 'login');

module.exports = routes;

SeanDemps pushed a commit to SeanDemps/next-routes that referenced this issue Dec 13, 2018
Update dependency @types/node to v10.12.9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants