DEV Community

Matthias Hryniszak
Matthias Hryniszak

Posted on

Vite config reuse

Have you ever wondered how big a Vite configuration file can get? What if you have a project with tens of workspaces? If any of the issues sound familiar - read on! There's something cool coming your way!

Writing reusable Vite configurations

As luck would have it, there is a function exported right from the vite package called mergeConfig(). It takes 2 arguments, essentially 2 fragments of Vite configuration and merges them together.

Based on this we can create a base configuration to use for all our projects. For example, I like all my vite-based projects to have eslint enabled. Here's how you would define it:

/**
 * @param {import('vite').UserConfig} overrides
 */
export function defineBaseConfig(overrides = {}) {
  const config = {
    plugins: [
      eslint({
        lintOnStart: false,
      }),
    ],
  }

  return mergeConfig(config, overrides)
}
Enter fullscreen mode Exit fullscreen mode

Now, instead of importing defineConfig from vite you would import this function and define all your other configuration options (besides the eslint plugin) as usual.

All things being equal, here is how you could combine multiple functions to essentially build building blocks of configuration:

/**
 * @param {import('vite').UserConfig} overrides
 */
export function defineTestConfig(overrides) {
  const config = {
    test: {
      setupFiles: [
        './vitest.setup.js',
      ],
      coverage: {
        enabled: true,
        reporter: ['text', 'lcov'],
      },
    },
  }

  return mergeConfig(config, overrides)
}

/**
 * @param {import('vite').UserConfig} overrides
 */
export function defineDefaultConfig(overrides = {}) {
  return defineBaseConfig(defineTestConfig(overrides))
}
Enter fullscreen mode Exit fullscreen mode

Now, whenever you need a Vite-based project with eslint and vitest all you need to do is to use the defineDefaultConifg(), create the vitest.setup.js in your main project and your configuration is done.

Ready-made configurations for you to use

I'm a lazy man. Extremely lazy. I hate repeating myself. That's why I created those 4 packages that I can later on use in my projects:

@padcom/vite-config-default - for use in other configurations

@padcom/vite-config-lib - for use in TypeScript libraries

@padcom/vite-config-vue - for use in Vue.js applications

@padcom/vite-config-vue-lib - for use in Vue.js libraries written in TypeScript

They are written in plain JavaScript. You can easily navigate to their implementation in vscode to see what is being configured and how. The main thing that you might find odd is those configurations make use of the contents of your package.json for a lot of things. That's why the first parameter is the package.json imported like so:

import pkg from './package.json' with { type: 'json }
Enter fullscreen mode Exit fullscreen mode

And then if you need a Vue.js library then simply:

import { defineVueLibConfig } from '@padcom/vite-config-vue-lib'
import pkg from './package.json' with { type: 'json' }

export default defineVueLibConfig(pkg)
Enter fullscreen mode Exit fullscreen mode

That's all! Isn't it nice?

So is that really all I need to do?

For Vite - yes. For your library - there is a little bit more to it, and it not because of vite, but because you're doing a library that exports things.

First of all, you need a proper exports definition for your library. The final build will reside in the dist folder and will contain the following files, assuming your project's name property is set to shiny-components:

{
  "name": "shiny-components",
  "type": "module",
  "files": ["dist", "README.md"],
  "exports": {
    ".": {
      "require": "./dist/shiny-components.umd.cjs",
      "import": "./dist/shiny-components.js",
      "types": "./dist/types.d.ts"
    },
    "./dist/style.css": "./dist/style.css"
  },
  "dependencies": {
    "vue": "^3"
  },
  "devDependencies": {
    "@padcom/vite-config-vue-lib": "^0.2.0",
    "typescript": "5.1.6",
    "vite": "^5.2.10",
    "vitest": "^1.5.2"
  }
}
Enter fullscreen mode Exit fullscreen mode

Please note, that each library you want your library to import but not bundle needs to be declared in dependencies. Likewise, if you want your library to bundle another library then put it into devDependencies. That is the reason why the pkg needs to be passed on to defineVueLibConfig()

And that is really all there is to it! Have fun creating your own configurations or using mine. Let me know how it made your projects more maintainable :)

Have a nice day!

Top comments (0)