nuxt-layers-utils
TypeScript icon, indicating that this package has built-in type declarations

0.3.0 • Public • Published

Nuxt Layers Utils

A collection of utilities to work with Nuxt layers

Nuxt Layers Utils logo

Abstract

Nuxt Layers are great to modularise your applications, but they can be fiddly, verbose and repetitive to configure when you have many layers, reconfigured folders, aliases, nested component folders, auto-imports, etc.

Nuxt Layers Utils provides a common interface to generate these disparate configuration options – hopefully saving you from shouting at your laptop because you misconfigured some path setting.

Usage

Installation

Install from NPM:

npm i --save-dev nuxt-layers-utils

Configuration

[!IMPORTANT] Read this before designing your layers

Nuxt's path-oriented configuration settings take a variety of formats: absolute, relative, folder names, root-relative, layer-relative, aliased, etc, etc, and it's not always clear which should be used when. Additionally, not all settings work as expected when configured in layer config files.

And because it's tricky to chase down path-related config across multiple folders, I strongly recommend to configure everything path-related in your project's main nuxt.config.ts.

See my article on Nuxt Layers for more information:

Overview

The package provides a useLayers() factory which:

  • takes an absolute baseDir path
  • takes a layers config object
  • provides a set of named config methods, i.e. alias(), dir()
  • provides additional utility and helper functions, i.e. only(), rel(), obj()

You create a layers helper, then sprinkle generated config into your main nuxt.config.ts as required.

Simple example

A simple example with:

  • three layers
  • path aliases
import { useLayers } from 'nuxt-layers-utils'

const layers = useLayers(__dirname, {
  core: 'core',
  blog: 'layers/blog',
  site: 'layers/site',
})

export default defineNuxtConfig({
  extends: layers.extends(),
  alias: layers.alias('#'),
})

That generates:

export default {
  extends: [
    'core',
    'layers/blog',
    'layers/site'
  ],
  alias: {
    '#core': '/Volumes/Projects/some-project/core',
    '#blog': '/Volumes/Projects/some-project/layers/blog',
    '#site': '/Volumes/Projects/some-project/layers/site',
  },
}

Complex example

A complex example with:

  • multiple layers
  • layer aliases
  • additional custom aliases
  • reconfigured default folders
  • additional auto-imports
  • vite aliases
import { useLayers } from 'nuxt-layers-utils'
import { defineNuxtConfig } from 'nuxt/config'
import { resolve } from 'pathe'

// configure helper
const layers = useLayers(__dirname, {
  core: 'core',
  auth: 'layers/auth',
  account: 'layers/account',
  services: 'layers/services',
  site: 'layers/site',
})

// set up global aliases; note is a mix of layer and non layer code
const alias = {
  // layers
  ...layers.alias('#'),

  // core
  ...layers.only('core').alias('~/', [
    'components',
    'composables',
    'utils',
  ]),

  // site
  ...layers.only('site').alias('~/', [
    'public',
    'pages',
  ]),

  // third party
  '~/libs': resolve('../../libs'),
}

// build the final config 
export default defineNuxtConfig({
  // add all layers
  extends: layers.extends(),

  // reconfigure core nuxt folders
  dir: {
    ...layers.dir('core', [
      'middleware',
      'modules',
      'plugins',
    ]),
    ...layers.dir('site', [
      'assets',
      'layouts',
      'pages',
      'public',
    ]),
  },

  // add additional layer auto-import folders
  imports: {
    dirs: [
      ...layers.importsDirs([
        'config',
        'state',
      ]),
    ],
  },

  // add layer aliases
  alias,

  // configure vite to use the same aliases
  vite: {
    resolve: {
      alias: layers.viteResolveAlias(alias),
    },
  },
})

A manual setup might look more like:

export default {
  // layers
  extends: [
    'core',
    'layers/auth',
    'layers/account',
    'layers/services',
    'layers/site'
  ],

  // aliases, layers, core and third party
  alias: {
    // layer-level aliases (prefixed with a `#`)
    '#core': '/Volumes/Projects/some-project/core',
    '#auth': '/Volumes/Projects/some-project/layers/auth',
    '#account': '/Volumes/Projects/some-project/layers/account',
    '#tools': '/Volumes/Projects/some-project/layers/services',
    '#site': '/Volumes/Projects/some-project/layers/site',

    // core
    '~/components': '/Volumes/Projects/some-project/core/components',
    '~/composables': '/Volumes/Projects/some-project/core/composables',
    '~/utils': '/Volumes/Projects/some-project/core/utils',
    '~/public': '/Volumes/Projects/some-project/layers/site/public',
    '~/pages': '/Volumes/Projects/some-project/layers/site/pages',

    // third-party
    '~/libs': '/Volumes/Projects/libs',
    '#basicscroll': 'basicscroll'
  },

  // auto-imports
  imports: {
    dirs: [
      'core/config',
      'core/state',
      'layers/auth/config',
      'layers/auth/state',
      'layers/account/config',
      'layers/account/state',
      'layers/services/config',
      'layers/services/state',
      'layers/site/config',
      'layers/site/state'
    ]
  },

  // default folders
  dir: {
    // core
    middleware: 'core/middleware',
    modules: 'core/modules',
    plugins: 'core/plugins',

    // site
    assets: 'layers/site/assets',
    layouts: 'layers/site/layouts',
    pages: 'layers/site/pages',
    public: 'layers/site/public'
  },

  // aliases for vite (transformed version of core aliases)
  vite: {
    resolve: {
      alias: [
        { find: '...', replace: '...' },
        ...
      ]
    }
  }
}

