npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

next-routes-dir

v0.4.7

Published

`next-routes-dir` provides a way to use Next.js 13's `app/` directory colocation features while still using the feature-set of the old `pages/` directory. With `next-routes-dir`, you can create a `routes/` folder in your Next.js app that mirrors the folde

Downloads

49

Readme

next-routes-dir

next-routes-dir provides a way to use Next.js 13's app/ directory colocation features while still using the feature-set of the old pages/ directory. With next-routes-dir, you can create a routes/ folder in your Next.js app that mirrors the folder structure of Next.js 13's app/ directory, and it will automatically generate a valid pages/ directory based on the structure of the routes/ directory.

You might be wondering, why don't we use Next.js 13's app/ directory directly? In addition to the app/ directory still being in beta, there are many incompatibilities and breaking changes from the pages/ directory that require a substantial amount of work to migrate. However, the co-location features of the app/ directory is very useful, so next-routes-dir provides a way to leverage the co-located structure of files inside the app/ directory while still maintaining the same feature set provided by the pages/ directory.

Usage

Install next-routes-dir from npm:

npm install next-routes-dir

Then, refactor your existing pages/ folder to the app/ directory structure inside a routes/ folder.

For example, the following pages/ directory:

.
└── pages/
    ├── index.tsx
    ├── login.tsx
    ├── app/
    │   └── index.tsx
    └── profile/
        └── [id].tsx

could be converted into the following routes/ directory:

.
└── routes/
    ├── login/
    │   └── page.tsx
    ├── (marketing)/
    │   └── page.tsx
    └── (app)/
        ├── layout.tsx
        ├── app/
        │   └── page.tsx
        └── profile/
            └── [id]/
                └── page.tsx

Then, import and run setupRoutesDirectoryWatcher in your next.config.js file:

// next.config.js
const { setupRoutesDirectoryWatcher } = require('next-routes-dir')
const path = require('path')

setupRoutesDirectoryWatcher({
  routesDir: path.join(__dirname, 'routes'),
  pagesDir: path.join(__dirname, 'src/pages')
})

module.exports = {
  // ...
}

If you want to wrap your exported components inside a wrapper function, you can pass componentWrapperFunction:

// next.config.js
const { setupRoutesDirectoryWatcher } = require('next-routes-dir')
const path = require('path')

setupRoutesDirectoryWatcher({
  routesDir: path.join(__dirname, 'routes'),
  pagesDir: path.join(__dirname, 'src/pages'),
  componentWrapperFunction: {
    name: '__definePage',
    path: '~/utils/page'
  }
})

module.exports = {
  // ...
}

This would generate component exports that look like the following:

import { __definePage } from '~/utils/page'
export default __definePage(() => (
  <div>...</div>
))

Unlike the pages/ directory, next-routes-dir also supports getServerSideProps from layout files! It does this by merging the results of the getServerSideProps in the layout file and the getServerSideProps in the route file.

Caveats

Since the generated pages simply re-export getServerSideProps from the routes file, Next.js is unable to treeshake the getServerSideProps from the original routes file. To work around this, you can use a custom Webpack plugin like the following:

// next.config.js
module.exports = {
  webpack(config) {
    // Use string-replace-loader last, so that it runs _after_ everything has been transformed to JavaScript
    config.module.rules.unshift({
      test(id: string) {
        return routesDirs.some((routesDir) => isPathInside(id, routesDir))
      },
      loader: 'string-replace-loader',
      options: {
        search: /^[\S\s]*$/,
        replace(match: string) {
          const ast = acorn.parse(match, {
            ecmaVersion: 2020,
            sourceType: 'module'
          }) as any

          // Find the `getServerSideProps` named export
          const exportNamedDeclaration = ast.body.find(
            (node: any) =>
              (node.type === 'ExportNamedDeclaration' &&
                // Matches `export const getServerSideProps = ...`
                node.declaration?.declarations?.[0]?.id?.name ===
                  'getServerSideProps') ||
              // Matches `export function getServerSideProps() { ... }`
              node.declaration?.id === 'getServerSideProps'
          )

          // If a `getServerSideProps` export can't be found, return the original source code
          if (exportNamedDeclaration === undefined) {
            return match
          }

          const replacement =
            match.slice(0, exportNamedDeclaration.start) +
            match.slice(exportNamedDeclaration.end)

          return replacement
        }
      }
    })
  }
}