Replies: 5 comments
-
|
You can achieve this in two main ways depending on whether you want to catch it during linting (which is the standard, fastest approach) or directly during the Vite build/dev process. Option 1: The Linting Approach // eslint.config.js (Flat Config) export default [ Option 2: The Vite Plugin Approach import { defineConfig } from 'vite'; function restrictDependenciesPlugin() { return { }; export default defineConfig({ |
Beta Was this translation helpful? Give feedback.
-
|
To enforce that only production dependencies (listed in 1. ESLint (Recommended & Industry Standard)The standard way to restrict imports is using ESLint with You can configure it in your // eslint.config.js
import importPlugin from 'eslint-plugin-import';
export default [
{
plugins: {
import: importPlugin
},
rules: {
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: [
'**/*.test.ts',
'**/*.spec.ts',
'vite.config.ts',
'vitest.config.ts'
],
optionalDependencies: false,
peerDependencies: false
}
]
}
}
];2. Custom Vite Build-Time PluginIf you want the Vite build itself to fail immediately upon encountering a forbidden import, you can write a simple custom Vite resolver plugin: // vite.config.ts
import { defineConfig } from 'vite';
import { readFileSync } from 'fs';
import { resolve } from 'path';
function restrictImportsPlugin() {
const pkg = JSON.parse(readFileSync(resolve(process.cwd(), 'package.json'), 'utf-8'));
const allowedImports = new Set([
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
]);
return {
name: 'vite-plugin-restrict-imports',
resolveId(source, importer) {
// Ignore relative, absolute, and virtual module paths
if (source.startsWith('.') || source.startsWith('/') || source.startsWith('\\') || source.includes('\x00')) {
return null;
}
// Extract root package name (e.g., "lodash/map" -> "lodash")
const match = source.match(/^([^@/]+|@[^/]+/[^/]+)/);
const pkgName = match ? match[1] : source;
// Allow node built-ins
if (pkgName.startsWith('node:') || ['fs', 'path', 'os', 'crypto'].includes(pkgName)) {
return null;
}
if (!allowedImports.has(pkgName)) {
throw new Error(
`Forbidden import: "${source}" is imported in ${importer} but is not listed in package.json dependencies.`
);
}
return null;
}
};
}
export default defineConfig({
plugins: [restrictImportsPlugin()]
}); |
Beta Was this translation helpful? Give feedback.
-
|
Vite itself doesn't distinguish between For example, This keeps the check explicit and catches violations early without affecting Vite's module resolution. |
Beta Was this translation helpful? Give feedback.
-
|
There's no built-in Vite option for this, but it's a few lines as a small plugin. A // vite.config.js
import { readFileSync } from 'node:fs'
import { builtinModules } from 'node:module'
const pkg = JSON.parse(readFileSync('./package.json', 'utf-8'))
const allowed = new Set(Object.keys(pkg.dependencies || {}))
const builtins = new Set([
...builtinModules,
...builtinModules.map((m) => 'node:' + m),
])
const isBare = (id) => !id.startsWith('.') && !id.startsWith('/') && !id.startsWith('\0')
const pkgNameOf = (id) => {
const p = id.split('/')
return id.startsWith('@') ? p.slice(0, 2).join('/') : p[0]
}
function allowlistDeps() {
return {
name: 'allowlist-deps',
enforce: 'pre',
resolveId(source) {
// skip relative/absolute, virtual ids and `pkg:`-style ids
if (!isBare(source) || source.includes(':')) return null
const name = pkgNameOf(source)
// allow node builtins and vite's own internal imports
if (builtins.has(name) || name === 'vite') return null
if (!allowed.has(name)) {
throw new Error(
`[allowlist-deps] Import of "${source}" is not allowed. ` +
`"${name}" is not listed in "dependencies" of package.json.`
)
}
return null // let Vite resolve it normally
},
}
}
export default { plugins: [allowlistDeps()] }This gives you exactly the "only allow modules in A couple of notes from testing this on Vite 8:
|
Beta Was this translation helpful? Give feedback.
-
|
Control module pre-bundling in Vite: export default defineConfig({
optimizeDeps: {
include: ['lodash-es', 'heavy-pkg'], // force prebundle
exclude: ['your-local-linked-pkg'], // skip prebundle
},
ssr: {
noExternal: ['package-that-must-be-bundled'],
external: ['native-only-module'],
},
})Use |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
To prevent importing project tools from node_modules, I would like to only allow modules defined in
dependencies, or disallow any modules defined indevDependencies. How should I achieve that?Beta Was this translation helpful? Give feedback.
All reactions