API

Factory function:

Config methods:

Named after the config they provide, and listed in most-useful order

Utilities:

Helpers:

See the tests folder for working code examples.

useLayers()

Factory function to provide a standardised interface to generate layer and path-specific config.

Params:

@param baseDir   The absolute path to the project `nuxt.config.ts`
@param layers    A hash of layer keys and relative folder paths

Example:

const layers = useLayers(__dirname, {
  core: 'core',
  blog: 'layers/blog',
  site: 'layers/site',
  ...
})

export default defineNuxtConfig({
  extends: layers.extends(),
  ...
})

extends()

Used with config.extends

Generates the array of relative folder paths which Nuxt should treat as layers

Example:

{
  extends: layers.extends()
}

Result:

{
  extends: [
    'core',
    'layers/blog',
    'layers/site'
  ]
}

alias()

Used with config.alias

Generates path aliases for both named layers and arbitrary folders.

Params:

 @param prefix      The required alias prefix
 @param folders     An optional set of folder paths, defaults to layers config

Example 1; generate default layer aliases:

{
  alias: layers.alias('#')
}

Result:

{
  alias: {
    '#core': '/Volumes/Projects/some-project/core',
    '#blog': '/Volumes/Projects/some-project/layers/blog',
    '#site': '/Volumes/Projects/some-project/layers/site',
  }
}

Example 2; generate custom aliases:

{
  alias: layers.alias('~/', [
    'foo/components',
  ])
}

Result:

{
  alias: {
    '~/foo/components': '/Volumes/Projects/some-project/foo/components',
  }
}

dir()

Used with config.dir

Reconfigures Nuxt's core default folders, such as assets, modules, server, etc.

Params:

@param key         A valid layer key, i.e. 'core'
@param folders     An array of valid config.dir folder keys

Example:

{
  dir: layers.dir('core', ['assets', 'modules'])
}

Result:

{
  dir: {
    assets: 'core/assets',
    modules: 'core/modules'
  }
}

dirPath()

Used with config.dir[folder]

Generate a single relative path from a named layer.

Params:

 @param key         A valid layer key, i.e. 'core'
 @param folder      A valid config.dir folder, i.e. 'assets'

Example:

{
  dir: {
    assets: layers.dirPath('site', 'assets')
  }
}

Result:

{
  dir: {
    assets: 'layers/site/assets'
  }
}

importsDirs()

Used with config.imports.dirs

Determines which folders should be auto-imported by Nuxt.

Params:

 @param folders   An optional list of folders, defaults to AUTO_IMPORTS

Example:

{
  imports: {
    dirs: layers.importsDirs([
      'store'
    ])
  }
}

Result:

{
  imports: {
    dirs: [
      'core/store',
      'layers/blog/store',
      'layers/site/store',
    ]
  }
}

components()

Used with config.components

Override default component naming and registration, to prevent path-prefixing for components.

Note that Nuxt registers layers' component folders by default, using the default of path-prefixing sub-folder components, with the following effective config:

{ pathPrefix: true, global: false, prefix: '' }

So, you should only need to use this helper to change those defaults of one or more layers.

Params:

@param     global        Optional Boolean to register the components globally, defaults to false
@param     prefix        Optional String to prefix component names, defaults to ""
@param     pathPrefix    Optional Boolean to prefix component names with the full path, defaults to false

Example:

{
  components: layers.components()
}

Result:

{
  components: [
    { path: '~/core/components', pathPrefix: false },
    { path: '~/layers/blog/components', pathPrefix: false },
    { path: '~/layers/site/components', pathPrefix: false },
  ]
}

contentSources()

Used with content.sources

Generates Nuxt Content sources.

Tips:

  • combine with layers.only() to target only layers with content folders
  • if you need something more complex, consider obj() or abs()

Params:

@param prefix     An optional prefixing option; defaults to 'auto'
                  - 'auto' to prefix all but the first layer
                  - an object to map layer keys to prefixes
                  - true to prefix with the layer key, i.e. '/blog'
                  - false for no prefix

Example:

{
  content: {
    sources: layers.only('site blog').contentSources()
  }
}

Result:

{
  content: {
    sources: {
      site: {
        // note – no prefix for the first picked layer from `only()`
        base: '/Volumes/Projects/some-project/layers/site/content',
        driver: 'fs'
      },
      blog: {
        prefix: '/blog',
        base: '/Volumes/Projects/some-project/layers/blog/content',
        driver: 'fs'
      }
    }
  }
}

