Подобно этому вопросу, ссылаясь на рабочие пространства Yarn, у меня есть следующая структура рабочего пространства npm:
package.json // root
packages
@myscope/a
package.json
tsconfig.json
@myscope/b
package.json
tsconfig.json
@myscope/c
package.json
tsconfig.json
Эти пакеты упоминаются в корневом пакете JSON следующим образом:
{
"workspaces": [
"packages/*",
],
}
@myscope/c
зависит от @myscope/b
, а @myscope/b
зависит от @myscope/a
.
У каждого пакета есть своя команда сборки и своя tsconfig.json
:
{
"build": "tsc --build --verbose tsconfig.json",
}
Команда tsc
создает типы, а также JS, которые имеют решающее значение для работы импорта при разработке с использованием локальных пакетов. Я мог бы переключить эти команды на vite.config.ts
, который создает JS->TS, но типы не создаются. Я знаю, что могу использовать vite-plugin-dts для этой цели.
Если я запускаю @myscope/c
со следующей командой из папки @myscope/c
:
npx vite serve --mode=development --config vite.config.ts
Я создал пример репозитория, демонстрирующий макет. Внутри него запуск @myscope/c
с Vite не будет перестраивать @myscope/b
или @myscope/a
, когда они изменяются, несмотря на то, что preserveSymlinks
включен в мой vite.config.ts.
...
resolve: {
preserveSymlinks: true // this is the fix from yargs question
}
})
Как мне заставить команду @myscope/c
vite пересобирать @myscope/a
и @myscope/b
при их изменении?
Нужно ли мне реализовать vite.config.ts для @myscope/a
и @myscope/b
?
Ответ для рабочих пространств пряжи, preserveSymlinks
, не работает для рабочих пространств npm.
Мне пришлось написать плагин Vite для просмотра пакетов локального рабочего пространства npm и последующей обработки обновлений этих файлов.
Суть плагина такова:
export const VitePluginWatchWorkspace = async (config: VitePluginWatchExternalOptions): Promise<Plugin<any>> => {
// get a list of external files you want to watch
const externalFiles = await getExternalFileLists()
return {
name: 'vite-plugin-watch-workspace',
// on build start, add the external files to Vite's watch list
async buildStart() {
Object.keys(externalFiles).map((file) => {
this.addWatchFile(file)
})
},
// when the external files change, rebuild them with esbuild
async handleHotUpdate({ file, server }) {
log(`File', ${file}`)
const tsconfigPath = externalFiles[file]
if (!tsconfigPath) {
log(`tsconfigPath not found for file ${file}`)
return
}
const tsconfig = getTsConfigFollowExtends(tsconfigPath)
const fileExtension = path.extname(file)
const loader = getLoader(fileExtension)
const outdir = getOutDir(file, tsconfig)
const outfile = getOutFile(outdir, file, fileExtension)
log(`Outfile ${outfile}, loader ${loader}`)
const buildResult = await build({
tsconfig: tsconfigPath,
stdin: {
contents: fs.readFileSync(file, 'utf8'),
loader,
resolveDir: path.dirname(file),
},
outfile,
platform: config.format === 'cjs' ? 'node' : 'neutral',
format: config.format || 'esm',
})
log(`buildResult', ${JSON.stringify(buildResult)}`)
// tell the server that the file has updated
server.ws.send({
type: 'update',
updates: [
{
acceptedPath: file,
type: 'js-update',
path: file,
timestamp: Date.now(),
},
],
})
},
}
}
Вы можете скачать плагин здесь и просмотреть исходный код здесь.