Shared Vue components without duplicate runtimes
A focused look at external dependencies: what external and peerDependencies mean, how ES and UMD resolve runtimes, and how to verify the intended Vue boundary.
- Vue 3
- Vite
- Component libraries
- Build tooling
Related project: Shared business component library. This article focuses on runtime dependency boundaries using the project’s Vite 4 setup.
Two different acceptance checks
A feedback or payment component working in its own development page proves that the local environment provides its dependencies. Another host may use different runtime versions, resource loading or global styles.
Delivery therefore includes the entry point, runtime assumptions, props/events, styles and build version.
External dependencies are not automatically available
The project externalizes Vue and ant-design-vue and builds individual component entries. A reduced configuration is:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
lib: {
entry: 'src/entry.ts',
name: 'BusinessWidgets',
formats: ['es', 'umd'],
fileName: format => `widgets.${format}.js`,
},
rollupOptions: {
external: ['vue', 'ant-design-vue'],
output: {
globals: {
vue: 'Vue',
'ant-design-vue': 'antd',
},
},
},
},
})
External modules stay out of the library bundle. UMD globals identify the objects supplied by the host; see Vite 4 Library Mode.
ES consumers must resolve external imports through their build or browser module mapping. UMD consumers must provide the expected globals before loading the library. A peer dependency does not create a browser global, and a remote ES import containing bare module names still needs resolution.
Externalize deliberately
The current configuration externalizes Vue and ant-design-vue. Other packages appearing in the repository are not evidence that router or i18n has also been externalized.
Duplicated runtimes may create additional size and integration problems, but “two copies always fail” is too broad. State supported versions and test plugin, injection, instance and style behavior in the actual host.
Verify that the host really supplies the runtime
A development page may work because an unrelated script has already injected dependencies. Use a minimal host that explicitly provides Vue and the UI library before loading the component.
Inspect external imports, UMD parameters and build analysis to verify the intended runtime was not embedded again. Test plugin installation, cross-component provide/inject behavior and teardown, rather than only rendering a static button.
Declare supported versions and exercise representative hosts. Changing a peer-dependency range does not make incompatible APIs compatible.
Two misconceptions
Externalizing a module does not make it directly loadable over the network: the host must still resolve bare imports or supply globals.
Nor is externalizing everything automatically better. Runtime sharing, host availability and version requirements matter alongside bundle size.
Styles, caching and release rollback are separate delivery problems and deserve separate designs and tests.