Lean vite-first dev plugin
TL;DR: Use @mbsks/rspfx-plugin-dev when you only need vite dev on Vite. It is lean, vite-first, and reuses @mbsks/rspfx-dev-runtime.
Use @mbsks/rspfx-plugin when you need build and package (rspfx build, rspfx package, vite build per-bundle, Rsbuild, Rspack) — it includes @rspack/core and framework integrations.
When to use which
| Need | Package | Import |
|---|---|---|
vite dev only (Vite) | @mbsks/rspfx-plugin-dev | rspfxViteDev / rspfxDevPlugin |
vite dev + rspfx build/package | @mbsks/rspfx-plugin | rspfxVite / rspfxRsbuild / RSpfxPlugin |
vite dev is primary — Vite handles HMR/serve, the plugin just adds /temp/manifests.js, reload, and workbench URL via configureServer. rspfx dev is an optional CLI alternative using the same dev-runtime. Both carry RspfxConfig via RSPFX_PLUGIN_MARKER (@mbsks/rspfx-core:68) and can be discovered by rspfx dev via jiti.
Fastest — rspfx dev:vite (auto-generates this config)
In any existing SPFx project, run rspfx dev:vite and the CLI does the install and vite.config.ts for you.
See docs/guide/dev-vite.md and docs/reference/commands.md#rspfx-devvite.
npx @mbsks/rspfx-cli dev:vite --dry-run
npx @mbsks/rspfx-cli dev:viteIt detects spfxVersion/framework/tsconfig.json, sets type: module, adds @mbsks/rspfx-plugin-dev + vite, and writes:
import { defineConfig } from 'vite';
import { rspfxViteDev } from '@mbsks/rspfx-plugin-dev/vite';
export default defineConfig({ plugins: [rspfxViteDev({ name: 'my-app', framework: 'react', spfxVersion: '1.24' })] });Manual install (vite-first)
npm i -D @mbsks/rspfx-plugin-dev @mbsks/rspfx-clivite is a peer optional (^5 || ^6 || ^7 || ^8). react, sass, @fluentui/react, and framework packages are also peer optional — rspfxDevPlugin loads the framework preset dynamically and warns when absent, so framework: 'react' works without react installed (fast refresh degrades gracefully).
vite.config.ts (manual)
import { defineConfig } from 'vite';
import { rspfxDevPlugin } from '@mbsks/rspfx-plugin-dev';
// alias: rspfxViteDev, or subpath import '@mbsks/rspfx-plugin-dev/vite'
export default defineConfig({
plugins: [rspfxDevPlugin({ name: 'my-app', framework: 'react', spfxVersion: '1.24' })],
});Options are RspfxPluginOptions (packages/plugin-dev/src/types.ts:3): name, framework, spfxVersion, dev, paths, projectRoot, etc. — same shape as the full plugin.
What it does
rspfxViteDev / rspfxDevPlugin hooks config + configureServer (packages/plugin-dev/src/vite.ts:110) — Vite owns the server/HMR, the plugin augments it:
configreturnsserver.host/port/httpsfromresolveServeSettings(packages/dev-runtime/src/serve.ts:60) + certs (ensureCertificatesin~/.rspfx/certswhenmode === 'sharepoint'andhttps), andesbuild.tsconfigRawfallback whentsconfig.jsonextends missing@microsoft/rush-stack-compilerbase;configureServerresolves project (readProject), serve settings (resolveServeSettings), and mode (resolveServeMode);- ensures certs lazily when
mode === 'sharepoint'andhttps(already ensured inconfig); - loads the framework preset dynamically (
loadFrameworkPreset) — peer optional; - creates
createManifestRegenerator+createReloadControllerand serves/temp/manifests.jsand/__rspfx_hot.jsonviamiddlewares.use; - ticks
reloadafter regeneration (poll →location.reload()); debounces watcherchange/add/unlinkat 250 ms.
No bundler build, no @rspack/core, no sass, no emitted dist/ bundles beyond what Vite itself builds.
mode === 'local' (no tenantDomain/tenantUrl) forces https: false (packages/dev-runtime/src/serve.ts:131) — certs only for sharepoint (packages/plugin-dev/src/vite.ts:122).
Tsconfig with extends: @microsoft/rush-stack-compiler and missing base (node_modules/@microsoft/rush-stack-compiler-*/includes/base.json) is stubbed and esbuild.tsconfigRaw fallback applied — run rspfx migrate to rewrite to plain tsconfig.json (packages/templates/src/index.ts:223).
Requires Node >=20.0.0 (package.json:8), Vite ^5 || ^6 || ^7 || ^8 peer — Node 14 and Vite 8 on Node 14 are unsupported; rspfx doctor warns (apps/cli/src/commands/doctor.ts:159).
vite.config.ts with ESM import/export default and package.json without "type": "module" warns with Vite 8 configLoader: 'native' (ESM syntax in a file loaded as CommonJS) — rename to vite.config.mts/vite.config.mjs or add "type": "module".
Shared build helpers
@mbsks/rspfx-build-core (packages/build-core/src/index.ts:1) holds the lean helpers both plugins share:
amd.ts—amdName,computeUniqueName,cacheVersionHashexternals.ts—collectExternals,platformOnlyExternaldefines.ts—createDefineMap,ALLOWED_DEFINE_KEYScss.ts—hasPostcssConfig,inlineStyleCodeoutput.ts—createSpfxOutput,SPFX_PUBLIC_PATH_SENTINEL
Zero heavy deps (@mbsks/rspfx-core, @mbsks/rspfx-diagnostics, @mbsks/rspfx-manifest-generator, @mbsks/rspfx-plugin-api only).
Extensibility
plugin-dev is the vite-first reference for a minimal dev plugin. The same pattern extends to Rsbuild/Rspack:
- implement
configureServer(Vite) orsetup(api)withonBeforeStartDevServer/onAfterStartDevServer(Rsbuild) /apply(compiler)(Rspack); - reuse
readProject,resolveServeSettings,createManifestRegenerator,createReloadController,buildWorkbenchUrlfrom@mbsks/rspfx-dev-runtime; - keep
vite/@rsbuild/core/@rspack/coreas peer optional.
Contributions welcome — open an issue with your bundler target.
Switching to the full plugin
When you need rspfx build/rspfx package (vite build alone does not generate manifests.js/.sppkg):
npm i -D @mbsks/rspfx-plugin @mbsks/rspfx-cli