viteResolveAlias()

Used with config.vite.resolve.alias

[!Note] This seems to be required when adding additional layer aliases (but do your own checks)

Generate path aliases for Vite.

Params:

@param aliases     The same alias hash used in `config.alias`

Example:

// pass the same `alias` hash to both configurations
const alias = { ... }

{
  alias: layers.alias(alias)
  vite: {
    resolve: {
      alias: layers.viteResolveAlias(alias)
    }
  }
}

Result:

{
  vite: {
    alias: { ... },
    resolve: {
      alias: [
        { find: '#core', replace: '/Volumes/Projects/some-project/core' },
        { find: '#blog', replace: '/Volumes/Projects/some-project/layers/blog' },
        { find: '#site', replace: '/Volumes/Projects/some-project/layers/site' },
      ]
    }
  }
}

Utils

only()

Choose only certain layers to get config for.

Note that the hash will be rebuilt in the order of the specified keys.

Params:

@param filter       A space-delimited string of layer keys, or an array of layer keys

Example:

const alias = {
  ...layers.only('site').alias('~/', [
    'components',
    'composables',
    'utils',
  ]),
}

Result:

{
  alias: {
    '~/components' : '/Volumes/Projects/some-project/layers/site/components',
    '~/composables' : '/Volumes/Projects/some-project/layers/site/composables',
    '~/utils' : '/Volumes/Projects/some-project/layers/site/utils',
  }
}

rel()

Generate the relative path to a layer folder or sub-folder.

@param key         A valid layer key, i.e. 'site'
@param folder      An optional folder, i.e. 'assets'

Example:

layers.rel('site', 'assets')

Result:

'layers/site/assets'

abs()

Generate the absolute path to a layer folder or sub-folder.

@param key         A valid layer key, i.e. 'site'
@param folder      An optional folder, i.e. 'assets'

Example:

layers.abs('site', 'assets')

Result:

'/Volumes/Projects/some-project/layers/site/assets'

obj()

Utility function to return a hash of config options from a user-defined callback.

Note that this is bound to the useLayers() instance.

@param     callback    Callback function passing key, rel, abs and index values

Example:

{
  someConfig: layers.only('site blog').obj((key, rel, abs, index) => {
    return {
      key,
      rel,
      abs,
      index,
    }
  })
}

Result:

{
  site: {
    key: 'site',
    rel: 'layers/site/assets',
    abs: '/Volumes/Projects/some-project/layers/site/assets',
    index: 0,
  }
  blog: {
    key: 'blog',
    rel: 'layers/blog/assets',
    abs: '/Volumes/Projects/some-project/layers/blog/assets',
    index: 1,
  }
}

arr()

Utility function to return an array of config options from a user-defined callback

Note that this is bound to the useLayers() instance.

@param     callback    Callback function passing key, rel, abs and index values

Example:

{
  someConfig: layers.only('site blog').arr((key, rel, abs, index) => {
    return {
      key,
      rel,
      abs,
      index,
    }
  })
}

Result:

[
  {
    key: 'site',
    rel: 'layers/site/assets',
    abs: '/Volumes/Projects/some-project/layers/site/assets',
    index: 0,
  }
  {
    key: 'blog',
    rel: 'layers/blog/assets',
    abs: '/Volumes/Projects/some-project/layers/blog/assets',
    index: 1,
  }
]

layers

Reference to the original layers config

Example:

useLayers({ blog: 'layers/blog' }).layers

Result:

{ blog: 'layers/blog' }

Helpers

logConfig()

Dump the full, expanded and colorized content of your Nuxt config to the console.

Params:

@param config       A Nuxt configuration object

Example:

import { logConfig } from 'nuxt-layers-utils'

export default logConfig(defineNuxtConfig({
  extends: ...,
  dir: ...,
  imports: ...,
  alias: ...,
  vite: ...,
}))

Result:

{
  extends: [
    'core',
    'layers/auth',
    ...
  ],
  dir: {
    middleware: 'core/middleware',
    modules: 'core/modules',
    ...
  },
  imports: {
    dirs: [
      'core/config',
      'core/state',
      '...
    ]
  },
  alias: {
    '#core': '/Volumes/Projects/some-project/core',
    '#auth': '/Volumes/Projects/some-project/layers/auth',
    ...
  },
  vite: {
    resolve: {
      alias: [
        {
          find: '#core',
          replacement: '/Volumes/Projects/some-project/core'
        },
        {
          find: '#auth',
          replacement: '/Volumes/Projects/some-project/layers/auth'
        },
        ...
      ]
    }
  }
}

Addendum

Nuxt config

Nuxt config options which may reference paths or folders.

Layer-specific:

Core folders:

Other:

Readme

Keywords

Package Sidebar

Install

npm i nuxt-layers-utils

Weekly Downloads

31

Version

0.3.0

License

ISC

Unpacked Size

36 kB

Total Files

5

Last publish

Collaborators

  • davestewart