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

vite-split-config

v1.1.1

Published

Split monolithic config file into dedicated chunks.

Downloads

46

Readme


Motivation

Config files tend to grow.

Eventually there appears more and more specialized settings, more plugin imports and options for them, more local helpers and variables used once somewhere 300 lines below, more comments, and so on.

Left like that, config turns into leviathan, taking forever to figure it out and update something. Especially when the issue you want to address requires updating multiple config sections.

It's not hard at all to split config apart and merge that chunks. But anyway it's some extra complexity to care about – which nobody likes to bring.

This solution takes away that low-level logic from your sources.

Table of Contents

Installation

npm install -D vite-split-config
yarn add -D vite-split-config

Usage

Define chunks dedicated to certain configuration aspects:

// my-chunk.ts
import { defineChunk } from 'vite-split-config'
import checker from 'vite-plugin-checker'

export const useLint = defineChunk({
  plugins: [
    checker({
      typescript: true,
      eslint: { 
        lintCommand: '...' 
      },
      stylelint: { 
        lintCommand: '...' 
      },
    })
  ]
})
// my-other-chunk.ts
import { defineChunk } from 'vite-split-config'
import criticalCSS from 'rollup-plugin-critical'
import customSelectors from 'postcss-custom-selectors'

export const useStyles = defineChunk({
  css: {
    devSourcemap: true,
    postcss: {
      plugins: [
        customSelectors({
          /*...*/
        }),
      ]
    }
  },
  plugins: [
    criticalCSS({
      /*...*/
    }),
  ]
})

Then combine them together, and provide a basic config:

// vite.config.ts
import { useChunks } from 'vite-split-config'

import { useLint } from './my-chunk'
import { useStyles } from './my-other-chunk'

const defineConfig = useChunks([ useLint, useStyles ])

export default defineConfig({
  resolve: {
    alias: {/*...*/}
  },
  base: '/',
  /* other basic settings */
})

Chunks will be merged recursively, in order you specified in useChunks, starting with the basic config.

API

type ViteConfig = Vite.UserConfig | Promise<Vite.UserConfig>

type ExtendConfig<R> = (base: Vite.UserConfig, cfg: { env: NodeJS.ProcessEnv, vite: Vite.ConfigEnv }) => R

type Chunk = ExtendConfig<Promise<Vite.UserConfig>>

defineChunk

function defineChunk(config: ViteConfig): Chunk

function defineChunk(config: ExtendConfig<ViteConfig>): Chunk

function defineChunk(config: ExtendConfig<void | Promise<void>>): Chunk

// basic usage:
defineChunk({ /* Vite.UserConfig options here */ })

// async usage:
import { UserConfig } from 'vite'
import detectPort from 'detect-port'
defineChunk(new Promise<UserConfig>((resolve, reject) => {
    detectPort(3000, (err, freePort) => {
        if (err) reject(err)
        else resolve({
          server: { port: freePort },
        })
    })
}))

// depending on base config (can also return a promise):
defineChunk(base => ({
    define: { __APP_TYPE__: JSON.stringify(base.appType) }
}))

// depending on Vite env or process.env:
defineChunk((base, { env, vite }) => ({
    logLevel: vite.mode === 'test' ? 'silent' : 'info',
    appType: env.APP_TYPE,
}))

// imperative update:
defineChunk(base => {
    base.plugins.push(myPlugin())
    // don't need to return value explicitly
})

useChunks

function useChunks(chunks: Chunk[]): (base: Vite.UserConfigExport) => Vite.UserConfigFn

// vite.config.ts
const defineConfig = useChunks([ chunk1, chunk2, /* ... */ ])
export default defineConfig({ /* basic config */ })

Return value of useChunks is basically equivalent to vite.defineConfig function, so you may use it as drop-in replacement, with all the same features – defining conditional or async basic config.

The only difference is that it always returns a function – so that Vite will feed it with its env params, which then will be passed to every chunk.

useChunks.extend

const defineConfig = useChunks([chunk1, chunk2])
// somewhere else
const defineNewConfig = defineConfig.extend([ yetAnotherChunk, /* ... */ ])
defineNewConfig({ /* basic config */})

For complex distributed configs, extend method allows to append more chunks to already existing chain.

mergeConfig

Re-export of Vite's mergeConfig helper.

Hints

merging strategy

Configs are merged with Vite's mergeConfig helper.

It has one specific feature: if one of merged values is an array, then other value is added to that array. Like this:

mergeConfig({ a: [1] }, { a: 2 }) // => { a: [1, 2] }

Thus, you can't declaratively override a value in this case. But, the purpose of this tool is extension, not overriding. If some of your chunks are trying to specify different value for the same option, you're probably doing something wrong.

However, if you absolutely need to do override, you may use chunk callback definition and imperatively mutate parent config. See example in defineChunk section.

importing chunk modules

When importing local modules into vite.config, you may face complaints from your editor: It doesn't affect build in any way, but is annoying to see.

How to fix it is explained in warning itself: just include your files in tsconfig.node.json.

LICENSE

MIT