Параметр server.fs в конфигурации Vite управляет
доступом dev-сервера к файловой системе. Он определяет:
Механизм особенно важен в monorepo-структурах, при использовании симлинков, локальных пакетов, общих библиотек и нестандартной архитектуры проекта.
Конфигурация располагается внутри раздела server:
import { defineConfig } from 'vite'
export default defineConfig({
server: {
fs: {
}
}
})
Во время разработки Vite предоставляет браузеру доступ к исходным файлам напрямую. Без ограничений это создавало бы серьёзные проблемы безопасности:
.env;По этой причине Vite ограничивает область доступа файловой системы.
Если dev-сервер получает запрос к файлу вне разрешённой области, возвращается ошибка:
403 Restricted
или:
The request url is outside of Vite serving allow list
server.fsОсновные параметры:
server: {
fs: {
strict: true,
allow: [],
deny: []
}
}
strictВключает строгую проверку доступа к файловой системе.
allowСписок директорий, доступ к которым разрешён.
denyСписок запрещённых файлов и шаблонов.
server.fs.strictОпция определяет, должен ли Vite блокировать доступ к файлам вне рабочей области проекта.
Пример:
export default defineConfig({
server: {
fs: {
strict: true
}
}
})
strict: trueЭто значение используется по умолчанию.
Vite разрешает доступ только:
allow.Попытка получить файл вне разрешённых путей приводит к ошибке.
Например:
http://localhost:5173/@fs/C:/secret/config.txt
будет заблокирован.
strict: falseexport default defineConfig({
server: {
fs: {
strict: false
}
}
})
В этом режиме Vite перестаёт ограничивать файловую систему.
Dev-сервер получает доступ практически ко всем файлам, доступным процессу Node.js.
Это удобно:
Но подобная конфигурация считается небезопасной.
При strict: false становятся доступны:
Если dev-сервер случайно окажется доступным из сети, последствия могут быть критическими.
Поэтому отключение строгого режима допустимо только в контролируемой среде разработки.
server.fs.allowСвойство allow задаёт список директорий, доступ к
которым разрешён дополнительно.
Пример:
export default defineConfig({
server: {
fs: {
allow: ['..']
}
}
})
Частая ситуация — использование общей папки с библиотеками:
workspace/
├── shared/
├── frontend/
└── backend/
Если Vite запускается внутри frontend, доступ к
shared будет запрещён.
Решение:
import { defineConfig } from 'vite'
import path from 'path'
export default defineConfig({
server: {
fs: {
allow: [
path.resolve(__dirname, '../shared')
]
}
}
})
server: {
fs: {
allow: [
'/packages',
'/shared',
'/configs'
]
}
}
Наиболее надёжный вариант:
import path from 'path'
server: {
fs: {
allow: [
path.resolve(__dirname, '../shared')
]
}
}
searchForWorkspaceRootVite предоставляет встроенную функцию определения workspace-корня.
Пример:
import { defineConfig, searchForWorkspaceRoot } from 'vite'
export default defineConfig({
server: {
fs: {
allow: [
searchForWorkspaceRoot(process.cwd())
]
}
}
})
searchForWorkspaceRootФункция ищет признаки workspace:
package.json;pnpm-workspace.yaml;.git;lerna.json.После нахождения корневой директории она автоматически разрешается для доступа.
Это особенно полезно для:
repo/
├── apps/
│ └── frontend/
├── packages/
│ ├── ui/
│ └── core/
└── package.json
Если Vite работает внутри apps/frontend, пакеты из
packages могут блокироваться.
import { defineConfig } from 'vite'
import path from 'path'
export default defineConfig({
server: {
fs: {
allow: [
path.resolve(__dirname, '../. ./packages')
]
}
}
})
import { defineConfig, searchForWorkspaceRoot } from 'vite'
export default defineConfig({
server: {
fs: {
allow: [
searchForWorkspaceRoot(process.cwd())
]
}
}
})
server.fs.denyОпция deny запрещает доступ к определённым файлам и
шаблонам.
Даже если каталог разрешён через allow, файлы из
deny останутся недоступными.
export default defineConfig({
server: {
fs: {
deny: ['.env', '.env.*', '*.{crt,pem}']
}
}
})
По умолчанию Vite защищает:
.env;.env.*;*.crt;*.pem.Это предотвращает утечку:
server: {
fs: {
deny: [
'.secrets',
'*.key',
'*.sqlite'
]
}
}
/@fs//@fs/Vite использует специальный префикс:
/@fs/
Он позволяет обращаться к файлам напрямую через абсолютный путь.
Пример:
/@fs/C:/projects/shared/file.js
или:
/@fs/home/user/shared/file.js
При обращении через /@fs/ выполняются проверки:
deny;Если файл расположен вне allow-области:
403 Restricted
Node.js и Vite могут по-разному интерпретировать пути через symlink.
Например:
project/
└── node_modules/
└── shared -> ../. ./shared
Физически папка находится вне проекта.
Из-за этого Vite способен заблокировать доступ.
Нужно явно разрешить физическую директорию:
server: {
fs: {
allow: ['../. ./shared']
}
}
resolve.preserveSymlinksПри использовании симлинков иногда включают:
resolve: {
preserveSymlinks: true
}
Это меняет способ обработки путей модулей.
В сочетании с server.fs.allow позволяет корректно
подключать локальные пакеты.
host: trueКонфигурация:
server: {
host: true
}
делает dev-сервер доступным из локальной сети.
Если одновременно используется:
fs: {
strict: false
}
появляется риск удалённого доступа к файловой системе.
При неправильной настройке становится возможным:
http://ip:5173/@fs/C:/Users/admin/.ssh/id_rsa
или:
http://ip:5173/@fs/etc/passwd
export default defineConfig({
server: {
host: 'localhost',
fs: {
strict: true
}
}
})
import path from 'path'
export default defineConfig({
server: {
fs: {
allow: [
path.resolve(__dirname, '../shared-ui')
]
}
}
})
import { searchForWorkspaceRoot } from 'vite'
export default defineConfig({
server: {
fs: {
allow: [
searchForWorkspaceRoot(process.cwd())
]
}
}
})
export default defineConfig({
server: {
fs: {
deny: [
'.env',
'.env.production',
'*.pem',
'*.key'
]
}
}
})
resolveПлохо:
allow: ['../shared']
Лучше:
allow: [
path.resolve(__dirname, '../shared')
]
Опасно:
fs: {
strict: false
}
Особенно при:
host: true
Плохо:
allow: ['/']
или:
allow: ['C:/']
Это открывает доступ ко всему диску.
Если проект содержит:
их необходимо явно блокировать.
Оптимально оставить настройки по умолчанию:
server: {
fs: {
strict: true
}
}
Использовать:
searchForWorkspaceRoot(process.cwd())
или точечный allow.
Разрешать только конкретные директории:
allow: [
path.resolve(__dirname, '../packages/ui')
]
Дополнительно ограничивать:
deny: [
'*.pem',
'*.key',
'.env*'
]
import { defineConfig, searchForWorkspaceRoot } from 'vite'
import path from 'path'
export default defineConfig({
server: {
host: 'localhost',
fs: {
strict: true,
allow: [
searchForWorkspaceRoot(process.cwd()),
path.resolve(__dirname, '../shared')
],
deny: [
'.env',
'.env.*',
'*.pem',
'*.crt',
'*.key'
]
}
}
})